Skip to content

🧪 PHP and API server in Behat tests

License

Notifications You must be signed in to change notification settings

drevops/behat-phpserver

Repository files navigation

Behat contexts for serving static files and mocked API responses via the PHP server

GitHub Issues GitHub Pull Requests Test PHP codecov GitHub release (latest by date) Total Downloads LICENSE Renovate

Features

  • PhpServerContext context to start and stop PHP server:
    • Automatically start and stop PHP server for each scenario.
    • Serve files from a configurable document root.
    • Configurable PHP server protocol, host and port.
  • ApiServerContext context to serve queued API responses for API mocking:
    • A RESTful API server used to queue up expected API responses.
    • Step definition to queue up API responses.
    • Automatically start and stop PHP server for each scenario.
    • Serve files from a configurable document root.
    • Configurable PHP server protocol, host and port.

Installation

composer require --dev drevops/behat-phpserver

Usage

PhpServerContext

Used to serve assets from a pre-defined document root.

default:
  suites:
    default:
      contexts:
        - DrevOps\BehatPhpServer\PhpServerContext:
            webroot: '%paths.base%/tests/behat/fixtures' # Path to the PHP server document root
            protocol: http  # PHP server protocol
            host: 0.0.0.0   # PHP server host
            port: 8888      # PHP server port
            debug: false    # Enable debug mode for verbose output

ApiServerContext

Used to serve a pre-set API responses from a pre-defined document root.

default:
  suites:
    default:
      contexts:
        - DrevOps\BehatPhpServer\ApiServerContext:
            webroot: '%paths.base%/apiserver' # Path to the API server document root
            protocol: http  # API PHP server protocol
            host: 0.0.0.0   # API PHP server host
            port: 8889      # API PHP server port
            debug: false    # API Enable debug mode for verbose output

API responses can be queued up in the API server server by sending PUT requests to /admin/responses as an array of the expected responses using following JSON format:

[
  {
    "code": 200,
    "reason": "OK",
    "headers": {},
    "body": ""
  },
  {
    "code": 404,
    "reason": "Not found",
    "headers": {
    },
    "body": ""
  }
]

The ApiServerContext provides several step definitions to make it easier to work with the API server:

# Check if the API server is running.
Given the API server is running

# Queue up a single API response.
Given API will respond with:
  """
  {
    "code": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
      "Id": "test-id-1",
      "Slug": "test-slug-1"
    }
  }
  """

# Queue up a single API response with minimal configuration.
Given API will respond with:
  """
  {
    "code": 200
  }
  """

# Queue up a single API response with JSON body.
Given API will respond with JSON:
  """
  {
    "Id": "test-id-1",
    "Slug": "test-slug-1"
  }
  """

# Queue up a single API response with JSON body and expected code.

Given API will respond with JSON and 201 code:
  """
  {
    "Id": "test-id-2",
    "Slug": "test-slug-2"
  }
  """

See this test feature for more examples.

For more information on supported RESTful API enpoints, see the API server implementation.

Accessing the API server URL from your contexts

If you need to access the API server URL from your context to update the base URL of your API client, you can do so by using beforeScenario in your FeatureContext class:

<?php

declare(strict_types=1);

use Behat\Behat\Context\Context;
use Behat\Behat\Context\Environment\InitializedContextEnvironment;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use DrevOps\BehatPhpServer\ApiServerContext;
use DrevOps\BehatPhpServer\PhpServerContext;

class FeatureContext implements Context {

  /**
   * The PHP server URL.
   */
  protected string $phpServerUrl;

  /**
   * The API server URL.
   */
  protected string $apiServerUrl;

  /**
   * Initialize the context.
   *
   * @beforeScenario
   */
  public function beforeScenarioInit(BeforeScenarioScope $scope): void {
    $environment = $scope->getEnvironment();

    if (!$environment instanceof InitializedContextEnvironment) {
      throw new \Exception('Environment is not initialized');
    }

    $context = $environment->getContext(PhpServerContext::class);
    $this->phpServerUrl = $context->getServerUrl();

    $context = $environment->getContext(ApiServerContext::class);
    $this->apiServerUrl = $context->getServerUrl();
  }

}

Maintenance

Lint code

composer lint
composer lint-fix

Run tests

composer test
composer test-bdd

This repository was created using the Scaffold project template