Skip to content

Commit

Permalink
Add named route fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyWay committed Jan 21, 2021
1 parent c02729f commit c9b8bda
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 16 deletions.
18 changes: 18 additions & 0 deletions src/Controllers/CypressController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,30 @@
namespace Laracasts\Cypress\Controllers;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;

class CypressController
{
public function routes()
{
$routes = Route::getRoutes()->getRoutes();

return collect($routes)
->map(function (\Illuminate\Routing\Route $route) {
return [
'name' => $route->getName(),
'domain' => $route->getDomain(),
'action' => $route->getActionName(),
'uri' => $route->uri(),
'method' => $route->methods(),
];
})
->keyBy('name');
}

public function login(Request $request)
{
if ($attributes = $request->input('attributes')) {
Expand Down
19 changes: 13 additions & 6 deletions src/CypressBoilerplateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,25 @@ public function handle()

protected function copyStubs()
{
$this->files->copyDirectory(__DIR__.'/stubs/support', base_path('cypress/support'));
$this->files->copyDirectory(__DIR__.'/stubs/plugins', base_path('cypress/plugins'));
$this->files->copyDirectory(
__DIR__ . '/stubs/support',
base_path('cypress/support')
);
$this->files->copyDirectory(
__DIR__ . '/stubs/plugins',
base_path('cypress/plugins')
);

$this->lineBreak();

$this->status('Updated', 'cypress/support/index.js');
$this->status('Updated', 'cypress/plugins/index.js');
$this->status('Created', 'cypress/plugins/swap-env.js');
$this->status('Created', 'cypress/support/laravel-commands.js');
$this->status('Created', 'cypress/support/laravel-routes.js');
$this->status('Created', 'cypress/support/assertions.js');

if (! $this->files->exists($path = base_path('.env.cypress'))) {
if (!$this->files->exists($path = base_path('.env.cypress'))) {
$this->files->copy(base_path('.env'), $path);

$this->status('Created', '.env.cypress');
Expand All @@ -68,11 +75,11 @@ protected function requestCypressInstallation()
$this->warn(
<<<'EOT'
Cypress not found. Please install it through npm and try again.
Cypress not found. Please install it through npm and try again.
npm install cypress --save-dev && npx cypress open
npm install cypress --save-dev && npx cypress open

EOT
EOT
);
}
}
30 changes: 24 additions & 6 deletions src/routes/cypress.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,27 @@
use Illuminate\Support\Facades\Route;
use Laracasts\Cypress\Controllers\CypressController;

Route::post('/__cypress__/factory', [CypressController::class, 'factory'])->name('cypress.factory');
Route::post('/__cypress__/login', [CypressController::class, 'login'])->name('cypress.login');
Route::post('/__cypress__/logout', [CypressController::class, 'logout'])->name('cypress.logout');
Route::post('/__cypress__/artisan', [CypressController::class, 'artisan'])->name('cypress.artisan');
Route::post('/__cypress__/run-php', [CypressController::class, 'runPhp'])->name('cypress.run-php');
Route::get('/__cypress__/csrf_token', [CypressController::class, 'csrfToken'])->name('cypress.csrf-token');
Route::post('/__cypress__/factory', [
CypressController::class,
'factory',
])->name('cypress.factory');
Route::post('/__cypress__/login', [CypressController::class, 'login'])->name(
'cypress.login'
);
Route::post('/__cypress__/logout', [CypressController::class, 'logout'])->name(
'cypress.logout'
);
Route::post('/__cypress__/artisan', [
CypressController::class,
'artisan',
])->name('cypress.artisan');
Route::post('/__cypress__/run-php', [CypressController::class, 'runPhp'])->name(
'cypress.run-php'
);
Route::get('/__cypress__/csrf_token', [
CypressController::class,
'csrfToken',
])->name('cypress.csrf-token');
Route::post('/__cypress__/routes', [CypressController::class, 'routes'])->name(
'cypress.routes'
);
3 changes: 3 additions & 0 deletions src/stubs/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

import './commands';
import './laravel-commands';
import './laravel-routes';
import './assertions';

before(() => {
cy.task('activateCypressEnvFile', {}, { log: false });
cy.artisan('config:clear', {}, { log: false });

cy.refreshRoutes();
});

after(() => {
Expand Down
43 changes: 43 additions & 0 deletions src/stubs/support/laravel-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,49 @@ Cypress.Commands.add('csrfToken', () => {
.its('body', { log: false });
});

/**
* Fetch and store all named routes.
*
* @example cy.refreshRoutes();
*/
Cypress.Commands.add('refreshRoutes', () => {
return cy.csrfToken().then((token) => {
return cy
.request({
method: 'POST',
url: '/__cypress__/routes',
body: { _token: token },
log: false,
})
.its('body', { log: false })
.then((routes) => {
cy.writeFile('cypress/support/routes.json', routes, {
log: false,
});

Cypress.Laravel.routes = routes;
});
});
});

/**
* Visit the given URL or route.
*
* @example cy.visit('foo/path');
* cy.visit({ route: 'home' });
* cy.visit({ route: 'team', parameters: { team: 1 } });
*/
Cypress.Commands.overwrite('visit', (originalFn, subject, options) => {
if (subject.route) {
return originalFn({
url: Cypress.Laravel.route(subject.route, subject.parameters || {}),
method: Cypress.Laravel.routes[subject.route].method[0],
});
}

return originalFn(subject, options);
});

/**
* Create a new Eloquent factory.
*
Expand Down
21 changes: 21 additions & 0 deletions src/stubs/support/laravel-routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Cypress.Laravel = {
routes: {},

route: (name, parameters = {}) => {
assert(
Cypress.Laravel.routes.hasOwnProperty(name),
`Laravel route "${name}" exists.`
);

return ((uri) => {
Object.keys(parameters).forEach((parameter) => {
uri = uri.replace(
new RegExp(`{${parameter}}`),
parameters[parameter]
);
});

return uri;
})(Cypress.Laravel.routes[name].uri);
},
};
19 changes: 19 additions & 0 deletions tests/CypressControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Laracasts\Cypress\Tests;

use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;
use Laracasts\Cypress\CypressServiceProvider;
use Laracasts\Cypress\Tests\Support\TestUser;
use Orchestra\Testbench\TestCase;
Expand All @@ -24,6 +25,24 @@ protected function setUp(): void
config(['auth.providers.users.model' => TestUser::class]);
}

/** @test */
function it_fetches_a_collection_of_named_routes()
{
Route::get('foo')->name('home');

$response = $this->post(route('cypress.routes'));

$response->assertJsonFragment([
'uri' => 'foo',
'name' => 'home',
'method' => ['GET', 'HEAD'],
'action' => 'Closure',
'domain' => null,
]);

$this->assertArrayHasKey('home', $response->json());
}

/** @test */
public function it_logs_a_new_user_in()
{
Expand Down
9 changes: 5 additions & 4 deletions tests/CypressTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected function getPackageProviders($app)
public function it_does_not_expose_cypress_routes_in_production()
{
$this->routeNames()->each(
fn ($name) => $this->assertFalse(Route::has($name))
fn($name) => $this->assertFalse(Route::has($name))
);
}

Expand All @@ -31,7 +31,7 @@ public function it_does_not_expose_cypress_routes_in_production()
public function it_exposes_cypress_routes_if_not_in_production()
{
$this->routeNames()->each(
fn ($name) => $this->assertTrue(Route::has($name))
fn($name) => $this->assertTrue(Route::has($name))
);
}

Expand All @@ -44,16 +44,17 @@ protected function routeNames()
'cypress.artisan',
'cypress.run-php',
'cypress.csrf-token',
'cypress.routes',
]);
}

protected function setUpAcceptanceEnvironment()
{
app()->detectEnvironment(fn () => 'acceptance');
app()->detectEnvironment(fn() => 'acceptance');
}

protected function setUpProductionEnvironment()
{
app()->detectEnvironment(fn () => 'production');
app()->detectEnvironment(fn() => 'production');
}
}

0 comments on commit c9b8bda

Please sign in to comment.