Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
DevToolsExtension
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 bootstrap
n/a
0 / 0
n/a
0 / 0
1
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of fast-forward/dev-tools.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/dev-tools
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\DevTools\PhpUnit\Runner\Extension;
20
21use FastForward\DevTools\PhpUnit\Event\EventTracer;
22use FastForward\DevTools\PhpUnit\Event\TestSuite\ByPassfinalsStartedSubscriber;
23use FastForward\DevTools\PhpUnit\Event\TestSuite\JoliNotifExecutionFinishedSubscriber;
24use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber;
25use PHPUnit\Event\TestSuite\StartedSubscriber;
26use PHPUnit\Event\Tracer\Tracer;
27use PHPUnit\Runner\Extension\Extension;
28use PHPUnit\Runner\Extension\Facade;
29use PHPUnit\Runner\Extension\ParameterCollection;
30use PHPUnit\TextUI\Configuration\Configuration;
31
32/**
33 * Registers the Joli notification tracer within the PHPUnit extension lifecycle.
34 *
35 * This extension MUST register a tracer capable of observing PHPUnit events so
36 * that desktop notifications can be dispatched when the test execution
37 * finishes.
38 *
39 * The tracer dependency MAY be overridden to allow alternative notification
40 * strategies or custom tracing behavior, but any provided implementation MUST
41 * satisfy PHPUnit's tracer contract.
42 */
43  class DevToolsExtension implements Extension
44{
45    private ExecutionFinishedSubscriber $executionFinishedSubscriber;
46
47    /**
48     * Creates a new extension instance.
49     *
50     * When no tracer is explicitly provided, the default Joli notification
51     * tracer SHALL be used.
52     *
53     * @param Tracer $tracer the tracer instance responsible for collecting
54     *                       PHPUnit events and producing notifications
55     * @param StartedSubscriber $startedSubscriber
56     * @param ExecutionFinishedSubscriber|null $executionFinishedSubscriber
57     */
58    public function __construct(
59        private Tracer $tracer = new EventTracer(),
60        private StartedSubscriber $startedSubscriber = new ByPassfinalsStartedSubscriber(),
61        ?ExecutionFinishedSubscriber $executionFinishedSubscriber = null
62    ) {
63        $this->executionFinishedSubscriber = $executionFinishedSubscriber ?? new JoliNotifExecutionFinishedSubscriber(
64            $tracer
65        );
66    }
67
68    /**
69     * Bootstraps the extension and registers its tracer with PHPUnit.
70     *
71     * This method MUST register the configured tracer with the provided facade
72     * so that the tracer can receive PHPUnit execution events during the test
73     * run.
74     * The configuration and parameter collection are part of the extension
75     * contract and MAY be used by future implementations, even though they are
76     * not currently required by this implementation.
77     *
78     * @param Configuration $configuration the resolved PHPUnit runtime
79     *                                     configuration
80     * @param Facade $facade the PHPUnit extension facade used to register
81     *                       runtime integrations
82     * @param ParameterCollection $parameters the user-defined extension
83     *                                        parameters passed by PHPUnit
84     *
85     * @return void
86     *
87     * @codeCoverageIgnore
88     */
89    public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void
90    {
91        $facade->registerTracer($this->tracer);
92        $facade->registerSubscriber($this->startedSubscriber);
93        $facade->registerSubscriber($this->executionFinishedSubscriber);
94    }
95}