### Minimal Configuration Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md A zero-configuration example using `Bypass::open()` which utilizes all default settings. Demonstrates basic route addition and retrieving the base URL. ```php use Ciareis\Bypass\Bypass; // Zero-config - everything uses defaults $bypass = Bypass::open(); $bypass->addRoute('GET', '/api/test', 200, 'OK'); echo $bypass->getBaseUrl(); // http://localhost:RANDOM_PORT ``` -------------------------------- ### Ensuring Server is Started Before Use Source: https://github.com/ciareis/bypass/blob/main/_autodocs/errors.md Illustrates the correct order of operations: starting the Bypass server with `Bypass::open()` before calling methods like `getPort()` to avoid errors. ```php $bypass = Bypass::open(); // Start the server first $port = $bypass->getPort(); // Now safe to call // Wrong order - would fail: // $port = $bypass->getPort(); // RuntimeException // $bypass = Bypass::open(); ``` -------------------------------- ### Minimal Server Setup Source: https://github.com/ciareis/bypass/blob/main/_autodocs/README.md Opens a Bypass server and retrieves its base URL. Useful for basic server initialization. ```php $bypass = Bypass::open(); $url = $bypass->getBaseUrl(); ``` -------------------------------- ### Initializing Bypass in Test Setup Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass-service-provider.md Shows how to initialize the Bypass instance in the `setUp()` method of a Laravel TestCase to make it available across multiple test methods. ```php protected function setUp(): void { parent::setUp(); $this->bypass = app(Bypass::class); } ``` -------------------------------- ### Route Instance Creation Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Example of instantiating the Route class with specific parameters for method, URI, status, body, times, and headers. ```php use Ciareis\Bypass\Route; $route = new Route( method: 'GET', uri: '/users/1', status: 200, body: ['id' => 1, 'name' => 'Alice'], times: 1, headers: ['X-Custom' => 'value'] ); ``` -------------------------------- ### Multi-Value Header Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Shows how to define a multi-value HTTP header, such as for 'Set-Cookie'. ```php [ 'Set-Cookie' => [ 'session=abc123', 'user=john', 'preferences=dark' ] ] ``` -------------------------------- ### Serve Routes with Bypass Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Starts a Bypass server configured with one or more predefined routes. This is useful for setting up mock servers quickly. ```php // Single serve $bypass = Bypass::serve( Route::ok(uri: '/users') ); // Multiple routes $bypass = Bypass::serve( Route::ok(uri: '/users'), Route::created(uri: '/users'), Route::notFound(uri: '/missing'), Route::serverError(uri: '/error') ); ``` -------------------------------- ### Open Bypass Server using Bypass::up() Source: https://github.com/ciareis/bypass/blob/main/README.md Use Bypass::up() as an alias for Bypass::open() to start a new server instance. ```php //Same as Bypass::open() $bypass = Bypass::up(); ``` -------------------------------- ### Route Response Times Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Provides examples of using the 'times' parameter to control route responses: once (default), twice for retries, zero to assert not called, and multiple times. ```php // Called once $bypass->addRoute('GET', '/api/data', 200, times: 1); // Called twice (test retry logic) $bypass->addRoute('GET', '/api/unstable', 500, times: 2); // Called 0 times (assert not called) $bypass->addRoute('GET', '/api/deprecated', 200, times: 0); // Multiple calls $bypass->addRoute('GET', '/api/poll', 200, times: 5); ``` -------------------------------- ### Install Bypass with Composer Source: https://github.com/ciareis/bypass/blob/main/README.md Install Bypass as a development dependency using Composer. ```bash composer require --dev ciareis/bypass ``` -------------------------------- ### Opening Bypass with Port Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Shows how to open a Bypass instance, either with an auto-assigned random port (0) or a specific fixed port. ```php Bypass::open(0) // Auto-assign random port Bypass::open(8080) // Fixed port 8080 Bypass::open(3000) // Fixed port 3000 ``` -------------------------------- ### Parallel Test Configuration Pattern Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md Ensure each test gets its own Bypass instance with a random port by initializing it within the `setUp()` method. This prevents port conflicts in parallel test runs. ```php // Each test gets its own instance with random port protected function setUp(): void { parent::setUp(); $this->bypass = Bypass::open(); // Random port - no conflicts } ``` -------------------------------- ### Quick Start: Open Server, Add Route, and Test Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md This snippet demonstrates the basic workflow of using Bypass: opening a server instance, registering a route with a specific method, URI, status code, and response body, and then making a request to the mock server using an HTTP client and asserting the response. ```php use Ciareis\Bypass\Bypass; // Open server $bypass = Bypass::open(); // Register route $bypass->addRoute('GET', '/api/data', 200, ['result' => 'success']); // Use in test $client = new GuzzleHttp\Client(); $response = $client->get($bypass->getBaseUrl() . '/api/data'); // Assert assert($response->getStatusCode() === 200); $bypass->assertRoutes(); ``` -------------------------------- ### Single-Value Header Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Illustrates how to define a single-value HTTP header. ```php ['X-Custom-Header' => 'single-value'] ``` -------------------------------- ### URI Syntax Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Illustrates various ways to define URIs for routes, including standard paths, paths with automatic slash addition, paths with IDs, and paths with query strings. ```php '/api/users' // Standard path 'v1/data' // Slash added automatically '/api/users/123' // With ID '/api/users?filter=admin' // With query string '/api/v1/users?id=1&sort=name' // Complex query ``` -------------------------------- ### Serving Multiple Routes Source: https://github.com/ciareis/bypass/blob/main/_autodocs/README.md Starts a Bypass server configured with multiple predefined routes using Route helper methods. ```php $bypass = Bypass::serve( Route::ok(uri: '/users'), Route::notFound(uri: '/missing') ); ``` -------------------------------- ### Alternative Bypass Server Entry Points Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md Presents alternative methods for starting a Bypass server: `up()` as an alias for `open()`, `serve()` for initializing with routes, and obtaining an instance via Laravel's service container. ```php // Alias for open() $bypass = Bypass::up(); // Open and register routes in one step $bypass = Bypass::serve($route1, $route2); // Laravel service container $bypass = app(Bypass::class); ``` -------------------------------- ### get() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Creates a GET request route with a specified status code and response body. Defaults to a 200 OK status. ```APIDOC ## get() ### Description Creates a GET request route. ### Method Signature ```php public static function get( string $uri, null|string|array $body = null, int $status = 200, int $times = 1, array $headers = [], ): self ``` ### Parameters #### Path Parameters There are no path parameters for this method. #### Query Parameters There are no query parameters for this method. #### Request Body There are no explicit request body parameters defined for this method signature, but the `body` parameter can be used to set the response body. ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | uri | string | Yes | — | URI path. | | body | string\|array\|null | No | null | Response body. | | status | int | No | 200 | HTTP status code. | | times | int | No | 1 | Number of times callable. | | headers | array | No | [] | HTTP headers. | ### Example ```php $route = Route::get(uri: '/api/users', body: ['users' => []]); ``` ``` -------------------------------- ### Avoid Calling getPort() Before Server Start Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Warns against calling getPort() before the Bypass server has been started, as this will result in a RuntimeException. ```php // ❌ Don't call getPort() before opening server $port = $bypass->getPort(); // RuntimeException ``` -------------------------------- ### Mixed Headers Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Demonstrates defining an HTTP header set containing both single-value and multi-value headers. ```php [ 'Content-Type' => 'application/json', // Single value 'Set-Cookie' => ['session=abc', 'user=john'], // Multiple values 'Cache-Control' => 'no-cache', // Single value 'Accept' => ['application/json', 'text/html'] // Multiple values ] ``` -------------------------------- ### Getting Base URL with Path Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Demonstrates how to obtain the base URL, optionally appending a specific path. ```php $bypass->getBaseUrl(); // 'http://localhost:12345' $bypass->getBaseUrl('/api/users'); // 'http://localhost:12345/api/users' ``` -------------------------------- ### Serve Routes with Route Helpers Source: https://github.com/ciareis/bypass/blob/main/README.md Utilize `Bypass::serve` with `Route` helpers to quickly set up mock routes for common HTTP responses like OK (200) and Not Found (404). The server starts automatically on a random port. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; //Create and serve routes $bypass = Bypass::serve( Route::ok(uri: '/v1/demo/john', body: ['username' => 'john', 'name' => 'John Smith', 'total' => 1250]), //method GET, status 200 Route::notFound(uri: '/v1/demo/wally') //method GET, status 404 ); ``` -------------------------------- ### Opening a New Bypass Server Instance Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md This snippet shows the primary way to start a new Bypass server instance using the static `open()` method. ```php use Ciareis\Bypass\Bypass; // Opens a new server instance $bypass = Bypass::open(); ``` -------------------------------- ### Retry Server Startup on Timeout Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md Implement a retry mechanism to handle potential server startup timeouts. This example attempts to open Bypass up to three times with a one-second delay between retries. ```php $attempts = 0; while ($attempts < 3) { try { $bypass = Bypass::open(); break; } catch (RuntimeException $e) { if ($attempts < 2) { sleep(1); $attempts++; } else { throw $e; } } } ``` -------------------------------- ### Creating RouteFile with Route::getFile() Helper Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md Use the Route::getFile() static method for a shorthand to create a RouteFile, defaulting to the GET method. Specify the URI, file content, and optional headers. ```php $archiveContent = file_get_contents('backup.zip'); $route = Route::getFile( uri: '/backups/latest.zip', file: $archiveContent, headers: ['Content-Type' => 'application/zip'] ); ``` -------------------------------- ### Serve Multiple Routes at Once Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md Creates and serves multiple routes simultaneously using the `serve()` method. This is a convenience method that automatically starts the server and registers all provided routes. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; $bypass = Bypass::serve( Route::ok(uri: '/v1/users', body: ['id' => 1, 'name' => 'John']), Route::notFound(uri: '/v1/missing') ); echo $bypass->getBaseUrl(); // http://localhost:12345 ``` -------------------------------- ### Exception Message Format Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Provides examples of exception messages for various error conditions, including route assertion failures, invalid methods, invalid status codes, invalid ports, and server startup issues. ```php "Bypass expected route '/api/data' with method 'GET' to be called 2 times(s). Found 1 calls(s) instead." "Invalid HTTP method: INVALID. Valid methods are: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS" "Invalid HTTP status code: 600. Status code must be between 100 and 599." "Invalid port number. Port must be between 1 and 65535." "Failed to start PHP built-in server." "Server did not start within 5 seconds." ``` -------------------------------- ### Basic Bypass Server Usage Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md Demonstrates the fundamental steps of opening a Bypass server, registering a GET route for '/api/users' that returns a JSON array, obtaining the server's base URL, making a client request, and asserting that all registered routes were called. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; // 1. Create server $bypass = Bypass::open(); // 2. Register routes $bypass->addRoute('GET', '/api/users', 200, ['users' => []]); // 3. Use server URL in your code $url = $bypass->getBaseUrl(); $result = $client->get($url . '/api/users'); // 4. Assert expectations $bypass->assertRoutes(); ``` -------------------------------- ### Create GET Request Route Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md This is a shortcut method for creating a route that handles GET requests. It allows specifying the URI, an optional response body, an HTTP status code, and the number of times the route can be called. ```php public static function get( string $uri, null|string|array $body = null, int $status = 200, int $times = 1, array $headers = [], ): self ``` ```php $route = Route::get(uri: '/api/users', body: ['users' => []]); ``` -------------------------------- ### Route to Array Conversion Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Demonstrates converting a Route object into its array representation, showing how data like JSON bodies are encoded. ```php $route = Route::ok( uri: '/api/users', body: ['users' => []], times: 2, headers: ['X-Total-Count' => '0'] ); $array = $route->toArray(); // Result: // [ // 'method' => 'GET', // 'uri' => '/api/users', // 'status' => 200, // 'body' => '{"users":[]}', // Arrays are JSON-encoded // 'times' => 2, // 'headers' => ['X-Total-Count' => '0'] // ] ``` -------------------------------- ### Bypass::open() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md Opens a new Bypass server instance. It can start a server on a specific port or a random available port if none is provided. This is the primary method for initializing the mock server. ```APIDOC ## Bypass::open() ### Description Opens a new Bypass server instance. It can start a server on a specific port or a random available port if none is provided. This is the primary method for initializing the mock server. ### Method `public static function open(?int $port = null): self` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **port** (int|null) - Optional - Description: Optional port number. If null or 0, a random available port will be used. Must be between 1-65535. ### Returns `self` - A new Bypass instance with the server started. ### Throws `RuntimeException` - If the server fails to start or if an invalid port is provided. ### Example ```php use Ciareis\Bypass\Bypass; // Open with random port $bypass = Bypass::open(); // Open with specific port $bypass = Bypass::open(8081); ``` ``` -------------------------------- ### Bypass::serve() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md Creates and serves multiple routes at once. This convenience method automatically opens a server and registers all provided routes, simplifying the setup for multiple predefined responses. ```APIDOC ## Bypass::serve() ### Description Creates and serves multiple routes at once. This convenience method automatically opens a server and registers all provided routes, simplifying the setup for multiple predefined responses. ### Method `public static function serve(...$routes): self` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **routes** (Route|RouteFile|array) - Yes - Description: Variable number of Route objects, RouteFile objects, or array configurations. Can also pass a single array of routes. ### Returns `self` - A new Bypass instance with all routes registered. ### Throws `RuntimeException` - If the server fails to start. ### Example ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; $bypass = Bypass::serve( Route::ok(uri: '/v1/users', body: ['id' => 1, 'name' => 'John']), Route::notFound(uri: '/v1/missing') ); echo $bypass->getBaseUrl(); // http://localhost:12345 ``` ``` -------------------------------- ### Create a GET file route Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Use getFile to create a route that returns binary content. You can specify the URI, file content, status code, number of times it should be called, and headers. ```php public static function getFile( string $uri, string $file, int $status = 200, int $times = 1, array $headers = [], ): RouteFile ``` ```php $imageContent = file_get_contents('logo.png'); $route = Route::getFile( uri: '/images/logo.png', file: $imageContent, headers: ['Content-Type' => 'image/png'] ); ``` -------------------------------- ### Conditional Configuration Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md Conditionally open Bypass on a specific port if the `BYPASS_PORT` environment variable is set, otherwise use a random port. ```php $port = getenv('BYPASS_PORT'); if ($port) { $bypass = Bypass::open((int) $port); } else { $bypass = Bypass::open(); // Random port } ``` -------------------------------- ### Bypass URL Format Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Shows different formats for Bypass URLs, including the base URL and URLs with paths and IDs. ```php 'http://localhost:8080' // Base URL 'http://localhost:8080/api/users' // With path 'http://localhost:8080/api/users/1' // With path and ID ``` -------------------------------- ### URI Format Examples Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Illustrates various formats for URIs, including absolute, relative, with IDs, and with query strings. Leading slashes are optional as Bypass adds them automatically. ```php '/api/users' // Absolute path 'v1/data' // Relative (slash added automatically) '/api/users/123' // With ID '/api/users?filter=admin' // With query string '/api/users/123?v=2' // ID and query string ``` -------------------------------- ### Adding File Response Routes Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md Illustrates how to add a route that serves a binary file. It reads the content of a local file ('document.pdf') and registers a GET route for '/downloads/document.pdf' that will return this file content. ```php $bypass = Bypass::open(); $pdfContent = file_get_contents('document.pdf'); $bypass->addFileRoute( method: 'GET', uri: '/downloads/document.pdf', file: $pdfContent ); ``` -------------------------------- ### getFile() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Creates a GET file route that returns binary content. This method is used to define a route that serves a specific file as its response. ```APIDOC ## GET /:uri ### Description Creates a GET file route that returns binary content. Returns a `RouteFile` instance. ### Method GET ### Endpoint /:uri ### Parameters #### Path Parameters - **uri** (string) - Required - URI path. - **file** (string) - Required - Binary file content. #### Query Parameters - **status** (int) - Optional - Default: 200 - HTTP status code. - **times** (int) - Optional - Default: 1 - Number of times callable. #### Headers - **headers** (array) - Optional - Default: [] - HTTP headers. ### Request Example ```php $imageContent = file_get_contents('logo.png'); $route = Route::getFile( uri: '/images/logo.png', file: $imageContent, headers: ['Content-Type' => 'image/png'] ); ``` ### Response #### Success Response (200) - **RouteFile** - A file route instance. #### Response Example ```php // Example of RouteFile instance (conceptual) // The actual returned object is an instance of RouteFile, not a direct array representation. // For detailed structure, refer to the RouteFile class documentation if available. { "type": "RouteFile", "uri": "/images/logo.png", "status": 200, "headers": {"Content-Type": "image/png"} } ``` ``` -------------------------------- ### Bypass: Open server with specific port or random port Source: https://github.com/ciareis/bypass/blob/main/README.md Shows how to start a Bypass server on a specific port, including error handling for port conflicts, or use a random port. ```php // Use random port (recommended) $bypass = Bypass::open(); // Or specify a port and handle errors try { $bypass = Bypass::open(8080); } catch (RuntimeException $e) { // Port might be in use, try another $bypass = Bypass::open(8081); } ``` -------------------------------- ### PHP Built-in Server Startup Failure Source: https://github.com/ciareis/bypass/blob/main/_autodocs/errors.md This error occurs when the PHP built-in server fails to start, often due to the PHP binary not being executable or issues with spawning child processes. ```php $bypass = Bypass::open(); // If PHP binary is not found or not executable: // RuntimeException: Failed to start PHP built-in server. ``` -------------------------------- ### Handling Multiple Routes with Different Expectations Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-not-called-exception.md This example shows how to manage and assert call counts for multiple routes with varying expectations within a single test. It's useful for complex scenarios involving multiple API interactions. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\RouteNotCalledException; $bypass = Bypass::open(); $bypass->addRoute('GET', '/api/users', 200, ['users' => []], times: 1); $bypass->addRoute('POST', '/api/users', 201, ['id' => 1], times: 1); $bypass->addRoute('GET', '/api/users/1', 200, ['id' => 1, 'name' => 'Alice'], times: 2); $service = new UserService(); $service->setBaseUrl($bypass->getBaseUrl()); // Perform multiple operations $users = $service->listUsers(); // GET /api/users once $user = $service->createUser('Alice'); // POST /api/users once $details = $service->getUser(1); // GET /api/users/1 twice try { $bypass->assertRoutes(); // All routes called exactly as expected } catch (RouteNotCalledException $e) { // One or more routes had unexpected call counts echo "Assertion failed: " . $e->getMessage(); } ``` -------------------------------- ### Get All Routes Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Retrieves all configured routes from the Bypass instance. Useful for debugging or inspecting the current route setup. ```php $routes = $bypass->getRoutes(); // Returns array of route configurations foreach ($routes as $route) { echo $route['method'] . ' ' . $route['uri']; } ``` -------------------------------- ### Server Port Not Set Error Source: https://github.com/ciareis/bypass/blob/main/_autodocs/errors.md This error occurs when attempting to get the server port or base URL before the server has successfully started, or if startup failed. ```php $bypass = new Bypass(); // Direct instantiation without open() // This throws RuntimeException $port = $bypass->getPort(); // RuntimeException: Server port is not set. Make sure the server has been started. // Also with getBaseUrl() $url = $bypass->getBaseUrl(); // RuntimeException: Server port is not set. Make sure the server has been started. ``` -------------------------------- ### Integration with Laravel Feature Tests Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass-service-provider.md Example of integrating Bypass into Laravel feature tests. It shows setting up a Bypass instance in `setUp`, adding routes, configuring external API URLs, and making assertions on the response. ```php use Ciareis\Bypass\Bypass; use Tests\TestCase; class ExternalApiFeatureTest extends TestCase { protected Bypass $bypass; protected function setUp(): void { parent::setUp(); $this->bypass = app(Bypass::class); } public function test_dashboard_loads_external_data(): void { $this->bypass->addRoute( 'GET', '/external/dashboard-data', 200, [ 'widgets' => [ ['id' => 1, 'title' => 'Sales'], ['id' => 2, 'title' => 'Users'], ] ] ); config(['services.external_api.url' => $this->bypass->getBaseUrl()]); $response = $this->get('/dashboard'); $response->assertStatus(200); $response->assertSee('Sales'); $response->assertSee('Users'); } } ``` -------------------------------- ### Using RouteFile with Bypass::serve() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md Demonstrates how to use RouteFile instances directly with the Bypass::serve() static method to set up multiple file routes. ```APIDOC ## Using RouteFile with Bypass::serve() ### Description Instances of `RouteFile` can be passed directly to the `Bypass::serve()` static method to configure multiple file routes simultaneously. This is a convenient way to set up a collection of file endpoints for testing. ### Method `Bypass::serve(RouteFile ...$routes) ` ### Parameters - **routes** (RouteFile) - A variable number of `RouteFile` objects to be served. ### Example ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\RouteFile; $pdfContent = file_get_contents('document.pdf'); $imageContent = file_get_contents('logo.png'); $bypass = Bypass::serve( new RouteFile( method: 'GET', uri: '/files/document.pdf', file: $pdfContent, headers: ['Content-Type' => 'application/pdf'] ), new RouteFile( method: 'GET', uri: '/images/logo.png', file: $imageContent, headers: ['Content-Type' => 'image/png'] ) ); $url = $bypass->getBaseUrl(); // Get the base URL for the running Bypass instance ``` ``` -------------------------------- ### Pest PHP: Test getting the logo Source: https://github.com/ciareis/bypass/blob/main/README.md Opens a Bypass server, defines a GET route for a file, and verifies the response. ```php use Ciareis\Bypass\Bypass; it('properly gets the logo', function () { //Opens a new Bypass server $bypass = Bypass::open(); //Reads the file $filePath = 'docs/img/logo.png'; $file = \file_get_contents($filePath); //Defines a route $bypass->addFileRoute(method: 'GET', uri: $filePath, status: 200, file: $file); //Configure your service to access Bypass URL $service = new LogoService(); $response = $service->setBaseUrl($bypass->getBaseUrl()) ->getLogo(); // asserts expect($response)->toEqual($file); }); ``` -------------------------------- ### Get Bypass Server URL Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Retrieves the base URL of the running Bypass server, optionally with a specified path. You can also get just the port number. ```php // Base URL $url = $bypass->getBaseUrl(); // http://localhost:12345 // With path $url = $bypass->getBaseUrl('/api/users'); // http://localhost:12345/api/users // Get port only $port = $bypass->getPort(); // 12345 ``` -------------------------------- ### Registering Routes with Route Helpers Source: https://github.com/ciareis/bypass/blob/main/_autodocs/OVERVIEW.md Shows how to use static factory methods from the Route class to define various types of responses (OK, Created, Not Found, Server Error) and pass them directly to the Bypass::serve() method for server initialization. ```php $bypass = Bypass::serve( Route::ok(uri: '/api/users'), Route::created(uri: '/api/users'), Route::notFound(uri: '/api/missing'), Route::serverError(uri: '/api/error') ); ``` -------------------------------- ### Get Bypass Server Port Source: https://github.com/ciareis/bypass/blob/main/README.md Retrieve the port number the Bypass server is listening on. ```php $bypassPort = $bypass->getPort(); //16819 ``` -------------------------------- ### Handling General Server Startup Errors Source: https://github.com/ciareis/bypass/blob/main/_autodocs/errors.md A comprehensive try-catch block to differentiate and handle various server startup issues, including invalid ports, general startup failures, and timeouts. ```php try { $bypass = Bypass::open(8080); } catch (RuntimeException $e) { if (strpos($e->getMessage(), 'Invalid port') !== false) { echo "Port error: " . $e->getMessage(); } elseif (strpos($e->getMessage(), 'Failed to start') !== false) { echo "Server startup failed: " . $e->getMessage(); } elseif (strpos($e->getMessage(), 'did not start within') !== false) { echo "Server timeout: " . $e->getMessage(); } } ``` -------------------------------- ### Get Bypass Server Base URL Source: https://github.com/ciareis/bypass/blob/main/README.md Retrieve the base URL of the running Bypass server. ```php $bypassUrl = $bypass->getBaseUrl(); //http://localhost:16819 ``` -------------------------------- ### Create Bypass Server with Routes Source: https://github.com/ciareis/bypass/blob/main/_autodocs/QUICK-REFERENCE.md Initializes a Bypass server instance with predefined routes. This is useful for setting up mock APIs for testing. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; // 1. Create server $bypass = Bypass::serve( Route::ok(uri: '/api/users', body: ['users' => []]), Route::notFound(uri: '/api/missing') ); ``` -------------------------------- ### Equivalent addRoute Configuration Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md Demonstrates the equivalent configuration using `addRoute` for the routes defined with `Bypass::serve()`. ```php $bypass = Bypass::open(); $bypass->addRoute('GET', '/users', 200); $bypass->addRoute('POST', '/users', 201); $bypass->addRoute('GET', '/missing', 404); $bypass->addRoute('GET', '/error', 500); ``` -------------------------------- ### Serving Multiple Files with Bypass::serve() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md Use Bypass::serve() to initialize Bypass with multiple RouteFile instances. Each instance defines a distinct file route with its specific content and headers. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\RouteFile; $pdfContent = file_get_contents('document.pdf'); $imageContent = file_get_contents('logo.png'); $bypass = Bypass::serve( new RouteFile( method: 'GET', uri: '/files/document.pdf', file: $pdfContent, headers: ['Content-Type' => 'application/pdf'] ), new RouteFile( method: 'GET', uri: '/images/logo.png', file: $imageContent, headers: ['Content-Type' => 'image/png'] ) ); $url = $bypass->getBaseUrl(); ``` -------------------------------- ### HTTP Method Case-Insensitivity Example Source: https://github.com/ciareis/bypass/blob/main/_autodocs/types.md Shows that Bypass accepts HTTP methods in various cases, converting them to uppercase internally. ```php $bypass->addRoute('get', '/test'); // OK - converted to GET $bypass->addRoute('Get', '/test'); // OK - converted to GET $bypass->addRoute('GET', '/test'); // OK $bypass->addRoute('invalid', '/test'); // Error - RuntimeException ``` -------------------------------- ### Route Constructor Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Initializes a new Route instance with specified HTTP method, URI, status, body, times, and headers. ```APIDOC ## Route Constructor ### Description Initializes a new Route instance with specified HTTP method, URI, status, body, times, and headers. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **method** (string) - Required - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS). Case-insensitive. - **uri** (string) - Required - URI path (e.g., '/v1/users' or 'v1/users'). Leading slash added automatically if missing. - **status** (int) - Required - HTTP status code (100-599). - **body** (string|array|null) - Optional - Response body. If array, will be JSON encoded when the route is used. Defaults to null. - **times** (int) - Optional - Number of times this route should respond. Defaults to 1. - **headers** (array) - Optional - HTTP headers. Values can be strings or arrays of strings for multiple values. Defaults to []. ### Request Example ```php use Ciareis\Bypass\Route; $route = new Route( method: 'GET', uri: '/users/1', status: 200, body: ['id' => 1, 'name' => 'Alice'], times: 1, headers: ['X-Custom' => 'value'] ); ``` ``` -------------------------------- ### PHPUnit: Test total score by username Source: https://github.com/ciareis/bypass/blob/main/README.md Opens a Bypass server, defines a GET route for user scores, and asserts the response. ```php use Ciareis\Bypass\Bypass; class BypassTest extends TestCase { public function test_total_score_by_username(): void { //Opens a new Bypass server $bypass = Bypass::open(); //Json body $body = '{"games":[{"id":1,"name":"game 1","points":25},{"id":2,"name":"game 2","points":10}],"is_active":true}'; //Defines a route $bypass->addRoute(method: 'GET', uri: '/v1/score/johndoe', status: 200, body: $body); //Configure your service to access Bypass URL $service = new TotalScoreService(); $response = $service ->setBaseUrl($bypass->getBaseUrl()) ->getTotalScoreByUsername('johndoe'); //Verifies that response is 35 $this->assertSame(35, $response); } public function test_gets_logo(): void { //Opens a new Bypass server $bypass = Bypass::open(); //Reads the file $filePath = 'docs/img/logo.png'; $file = \file_get_contents($filePath); //Defines a route $bypass->addFileRoute(method: 'GET', uri: $filePath, status: 200, file: $file); //Configure your service to access Bypass URL $service = new LogoService(); $response = $service->setBaseUrl($bypass->getBaseUrl()) ->getLogo(); $this->assertSame($response, $file); } } ``` -------------------------------- ### Direct Instantiation of Bypass Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass-service-provider.md Illustrates how to directly instantiate the Bypass class without using the service provider, useful for standalone usage. ```php use Ciareis\Bypass\Bypass; $bypass = Bypass::open(); $bypass->addRoute('GET', '/test', 200); ``` -------------------------------- ### Get all registered routes with getRoutes() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md Use getRoutes() to retrieve all configured routes. The returned array contains detailed configuration for each route. ```php public function getRoutes(): array ``` ```php $bypass = Bypass::open(); $bypass->addRoute('GET', '/test', 200, 'OK'); $bypass->addRoute('POST', '/create', 201, 'Created'); $routes = $bypass->getRoutes(); // [ // [ // 'method' => 'GET', // 'uri' => '/test', // 'status' => 200, // 'body' => 'OK', // 'times' => 1, // 'headers' => [] // ], // [ // 'method' => 'POST', // 'uri' => '/create', // 'status' => 201, // 'body' => 'Created', // 'times' => 1, // 'headers' => [] // ] // ] ``` -------------------------------- ### Route::file() Helper Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md A convenience static method on the Route class to create a RouteFile instance for GET requests serving files. ```APIDOC ## Route::file() ### Description A static helper method provided by the `Route` class to simplify the creation of `RouteFile` instances specifically for GET requests serving files. It abstracts away the need to explicitly instantiate `RouteFile` for common file serving scenarios. ### Method `static Route::file(string $uri, string $file, string $method = 'GET', int $status = 200, int $times = 1, array $headers = []): RouteFile ` ### Parameters - **uri** (string) - Required - The URI path for the route. - **file** (string) - Required - The binary file content. - **method** (string) - Optional - The HTTP method. Defaults to 'GET'. - **status** (int) - Optional - The HTTP status code. Defaults to 200. - **times** (int) - Optional - The number of times this route should respond. Defaults to 1. - **headers** (array) - Optional - An array of HTTP headers. ### Returns `RouteFile` - A new `RouteFile` instance configured for serving the specified file. ### Example ```php use Ciareis\Bypass\Route; $imageContent = file_get_contents('logo.png'); $route = Route::file( uri: '/images/logo.png', file: $imageContent, method: 'GET', status: 200, headers: ['Content-Type' => 'image/png'] ); ``` ``` -------------------------------- ### Best Practice: Set times appropriately Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-not-called-exception.md Demonstrates setting the 'times' parameter when adding a route to accurately reflect its expected usage, including accounting for potential retries. ```php // Route will be called 3 times - account for retries $bypass->addRoute('GET', '/api/unstable', 500, times: 3); ``` -------------------------------- ### Configure Multiple Routes with Bypass::serve() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/configuration.md Use the `serve()` helper to configure multiple routes simultaneously using Route objects. This is a concise way to set up common responses. ```php use Ciareis\Bypass\Bypass; use Ciareis\Bypass\Route; $bypass = Bypass::serve( Route::ok(uri: '/users'), Route::created(uri: '/users'), Route::notFound(uri: '/missing'), Route::serverError(uri: '/error') ); ``` -------------------------------- ### RouteFile Constructor Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md Defines an HTTP route that serves binary file content. It takes the HTTP method, URI, file content, and optional status, times, and headers. ```APIDOC ## RouteFile Constructor ### Description Initializes a new instance of the `RouteFile` class, which represents an HTTP route designed to return binary file content. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None #### Constructor Parameters - **method** (string) - Required - The HTTP method for the route (e.g., 'GET', 'POST'). - **uri** (string) - Required - The URI path for the route (e.g., '/files/document.pdf'). The leading slash is added automatically if missing. - **file** (string) - Required - The binary file content, typically obtained using `file_get_contents()`. - **status** (int) - Optional - The HTTP status code to return. Defaults to 200. - **times** (int) - Optional - The number of times this route should respond. Defaults to 1. - **headers** (array) - Optional - An array of HTTP headers to include in the response. Defaults to an empty array. ### Example ```php use Ciareis\Bypass\RouteFile; $pdfContent = file_get_contents('document.pdf'); $route = new RouteFile( method: 'GET', uri: '/downloads/document.pdf', file: $pdfContent, status: 200, times: 1, headers: ['Content-Type' => 'application/pdf'] ); ``` ``` -------------------------------- ### Pest PHP: Test total score by username Source: https://github.com/ciareis/bypass/blob/main/README.md Opens a Bypass server, defines a GET route for user scores, and verifies the response. ```php use Ciareis\Bypass\Bypass; it('properly returns the total score by username', function () { //Opens a new Bypass server $bypass = Bypass::open(); //Json body $body = '{"games":[{"id":1, "name":"game 1","points":25},{"id":2, "name":"game 2","points":10}],"is_active":true}'; //Defines a route $bypass->addRoute(method: 'GET', uri: '/v1/score/johndoe', status: 200, body: $body); //Configure your service to access Bypass URL $service = new TotalScoreService(); $response = $service ->setBaseUrl($bypass->getBaseUrl()) ->getTotalScoreByUsername('johndoe'); //Verifies that response is 35 expect($response)->toBe(35); }); ``` -------------------------------- ### BypassServiceProvider boot() Method Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass-service-provider.md The boot method of the BypassServiceProvider. It currently does not perform any actions but serves as a hook point for future initialization. ```php public function boot(): void ``` -------------------------------- ### Get Server Port Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md Retrieves the port number on which the Bypass server is currently listening. This is useful for constructing URLs or making direct requests. ```php $bypass = Bypass::open(); $port = $bypass->getPort(); echo $port; // e.g., 8234 ``` -------------------------------- ### Serve Multiple Files with Different Statuses Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route-file.md Utilize addFileRoute to add multiple file-serving routes, each with a specific HTTP method, URI, file content, status code, and headers. This is useful for simulating success and error responses. ```php $bypass = Bypass::open(); // Success case $bypass->addFileRoute( method: 'GET', uri: '/export/data.csv', file: file_get_contents('exports/data.csv'), status: 200, headers: ['Content-Type' => 'text/csv'] ); // Error case - 404 $bypass->addFileRoute( method: 'GET', uri: '/export/missing.csv', file: file_get_contents('errors/404.html'), status: 404, headers: ['Content-Type' => 'text/html'] ); ``` -------------------------------- ### Get All Registered Routes Source: https://github.com/ciareis/bypass/blob/main/README.md Inspect all registered routes for debugging purposes. This snippet shows how to open Bypass, add a route, and then retrieve all configured routes. ```php $bypass = Bypass::open(); $bypass->addRoute(method: 'GET', uri: '/v1/api/data', status: 200); $routes = $bypass->getRoutes(); // Returns array with route configurations ``` -------------------------------- ### Static Factory Methods: ok() Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/route.md Creates a route that returns HTTP 200 (OK). ```APIDOC ## ok() ### Description Creates a route that returns HTTP 200 (OK). ### Method `public static function ok(string $uri, null|string|array $body = null, string $method = "GET", int $times = 1, array $headers = []): self` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **uri** (string) - Required - URI path. - **body** (string|array|null) - Optional - Response body. Defaults to null. - **method** (string) - Optional - HTTP method. Defaults to "GET". - **times** (int) - Optional - Number of times callable. Defaults to 1. - **headers** (array) - Optional - HTTP headers. Defaults to []. ### Returns `self` - New Route instance. ### Request Example ```php $route = Route::ok( uri: '/api/users', body: ['users' => []], method: 'GET', times: 2 ); ``` ``` -------------------------------- ### Bypass Instance as String (Base URL) Source: https://github.com/ciareis/bypass/blob/main/_autodocs/api-reference/bypass.md The Bypass instance can be directly cast to a string to get its base URL. This simplifies constructing full request URLs. ```php $bypass = Bypass::serve( Route::ok(uri: '/test', body: 'OK') ); // Can be used directly as URL $response = Http::get($bypass . '/test'); // Equivalent to: Http::get($bypass->getBaseUrl() . '/test') ```