Skip to content
This repository was archived by the owner on Jan 9, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ A beautiful dashboard for your Dusk test suites.

![](https://pociot.dev/storage/22/dusk-dashboard.gif)


## Improvements
* Upgrade to PHP 8.0
* Upgraded some packages
* Applied community improvements from other forks

## Next Step
* Generate PDF report

## Installation

You can install the package via composer:
Expand Down
13 changes: 9 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@
}
],
"require": {
"php": "^7.2",
"php": "^7.2|^8.0",
"barryvdh/laravel-snappy": "^1.0",
"cboden/ratchet": "^0.4.1",
"clue/buzz-react": "^2.5",
"guzzlehttp/guzzle": "^7.0.1",
"h4cc/wkhtmltoimage-amd64": "0.12.x",
"h4cc/wkhtmltoimage-i386": "0.12.x",
"h4cc/wkhtmltopdf-amd64": "0.12.x",
"h4cc/wkhtmltopdf-i386": "0.12.x",
"illuminate/console": "5.6.*|5.7.*|5.8.*|6.*|7.*|8.*",
"illuminate/support": "5.6.*|5.7.*|5.8.*|6.*|7.*|8.*",
"laravel/dusk": "^4.0|^5.0|^6.0",
"yosymfony/resource-watcher": "^2.0"
"react/http": "^1.4",
"yosymfony/resource-watcher": "^3.0"
},
"require-dev": {
"larapack/dd": "^1.0",
"phpunit/phpunit": "^7.0"
"phpunit/phpunit": "^7.0|^8.0|^9.0"
},
"autoload": {
"psr-4": {
Expand Down
135 changes: 135 additions & 0 deletions src/BrowserReportCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

namespace BeyondCode\DuskDashboard;


use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\App;
use BeyondCode\DuskDashboard\Dusk\Browser;

class BrowserReportCollector
{
protected $pdf;

protected $testName;

public function __construct($testName)
{
$this->testName = $testName;

$this->pdf = App::make('snappy.pdf.wrapper');
$this->pdf->setOption('disable-javascript', false);
$this->pdf->setOption('javascript-delay', 10000);
$this->pdf->setOption('no-stop-slow-scripts', true);
$this->pdf->setOption('enable-smart-shrinking', true);
$this->pdf->setOption('margin-bottom', 0);
$this->pdf->setOption('margin-top', 0);

$file_name = Str::slug($this->testName) . "_" . Carbon::now()->format('YmdHis');
$outPath = storage_path("app/dusk-reports/");
if (!file_exists($outPath)) {
mkdir($outPath, 0777, true);
}


$data_html = '<h1>Bill</h1><p>You owe me money, dude.</p>';

$this->pdf->loadHtml($data_html);
$this->pdf->save($outPath . $file_name . '.pdf');
}

public function collect(string $action, array $arguments, Browser $browser, string $previousHtml = null)
{
$path = parse_url($browser->driver->getCurrentURL(), PHP_URL_PATH) ?? '';

$action = new Action($action, $arguments, $browser->getCurrentPageSource(), $path);

$action->setPreviousHtml($previousHtml);

$this->pushAction('dusk-event', [
'test' => $this->testName,
'path' => $action->getPath(),
'name' => $action->getName(),
'arguments' => $action->getArguments(),
'before' => $action->getPreviousHtml(),
'html' => $action->getHtml(),
]);

$this->processPerformanceLog($browser);
}

protected function processPerformanceLog(Browser $browser)
{
$logs = collect([]);

try {
$logs = collect($browser->driver->manage()->getLog('performance'));
} catch (\Exception $e) {
// performance logging might be disabled.
}

$allowedMethods = [
'Network.requestWillBeSent',
'Network.responseReceived',
];

$logs
->map(function ($log) {
return json_decode($log['message']);
})
->filter(function ($log) use ($allowedMethods) {
$method = data_get($log, 'message.method');

$type = data_get($log, 'message.params.type');

return in_array($method, $allowedMethods) && $type === 'XHR';
})->groupBy(function ($log) {
if (data_get($log, 'message.method') === 'Network.requestWillBeSent') {
return data_get($log, 'message.requestId');
}

return data_get($log, 'params.requestId');
})->map(function ($log) use ($browser) {
$this->pushPerformanceLog($log->toArray(), $browser);
});
}

protected function pushAction(string $name, array $payload)
{
/*
try {
$this->client->post('http://127.0.0.1:'.StartDashboardCommand::PORT.'/events', [
RequestOptions::JSON => [
'channel' => 'dusk-dashboard',
'name' => $name,
'data' => $payload,
],
]);
} catch (\Exception $e) {
// Dusk-Dashboard Server might be turned off. No need to panic!
}
*/
}

protected function pushPerformanceLog(array $log, Browser $browser)
{
$request = $log[0];
$response = $log[1];

$url = parse_url(data_get($request, 'message.params.request.url'));

$this->pushAction('dusk-event', [
'test' => $this->testName,
'name' => 'XHR',
'arguments' => [
data_get($request, 'message.params.request.method').' '.
$url['path'].' '.
data_get($response, 'message.params.response.status').' '.
data_get($response, 'message.params.response.statusText'),
],
'html' => $browser->getCurrentPageSource(),
'logs' => $log,
]);
}
}
23 changes: 15 additions & 8 deletions src/Console/StartDashboardCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
use BeyondCode\DuskDashboard\Ratchet\Server\App;
use BeyondCode\DuskDashboard\Ratchet\Socket;
use BeyondCode\DuskDashboard\Watcher;
use Clue\React\Buzz\Browser;
use React\Http\Browser;
use Illuminate\Console\Command;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory as LoopFactory;
use React\EventLoop\Loop as LoopFactory;
use React\EventLoop\LoopInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Routing\Route;

class StartDashboardCommand extends Command
{
const PORT = 9773;
public const PORT = 9773;

protected $signature = 'dusk:dashboard';

Expand Down Expand Up @@ -46,7 +46,7 @@ public function handle()
{
$url = parse_url(config('dusk-dashboard.host', config('app.url')));

$this->loop = LoopFactory::create();
$this->loop = LoopFactory::get();

$this->loop->futureTick(function () use ($url) {
$dashboardUrl = 'http://'.$url['host'].':'.self::PORT.'/dashboard';
Expand Down Expand Up @@ -78,17 +78,20 @@ protected function addRoutes()

protected function createTestWatcher()
{
$finder = (new Finder)
$finder = (new Finder())
->name('*.php')
->files()
->in($this->getTestSuitePath());

(new Watcher($finder, $this->loop))->startWatching(function () {
$client = new Browser($this->loop);

$client->post('http://127.0.0.1:'.self::PORT.'/events', [
$client->post(
'http://127.0.0.1:'.self::PORT.'/events',
[
'Content-Type' => 'application/json',
], json_encode([
],
json_encode([
'channel' => 'dusk-dashboard',
'name' => 'dusk-reset',
'data' => [],
Expand All @@ -109,7 +112,7 @@ protected function getTestSuitePath()
$xml = simplexml_load_file(base_path('phpunit.dusk.xml'));

foreach ($xml->testsuites->testsuite as $testsuite) {
$directories[] = (string) $testsuite->directory;
$directories[] = trim((string) $testsuite->directory);
}
} else {
$directories[] = base_path('tests/Browser');
Expand All @@ -136,5 +139,9 @@ protected function tryToOpenInBrowser($url)
if (PHP_OS === 'Darwin') {
exec('open '.$url);
}

if (PHP_OS === 'Linux') {
exec('xdg-open '.$url);
}
}
}
37 changes: 29 additions & 8 deletions src/Dusk/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,47 @@
namespace BeyondCode\DuskDashboard\Dusk;

use BeyondCode\DuskDashboard\BrowserActionCollector;
use BeyondCode\DuskDashboard\BrowserReportCollector;

class Browser extends \Laravel\Dusk\Browser
{
use Concerns\InteractsWithAuthentication,
Concerns\InteractsWithCookies,
Concerns\InteractsWithElements,
Concerns\InteractsWithJavascript,
Concerns\InteractsWithMouse,
Concerns\MakesAssertions,
Concerns\MakesUrlAssertions,
Concerns\WaitsForElements;
use Concerns\InteractsWithAuthentication;
use Concerns\InteractsWithCookies;
use Concerns\InteractsWithElements;
use Concerns\InteractsWithJavascript;
use Concerns\InteractsWithMouse;
use Concerns\MakesAssertions;
use Concerns\MakesUrlAssertions;
use Concerns\WaitsForElements;

/** @var BrowserActionCollector */
protected $actionCollector;

/** @var BrowserReportCollector */
protected $reportCollector;

/**
* Create a browser instance.
*
* @param \Facebook\WebDriver\Remote\RemoteWebDriver $driver
* @param \Laravel\Dusk\ElementResolver|null $resolver
* @return void
*/
public function __construct($driver, $resolver = null)
{
parent::__construct($driver, $resolver);
}

public function setActionCollector(BrowserActionCollector $collector)
{
$this->actionCollector = $collector;
}

public function setReportCollector(BrowserReportCollector $reportCollector)
{
$this->reportCollector = $reportCollector;
}

/**
* @return BrowserActionCollector|null
*/
Expand Down
4 changes: 2 additions & 2 deletions src/Ratchet/Http/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace BeyondCode\DuskDashboard\Ratchet\Http;

use GuzzleHttp\Psr7\Response;
use function GuzzleHttp\Psr7\str;
use GuzzleHttp\Psr7\Message;
use Psr\Http\Message\RequestInterface;
use Ratchet\ConnectionInterface;

Expand All @@ -12,7 +12,7 @@ class DashboardController extends Controller
public function onOpen(ConnectionInterface $connection, RequestInterface $request = null)
{
$connection->send(
str(new Response(
Message::toString(new Response(
200,
['Content-Type' => 'text/html'],
file_get_contents(__DIR__.'/../../../resources/views/index.html')
Expand Down
6 changes: 3 additions & 3 deletions src/Ratchet/Http/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use BeyondCode\DuskDashboard\Ratchet\Socket;
use Exception;
use GuzzleHttp\Psr7\Response;
use function GuzzleHttp\Psr7\str;
use GuzzleHttp\Psr7\Message;
use Psr\Http\Message\RequestInterface;
use Ratchet\ConnectionInterface;

Expand All @@ -23,9 +23,9 @@ public function onOpen(ConnectionInterface $conn, RequestInterface $request = nu
$connection->send($request->getBody());
}

$conn->send(str(new Response(200)));
$conn->send(Message::toString(new Response(200)));
} catch (Exception $e) {
$conn->send(str(new Response(500, [], $e->getMessage())));
$conn->send(Message::toString(new Response(500, [], $e->getMessage())));
}

$conn->close();
Expand Down
4 changes: 2 additions & 2 deletions src/Ratchet/Server/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public function __construct($httpHost, $port, $address, LoopInterface $loop)

$socket = new Reactor($address.':'.$port, $loop);

$this->routes = new RouteCollection;
$this->routes = new RouteCollection();

$urlMatcher = new UrlMatcher($this->routes, new RequestContext);
$urlMatcher = new UrlMatcher($this->routes, new RequestContext());

$router = new Router($urlMatcher);

Expand Down
14 changes: 8 additions & 6 deletions src/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

namespace BeyondCode\DuskDashboard\Testing;

use BeyondCode\DuskDashboard\BrowserActionCollector;
use BeyondCode\DuskDashboard\Console\StartDashboardCommand;
use BeyondCode\DuskDashboard\Dusk\Browser;
use Closure;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Throwable;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use BeyondCode\DuskDashboard\Dusk\Browser;
use Laravel\Dusk\TestCase as BaseTestCase;
use Throwable;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use BeyondCode\DuskDashboard\BrowserActionCollector;
use BeyondCode\DuskDashboard\BrowserReportCollector;
use BeyondCode\DuskDashboard\Console\StartDashboardCommand;

abstract class TestCase extends BaseTestCase
{
Expand Down Expand Up @@ -39,6 +40,7 @@ protected function createBrowsersFor(Closure $callback)

foreach ($browsers as $browser) {
$browser->setActionCollector(new BrowserActionCollector($this->getTestName()));
$browser->setReportCollector(new BrowserReportCollector($this->getTestName()));
}

static::$browsers = $browsers;
Expand Down