Full Code of Lakion/MinkDebugExtension for AI

master 270e5aa5aef5 cached
14 files
19.7 KB
5.1k tokens
33 symbols
1 requests
Download .txt
Repository: Lakion/MinkDebugExtension
Branch: master
Commit: 270e5aa5aef5
Files: 14
Total size: 19.7 KB

Directory structure:
gitextract_rw74d7mo/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── UPGRADE.md
├── composer.json
├── features/
│   ├── bootstrap/
│   │   └── FeatureContext.php
│   └── mink_debug.feature
├── src/
│   ├── Listener/
│   │   └── FailedStepListener.php
│   └── ServiceContainer/
│       └── MinkDebugExtension.php
└── test-application/
    ├── behat.yml.dist
    ├── features/
    │   └── test.feature
    └── logs/
        └── .gitkeep

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/build.yml
================================================
name: Build

on:
    push:
    pull_request:
        types: [opened, synchronize, edited, reopened]

jobs:
    tests:
        runs-on: ubuntu-latest
        continue-on-error: false
        name: "PHP ${{ matrix.php }}"

        strategy:
            fail-fast: false
            matrix:
                php:
                    - '7.4'
                    - '8.0'
                    - '8.1'

        steps:
            - name: Checkout
              uses: actions/checkout@v2

            - name: Setup PHP
              uses: shivammathur/setup-php@v2
              with:
                  coverage: none
                  ini-values: "memory_limit=-1"
                  php-version: ${{ matrix.php }}
                  tools: composer:v2

            - name: Run Chrome Headless
              run: google-chrome-stable --enable-automation --disable-background-networking --no-default-browser-check --no-first-run --disable-popup-blocking --disable-default-apps --allow-insecure-localhost --disable-translate --disable-extensions --no-sandbox --enable-features=Metal --headless --remote-debugging-port=9222 --window-size=2880,1800 --proxy-server='direct://' --proxy-bypass-list='*' http://127.0.0.1 > /dev/null 2>&1 &

            - name: Get Composer cache directory
              id: composer-cache
              run: echo "::set-output name=dir::$(composer config cache-files-dir)"

            - name: Cache Composer
              uses: actions/cache@v2
              with:
                  path: ${{ steps.composer-cache.outputs.dir }}
                  key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json **/composer.lock') }}
                  restore-keys: |
                      ${{ runner.os }}-php-${{ matrix.php }}-composer-

            - name: Install PHP dependencies
              run: composer install --no-interaction

            - name: Validate composer.json
              run: composer validate --ansi --strict

            - name: Run Behat
              run: vendor/bin/behat --colors --strict --no-interaction -vvv -f progress


================================================
FILE: .gitignore
================================================
/vendor
/composer.lock

/behat.yml

/test-application/logs/*
!/test-application/logs/.gitkeep


================================================
FILE: CHANGELOG.md
================================================
# CHANGELOG

### v2.0.1

- [#35](https://github.com/FriendsOfBehat/MinkDebugExtension/issues/35) Ignore StreamReadException as well ([@pamil](https://github.com/pamil))

### v2.0.0

* Added support for PHP 8.0
* Allowed taking screenshots with more drivers than just Selenium2Driver
* Changed log files extension from `.log` to `.html`
* Removed supplementary `upload-textfiles`, `upload-screenshots`, `wait-for-port` binaries
* Renamed extension from `Lakion\Behat\MinkDebugExtension` to `FriendsOfBehat\MinkDebugExtension`

### v1.0.0

* Initial release.


================================================
FILE: LICENSE
================================================
Copyright (c) 2016-2020 Lakion
              2020-2021 Kamil Kokot

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
MinkDebugExtension
==================

**MinkDebugExtension** is a Behat extension made for debugging and logging Mink related data after every failed step. 
It is especially useful while running tests on continuous integration server like Travis.
While using appropriate driver, you can also save screenshots just after the failure.

Installation
------------

Assuming you already have Composer:

```bash
composer require friends-of-behat/mink-debug-extension
```

Then you only need to configure your Behat profile:

```yml
default:
    extensions:
        FriendsOfBehat\MinkDebugExtension:
            directory: directory-where-to-save-logs
```

Configuration reference
-----------------------

Under `FriendsOfBehat\MinkDebugExtension` there are three options to be configured:

  - `directory` (required to enable extension) - contains path to directory that will contain generated logs. Use the variable `%paths.base%` to refer to the directory where your `behat.yml` is
  - `screenshot` (default `false`) - whether to save screenshots if using supporting driver
  - `clean_start` (default `true`) - whether to clean your existing logs on each Behat execution
  
Testing
-------

In order to test the extensions run:

```bash
composer install
bin/behat --strict
```

Authors
-------

MinkDebugExtension was originally created by [Kamil Kokot](https://kamilkokot.com).
See the list of [contributors](https://github.com/FriendsOfBehat/MinkDebugExtension/contributors).


================================================
FILE: UPGRADE.md
================================================
# UPGRADE

## FROM `1.x` TO `2.x`

- Change required package from `lakion/mink-debug-extension` to `friends-of-behat/mink-debug-extension` in your `composer.json`
- Change extension name from `Lakion\Behat\MinkDebugExtension` to `FriendsOfBehat\MinkDebugExtension` in your `behat.yml`
- Make sure you're not using binaries provided by `1.x` version of this library


================================================
FILE: composer.json
================================================
{
    "name": "friends-of-behat/mink-debug-extension",
    "type": "behat-extension",
    "description": "Debug extension for Behat",
    "keywords": [
        "debug",
        "behat",
        "mink",
        "logging"
    ],
    "homepage": "https://github.com/FriendsOfBehat/MinkDebugExtension",
    "license": "MIT",
    "authors": [
        {
            "name": "Kamil Kokot",
            "email": "kamil@kokot.me",
            "homepage": "https://kamilkokot.com"
        }
    ],
    "require": {
        "php": ">=7.4",
        "behat/behat": "^3.5",
        "behat/mink-extension": "^2.3"
    },
    "require-dev": {
        "behat/mink-goutte-driver": "^1.2",
        "behat/mink-selenium2-driver": "^1.4",
        "dmore/behat-chrome-extension": "^1.3",
        "dmore/chrome-mink-driver": "^2.7",
        "symfony/process": "^4.4 || ^5.2"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.1-dev"
        }
    },
    "autoload": {
        "psr-4": {
            "FriendsOfBehat\\MinkDebugExtension\\": "src/"
        }
    }
}


================================================
FILE: features/bootstrap/FeatureContext.php
================================================
<?php

declare(strict_types=1);

use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\TableNode;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;

final class FeatureContext implements Context
{
    /** @var string */
    private string $phpBin;

    /** @var array<string, string> */
    private array $configuration = ['%clean_start%' => 'true'];

    /** @var string */
    private string $testApplicationDir;

    /**
     * @BeforeScenario
     */
    public function prepareProcess(): void
    {
        $phpFinder = new PhpExecutableFinder();
        if (false === $php = $phpFinder->find()) {
            throw new \RuntimeException('Unable to find the PHP executable.');
        }

        $this->phpBin = $php;
        $this->testApplicationDir = __DIR__ . '/../../test-application';
    }

    /**
     * @Given there is following Behat extension configuration:
     */
    public function thereIsBehatExtensionConfiguration(TableNode $table): void
    {
        foreach ($table->getRowsHash() as $key => $value) {
            $this->configuration['%' . $key . '%'] = $value;
        }
    }

    /**
     * @Given /configuration option "([^"]+?)" is set to "([^"]+?)"/
     */
    public function configurationOptionSet(string $key, string $value): void
    {
        $this->configuration['%' . $key . '%'] = $value;
    }

    /**
     * @When /I run Behat with failing scenarios(?: using (.+?) profile)?/
     */
    public function iRunBehat(?string $profile = null): void
    {
        $this->createBehatConfigurationFile();

        $this->doRunBehat($this->getExtraConfiguration($profile));

        $this->deleteBehatConfigurationFile();
    }

    /**
     * @Then there should be text log generated
     */
    public function thereShouldBeTextLogGenerated(): void
    {
        $logPattern = $this->testApplicationDir . '/' . $this->configuration['%directory%'] . '/*.html';

        $logsAmount = count(glob($logPattern));
        if ($logsAmount !== 1) {
            throw new \RuntimeException(sprintf('Expected 1 log file, found %d.', $logsAmount));
        }
    }

    /**
     * @Then a screenshot should be made
     */
    public function screenshotShouldBeMade(): void
    {
        $screenshotPattern = $this->testApplicationDir . '/' . $this->configuration['%directory%'] . '/*.png';

        $screenshotsAmount = count(glob($screenshotPattern));
        if ($screenshotsAmount !== 1) {
            throw new \RuntimeException(sprintf('Expected 1 screenshot, found %d.', $screenshotsAmount));
        }
    }

    /**
     * @Then a screenshot should not be made
     */
    public function screenshotShouldNotBeMade(): void
    {
        $screenshotPattern = $this->testApplicationDir . '/' . $this->configuration['%directory%'] . '/*.png';

        $screenshotsAmount = count(glob($screenshotPattern));
        if ($screenshotsAmount !== 0) {
            throw new \RuntimeException(sprintf('Expected no screenshots, found %d.', $screenshotsAmount));
        }
    }

    private function createBehatConfigurationFile(): void
    {
        $behatConfiguration = strtr(
            file_get_contents($this->testApplicationDir . '/behat.yml.dist'),
            $this->configuration
        );

        file_put_contents($this->testApplicationDir . '/behat.yml', $behatConfiguration);
    }

    private function getExtraConfiguration(?string $profile): array
    {
        if (null !== $profile) {
            return ['--profile=' . $profile];
        }

        return [];
    }

    private function doRunBehat(array $extraConfiguration): void
    {
        $arguments = array_merge(
            [$this->phpBin, BEHAT_BIN_PATH, '--strict', '-vvv', '--no-interaction', '--lang=en'],
            $extraConfiguration
        );

        $process = new Process($arguments, $this->testApplicationDir);
        $process->start();
        $process->wait();

        printf("stdOut:\n %s\nstdErr:\n%s\n", $process->getOutput(), $process->getErrorOutput());
    }

    private function deleteBehatConfigurationFile(): void
    {
        if (file_exists($behatFile = $this->testApplicationDir . '/behat.yml')) {
            unlink($behatFile);
        }
    }
}


================================================
FILE: features/mink_debug.feature
================================================
Feature: Logging debug data
  In order to debug my Behat suites with ease
  As a developer
  I want to be able to access logs

  Background:
    Given there is following Behat extension configuration:
        | directory  | logs |
        | screenshot | true |

  Scenario:
     When I run Behat with failing scenarios
     Then there should be text log generated

  Scenario:
     When I run Behat with failing scenarios using javascript profile
     Then there should be text log generated
      And a screenshot should be made

  Scenario:
    Given configuration option "screenshot" is set to "false"
     When I run Behat with failing scenarios using javascript profile
     Then there should be text log generated
      And a screenshot should not be made


================================================
FILE: src/Listener/FailedStepListener.php
================================================
<?php

declare(strict_types=1);

namespace FriendsOfBehat\MinkDebugExtension\Listener;

use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\StepTested;
use Behat\Mink\Exception\Exception as MinkException;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Mink;
use Behat\Mink\Session;
use Behat\Testwork\Tester\Result\TestResult;
use DMore\ChromeDriver\StreamReadException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use WebDriver\Exception as WebDriverException;

final class FailedStepListener implements EventSubscriberInterface
{
    /**
     * @var Mink
     */
    private Mink $mink;

    /**
     * @var string
     */
    private string $logDirectory;

    /**
     * @var bool
     */
    private bool $screenshot;

    /**
     * Used to ensure that screenshot and log comes from the same failed step.
     *
     * @var string
     */
    private string $currentDateAsString;

    public function __construct(Mink $mink, string $logDirectory, bool $screenshot)
    {
        $this->mink = $mink;
        $this->logDirectory = $logDirectory;
        $this->screenshot = $screenshot;
    }

    /**
     * @return array<string, array>
     */
    public static function getSubscribedEvents(): array
    {
        return [
            StepTested::AFTER => ['logFailedStepInformations', -10],
        ];
    }

    public function logFailedStepInformations(AfterStepTested $event): void
    {
        $testResult = $event->getTestResult();

        if (!$testResult instanceof TestResult || TestResult::FAILED !== $testResult->getResultCode()) {
            return;
        }

        if (!$this->hasEligibleMinkSession()) {
            return;
        }

        $this->currentDateAsString = date('YmdHis');

        $this->logPageContent();

        if ($this->screenshot) {
            $this->logScreenshot();
        }
    }

    private function logPageContent(): void
    {
        $session = $this->getSession();

        $log = sprintf('Current page: %d %s', $this->getStatusCode($session), $this->getCurrentUrl($session)) . "\n";
        $log .= $this->getResponseHeadersLogMessage($session);
        $log .= $this->getResponseContentLogMessage($session);

        $this->saveLog($log, 'html');
    }

    private function logScreenshot(): void
    {
        $session = $this->getSession();

        try {
            $this->saveLog($session->getScreenshot(), 'png');
        } catch (UnsupportedDriverActionException | WebDriverException $exception) {}
    }

    private function saveLog(string $content, string $type): void
    {
        $path = sprintf("%s/behat-%s.%s", $this->logDirectory, $this->currentDateAsString, $type);

        if (file_put_contents($path, $content) === false) {
            throw new \RuntimeException(sprintf('Failed while trying to write log in "%s".', $path));
        }
    }

    private function getSession(?string $name = null): Session
    {
        return $this->mink->getSession($name);
    }

    private function hasEligibleMinkSession(?string $name = null): bool
    {
        $name = $name ?: $this->mink->getDefaultSessionName();

        return $this->mink->hasSession($name) && $this->mink->isSessionStarted($name);
    }

    private function getStatusCode(Session $session): ?int
    {
        try {
            return $session->getStatusCode();
        } catch (MinkException | WebDriverException | StreamReadException $exception) {
            return null;
        }
    }

    private function getCurrentUrl(Session $session): ?string
    {
        try {
            return $session->getCurrentUrl();
        } catch (MinkException | WebDriverException | StreamReadException $exception) {
            return null;
        }
    }

    private function getResponseHeadersLogMessage(Session $session): ?string
    {
        try {
            return 'Response headers:' . "\n" . print_r($session->getResponseHeaders(), true) . "\n";
        } catch (MinkException | WebDriverException | StreamReadException $exception) {
            return null;
        }
    }

    private function getResponseContentLogMessage(Session $session): ?string
    {
        try {
            return 'Response content:' . "\n" . $session->getPage()->getContent() . "\n";
        } catch (MinkException | WebDriverException | StreamReadException $exception) {
            return null;
        }
    }
}


================================================
FILE: src/ServiceContainer/MinkDebugExtension.php
================================================
<?php

declare(strict_types=1);

namespace FriendsOfBehat\MinkDebugExtension\ServiceContainer;

use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
use Behat\Testwork\ServiceContainer\ExtensionManager;
use FriendsOfBehat\MinkDebugExtension\Listener\FailedStepListener;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

final class MinkDebugExtension implements ExtensionInterface
{
    public function load(ContainerBuilder $container, array $config): void
    {
        $this->loadStepFailureListener($container);

        $this->removeAllExistingLogsIfRequested($config);

        $container->setParameter('mink_debug.directory', $config['directory']);
        $container->setParameter('mink_debug.screenshot', $config['screenshot']);
        $container->setParameter('mink_debug.clean_start', $config['clean_start']);
    }

    public function configure(ArrayNodeDefinition $builder): void
    {
        $builder
            ->children()
                ->scalarNode('directory')->isRequired()->end()
                ->booleanNode('screenshot')->defaultFalse()->end()
                ->booleanNode('clean_start')->defaultTrue()->end()
            ->end();
    }

    public function getConfigKey(): string
    {
        return 'fob_mink_debug';
    }

    public function initialize(ExtensionManager $extensionManager): void
    {
    }

    public function process(ContainerBuilder $container): void
    {
    }

    private function loadStepFailureListener(ContainerBuilder $container): void
    {
        $definition = new Definition(FailedStepListener::class, [
            new Reference('mink'),
            '%mink_debug.directory%',
            '%mink_debug.screenshot%',
        ]);

        $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, ['priority' => 0]);

        $container->setDefinition('mink_debug.listener.step_failure', $definition);
    }

    /**
     * @param array<string, mixed> $config
     */
    private function removeAllExistingLogsIfRequested(array $config): void
    {
        if ($config['clean_start']) {
            array_map('unlink', glob($config['directory'] . '/*.html'));
            array_map('unlink', glob($config['directory'] . '/*.png'));
        }
    }
}


================================================
FILE: test-application/behat.yml.dist
================================================
default:
    suites:
        default:
            contexts:
                - Behat\MinkExtension\Context\MinkContext

    extensions:
        FriendsOfBehat\MinkDebugExtension:
            directory: %directory%
            clean_start: %clean_start%

        Behat\MinkExtension:
            sessions:
                default:
                    goutte: ~

    gherkin:
        filters:
            tags: "~@javascript"

javascript:
    extensions:
        FriendsOfBehat\MinkDebugExtension:
            directory: %directory%
            screenshot: %screenshot%
            clean_start: %clean_start%

        DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~

        Behat\MinkExtension:
            javascript_session: chrome
            sessions:
                chrome:
                    chrome:
                        api_url: http://127.0.0.1:9222
                        validate_certificate: false
            show_auto: false

    gherkin:
        filters:
            tags: "@javascript"


================================================
FILE: test-application/features/test.feature
================================================
Feature: Testing MinkDebugExtension
  In order to test MinkDebugExtension
  As a behat
  I want to download a page and fail

  Scenario: Downloading a page and failing
     When I go to "https://sylius.com"
     Then I select "Create failing test" from "Available steps"

  @javascript
  Scenario: Downloading a page and failing (Javascript session)
    When I go to "https://sylius.com"
    Then I select "Create failing test" from "Available steps"


================================================
FILE: test-application/logs/.gitkeep
================================================
Download .txt
gitextract_rw74d7mo/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── UPGRADE.md
├── composer.json
├── features/
│   ├── bootstrap/
│   │   └── FeatureContext.php
│   └── mink_debug.feature
├── src/
│   ├── Listener/
│   │   └── FailedStepListener.php
│   └── ServiceContainer/
│       └── MinkDebugExtension.php
└── test-application/
    ├── behat.yml.dist
    ├── features/
    │   └── test.feature
    └── logs/
        └── .gitkeep
Download .txt
SYMBOL INDEX (33 symbols across 3 files)

FILE: features/bootstrap/FeatureContext.php
  class FeatureContext (line 10) | final class FeatureContext implements Context
    method prepareProcess (line 24) | public function prepareProcess(): void
    method thereIsBehatExtensionConfiguration (line 38) | public function thereIsBehatExtensionConfiguration(TableNode $table): ...
    method configurationOptionSet (line 48) | public function configurationOptionSet(string $key, string $value): void
    method iRunBehat (line 56) | public function iRunBehat(?string $profile = null): void
    method thereShouldBeTextLogGenerated (line 68) | public function thereShouldBeTextLogGenerated(): void
    method screenshotShouldBeMade (line 81) | public function screenshotShouldBeMade(): void
    method screenshotShouldNotBeMade (line 94) | public function screenshotShouldNotBeMade(): void
    method createBehatConfigurationFile (line 104) | private function createBehatConfigurationFile(): void
    method getExtraConfiguration (line 114) | private function getExtraConfiguration(?string $profile): array
    method doRunBehat (line 123) | private function doRunBehat(array $extraConfiguration): void
    method deleteBehatConfigurationFile (line 137) | private function deleteBehatConfigurationFile(): void

FILE: src/Listener/FailedStepListener.php
  class FailedStepListener (line 18) | final class FailedStepListener implements EventSubscriberInterface
    method __construct (line 42) | public function __construct(Mink $mink, string $logDirectory, bool $sc...
    method getSubscribedEvents (line 52) | public static function getSubscribedEvents(): array
    method logFailedStepInformations (line 59) | public function logFailedStepInformations(AfterStepTested $event): void
    method logPageContent (line 80) | private function logPageContent(): void
    method logScreenshot (line 91) | private function logScreenshot(): void
    method saveLog (line 100) | private function saveLog(string $content, string $type): void
    method getSession (line 109) | private function getSession(?string $name = null): Session
    method hasEligibleMinkSession (line 114) | private function hasEligibleMinkSession(?string $name = null): bool
    method getStatusCode (line 121) | private function getStatusCode(Session $session): ?int
    method getCurrentUrl (line 130) | private function getCurrentUrl(Session $session): ?string
    method getResponseHeadersLogMessage (line 139) | private function getResponseHeadersLogMessage(Session $session): ?string
    method getResponseContentLogMessage (line 148) | private function getResponseContentLogMessage(Session $session): ?string

FILE: src/ServiceContainer/MinkDebugExtension.php
  class MinkDebugExtension (line 16) | final class MinkDebugExtension implements ExtensionInterface
    method load (line 18) | public function load(ContainerBuilder $container, array $config): void
    method configure (line 29) | public function configure(ArrayNodeDefinition $builder): void
    method getConfigKey (line 39) | public function getConfigKey(): string
    method initialize (line 44) | public function initialize(ExtensionManager $extensionManager): void
    method process (line 48) | public function process(ContainerBuilder $container): void
    method loadStepFailureListener (line 52) | private function loadStepFailureListener(ContainerBuilder $container):...
    method removeAllExistingLogsIfRequested (line 68) | private function removeAllExistingLogsIfRequested(array $config): void
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
  {
    "path": ".github/workflows/build.yml",
    "chars": 2090,
    "preview": "name: Build\n\non:\n    push:\n    pull_request:\n        types: [opened, synchronize, edited, reopened]\n\njobs:\n    tests:\n  "
  },
  {
    "path": ".gitignore",
    "chars": 94,
    "preview": "/vendor\n/composer.lock\n\n/behat.yml\n\n/test-application/logs/*\n!/test-application/logs/.gitkeep\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 557,
    "preview": "# CHANGELOG\n\n### v2.0.1\n\n- [#35](https://github.com/FriendsOfBehat/MinkDebugExtension/issues/35) Ignore StreamReadExcept"
  },
  {
    "path": "LICENSE",
    "chars": 1091,
    "preview": "Copyright (c) 2016-2020 Lakion\n              2020-2021 Kamil Kokot\n\nPermission is hereby granted, free of charge, to any"
  },
  {
    "path": "README.md",
    "chars": 1476,
    "preview": "MinkDebugExtension\n==================\n\n**MinkDebugExtension** is a Behat extension made for debugging and logging Mink r"
  },
  {
    "path": "UPGRADE.md",
    "chars": 365,
    "preview": "# UPGRADE\n\n## FROM `1.x` TO `2.x`\n\n- Change required package from `lakion/mink-debug-extension` to `friends-of-behat/min"
  },
  {
    "path": "composer.json",
    "chars": 1067,
    "preview": "{\n    \"name\": \"friends-of-behat/mink-debug-extension\",\n    \"type\": \"behat-extension\",\n    \"description\": \"Debug extensio"
  },
  {
    "path": "features/bootstrap/FeatureContext.php",
    "chars": 4232,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nuse Behat\\Behat\\Context\\Context;\nuse Behat\\Gherkin\\Node\\TableNode;\nuse Symfony\\Componen"
  },
  {
    "path": "features/mink_debug.feature",
    "chars": 762,
    "preview": "Feature: Logging debug data\n  In order to debug my Behat suites with ease\n  As a developer\n  I want to be able to access"
  },
  {
    "path": "src/Listener/FailedStepListener.php",
    "chars": 4434,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace FriendsOfBehat\\MinkDebugExtension\\Listener;\n\nuse Behat\\Behat\\EventDispatcher\\"
  },
  {
    "path": "src/ServiceContainer/MinkDebugExtension.php",
    "chars": 2500,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace FriendsOfBehat\\MinkDebugExtension\\ServiceContainer;\n\nuse Behat\\Testwork\\Event"
  },
  {
    "path": "test-application/behat.yml.dist",
    "chars": 1021,
    "preview": "default:\n    suites:\n        default:\n            contexts:\n                - Behat\\MinkExtension\\Context\\MinkContext\n\n "
  },
  {
    "path": "test-application/features/test.feature",
    "chars": 451,
    "preview": "Feature: Testing MinkDebugExtension\n  In order to test MinkDebugExtension\n  As a behat\n  I want to download a page and f"
  },
  {
    "path": "test-application/logs/.gitkeep",
    "chars": 0,
    "preview": ""
  }
]

About this extraction

This page contains the full source code of the Lakion/MinkDebugExtension GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (19.7 KB), approximately 5.1k tokens, and a symbol index with 33 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!