• Stars
    star
    568
  • Rank 76,091 (Top 2 %)
  • Language
    PHP
  • License
    MIT License
  • Created almost 4 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Laravel Cypress Integration

Laravel + Cypress Integration

This package provides the necessary boilerplate to quickly begin testing your Laravel applications using Cypress.

Video Tour

If you'd prefer a more visual review of this package, please watch this video on Laracasts.

Table of Contents

Installation

If you haven't already installed Cypress; that's your first step.

npm install cypress --save-dev

Now you're ready to install this package through Composer. Pull it in as a development-only dependency.

composer require laracasts/cypress --dev

Finally, run the cypress:boilerplate command to copy over the initial boilerplate files for your Cypress tests.

php artisan cypress:boilerplate

That's it! You're ready to go. We've provided an example.cy.js spec for you to play around with it. Let's run it now:

npx cypress open

In the Cypress window that opens, Choose "E2E Testing," and then "Start E2E Testing in Chrome." This will bring up a list of all specs in your application. Of course, at this point, we only have the single example spec. Click example.cy.js to run it. Wew! All green.

Cypress Configuration

We've declared some initial settings in your project's cypress.config.js file. Have a quick look now to ensure that everything is in order. In particular, please ensure that the baseUrl property is set correctly (we default to your app's APP_URL environment setting).

Environment Handling

After running the php artisan cypress:boilerplate command, you'll now have a .env.cypress file in your project root. To get you started, this file is a duplicate of .env. Feel free to update it as needed to prepare your application for your Cypress tests.

Likely, you'll want to use a special database to ensure that your Cypress acceptance tests are isolated from your development database.

DB_CONNECTION=mysql
DB_DATABASE=cypress

When running your Cypress tests, this package, by default, will automatically back up your primary .env file, and swap it out with env.cypress. Once complete, of course the environment files will be reset to how they originally were.

All Cypress tests run according to the environment specified in .env.cypress.

However, when your Cypress tests fail, it can often be useful to manually browse your application in the exact state that triggered the test failure. You can't do this if your environment is automatically reverted after each test run.

To solve this, you have two choices:

Option 1:

Temporarily disable the Cypress task that resets the environment. Visit cypress/support/index.js and comment out this portion.

after(() => {
  // cy.task("activateLocalEnvFile", {}, { log: false });
});

That should do it! Just remember to manually revert to your local .env file when you're done performing your Cypress tests.

Option 2:

When booting a server with php artisan serve, you can optionally pass an --env flag to specify your desired environment for the application.

php artisan serve --env="cypress"

^ This command instructs Laravel to boot up a server and use the configuration that is declared in .env.cypress.

Now visit cypress.json and change the baseUrl to point to your local server.

{
  "baseUrl": "http://127.0.0.1:8000"
}

And you're all set! I'd recommend creating an npm script to simplify this process. Open package.json, and add:

{
  "scripts": {
    "test:cypress": "php artisan serve --env=cypress & cypress open"
  }
}

Now from the command line, you can run npm run test:cypress to start a local server and open Cypress.

If you choose this second option, visit cypress/support/index.js and delete the activateCypressEnvFile and activateLocalEnvFile tasks, as shown here. They're no longer required, as you'll be handling the environment handling yourself.

API

This package will add a variety of commands to your Cypress workflow to make for a more familiar Laravel testing environment.

We allow for this by exposing a handful of Cypress-specific endpoints in your application. Don't worry: these endpoints will never be accessible in production.

cy.login()

Find an existing user matching the optional attributes provided and set it as the authenticated user for the test. If not found, it'll create a new user and log it in.

test('authenticated users can see the dashboard', () => {
  cy.login({ username: 'JohnDoe' });

  cy.visit('/dashboard').contains('Welcome Back, JohnDoe!');
});

Should you need to also eager load relationships on the user model or specifiy a certain model factory state before it's returned from the server, instead pass an object to cy.login(), like so:

test('authenticated users can see the dashboard', () => {
    cy.login({
        attributes: { username: 'JohnDoe' },
        state: ['guest'],
        load: ['profile']
    });

    cy.visit('/dashboard').contains('Welcome Back, JohnDoe!');
});

If written in PHP, this object would effectively translate to:

$user = User::factory()->guest()->create([ 'username' => 'JohnDoe' ])->load('profile');

auth()->login($user);

cy.currentUser()

Fetch the currently authenticated user from the server, if any. Equivalent to Laravel's auth()->user().

test('assert the current user has email', () => {
    cy.login({ email: '[email protected]' });

    cy.currentUser().its('email').should('eq', '[email protected]');
    
    // or...
    
    cy.currentUser().then(user => {
        expect(user.email).to.eql('[email protected]');
    });
});

cy.logout()

Log out the currently authenticated user. Equivalent to Laravel's auth()->logout().

test('once a user logs out they cannot see the dashboard', () => {
  cy.login({ username: 'JohnDoe' });

  cy.logout();

  cy.visit('/dashboard').assertRedirect('/login');
});

cy.create()

Use Laravel factories to create and persist a new Eloquent record.

test('it shows blog posts', () => {
  cy.create('App\\Post', { title: 'My First Post' });

  cy.visit('/posts').contains('My First Post');
});

Note that the cy.create() call above is equivalent to:

App\Post::factory()->create(['title' => 'My First Post']);

You may optionally specify the number of records you require as the second argument. This will then return a collection of posts.

test('it shows blog posts', () => {
  cy.create('App\\Post', 3, { title: 'My First Post' });
});

Lastly, you can alternatively pass an object to cy.create(). This should be the preferred choice, if you need to eager load relationships or create the model record in a given model factory state.

test('it shows blog posts', () => {
    cy.create({
        model: 'App\\Post',
        attributes: { title: 'My First Post' },
        state: ['archived'],
        load: ['author'],
        count: 10
    })
});

If written in PHP, this object would effectively translate to:

$user = \App\Post::factory(10)->archived()->create([ 'title' => 'My First Post' ])->load('author');

auth()->login($user);

cy.refreshRoutes()

Before your Cypress test suite run, this package will automatically fetch a collection of all named routes for your Laravel app and store them in memory. You shouldn't need to manually call this method, however, it's available to you if your routing will change as side effect of a particular test.

test('it refreshes the list of Laravel named routes in memory', () => {
    cy.refreshRoutes();
});

cy.refreshDatabase()

Trigger a migrate:refresh on your test database. Often, you'll apply this in a beforeEach call to ensure that, before each new test, your database is freshly migrated and cleaned up.

beforeEach(() => {
  cy.refreshDatabase();
});

test('it does something', () => {
  // php artisan migrate:fresh has been
  // called at this point.
});

cy.seed()

Run all database seeders, or a single class, in the current Cypress environment.

test('it seeds the db', () => {
  cy.seed('PlansTableSeeder');
});

Assuming that APP_ENV in your .env.cypress file is set to "acceptance," the call above would be equivalent to:

php artisan db:seed --class=PlansTableSeeder --env=acceptance

cy.artisan()

Trigger any Artisan command under the current environment for the Cypress test. Remember to precede options with two dashes, as usual.

test('it can create posts through the command line', () => {
  cy.artisan('post:make', {
    '--title': 'My First Post',
  });

  cy.visit('/posts').contains('My First Post');
});

This call is equivalent to:

php artisan post:make --title="My First Post"

cy.php()

While not exactly in the spirit of acceptance testing, this command will allow you to trigger and evaluate arbitrary PHP.

test('it can evaluate PHP', () => {
    cy.php(`
        App\\Plan::first();
    `).then(plan => {
        expect(plan.name).to.equal('Monthly'); 
    });
});

Be thoughtful when you reach for this command, but it might prove useful in instances where it's vital that you verify the state of the application or database in response to a certain action. It could also be used for setting up the "world" for your test. That said, a targeted database seeder - using cy.seed() - will typically be the better approach.

Routing

Each time your test suite runs, this package will fetch all named routes for your Laravel application, and store them in memory. You'll additionally find a ./cypress/support/routes.json file that contains a dump of this JSON.

This package overrides the base cy.visit() method to allow for optionally passing a route name instead of a URL.

test('it loads the about page using a named route', () => {
    cy.visit({
        route: 'about'
    });
});

If the named route requires a wildcard, you may include it using the parameters property.

test('it loads the team dashboard page using a named route', () => {
    cy.visit({
        route: 'team.dashboard',
        parameters: { team: 1 }
    });
});

Should you need to access the full list of routes for your application, use the Cypress.Laravel.routes property.

// Get an array of all routes for your app.

Cypress.Laravel.routes; // ['home' => []]

Further, if you need to translate a named route to its associated URL, instead use the Cypress.Laravel.route() method, like so:

Cypress.Laravel.route('about'); // /about-page

Cypress.Laravel.route('team.dashboard', { team: 1 }); // /teams/1/dashboard

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

More Repositories

1

flash

Easy flash notifications
PHP
2,637
star
2

Laravel-5-Generators-Extended

This package extends the core file generators that are included with Laravel 5
PHP
2,447
star
3

PHP-Vars-To-Js-Transformer

Transform PHP data to JavaScript.
PHP
2,206
star
4

Lets-Build-a-Forum-in-Laravel

http://laracasts.com/series/lets-build-a-forum-with-laravel
JavaScript
912
star
5

Presenter

Easy view presenters in your apps.
PHP
864
star
6

Integrated

Simple, intuitive integration testing with PHPUnit.
PHP
478
star
7

TestDummy

Easy factories for PHP integration testing.
PHP
461
star
8

Vue-Forms

https://laracasts.com/series/learn-vue-2-step-by-step/episodes/19
PHP
402
star
9

Commander

Easily leverage commands and domain events in your Laravel projects.
PHP
283
star
10

Behat-Laravel-Extension

Laravel extension for Behat functional testing.
PHP
261
star
11

matryoshka

Russian Doll Caching in Laravel
PHP
237
star
12

birdboard

Birdboard Series Code
PHP
236
star
13

Tweety

The final project from Laravel From Scratch.
PHP
178
star
14

The-PHP-Practitioner-Full-Source-Code

PHP
176
star
15

Laravel-From-Scratch-HTML-CSS

The HTML and CSS for the blog design for Laravel From Scratch
HTML
158
star
16

laravel-5-roles-and-permissions-demo

https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/16
PHP
153
star
17

Validation

Easy form validation.
PHP
150
star
18

larabook

Larabook Series
PHP
142
star
19

PHP-For-Beginners-Series

PHP
119
star
20

laravel-vue-spa

PHP
110
star
21

Dedicated-Query-String-Filtering

https://laracasts.com/series/eloquent-techniques/episodes/4
PHP
94
star
22

Code-Katas-in-PHP

Screencasts of various code kata challenges in HP.
PHP
88
star
23

Email-Verification-In-Laravel

PHP
83
star
24

URL-Shortener

For demo at Laracasts.com
PHP
82
star
25

The-PHP-Practitioner-Episode-16

PHP
70
star
26

Eloquent-Outside-of-Laravel

In this lesson, you'll learn how to use Eloquent in a simple vanilla PHP environment. Luckily, it's pretty easy! For smaller projects that don't require the overhead of a full-stack framework, this method can be a great choice!
PHP
69
star
27

eloquent-performance-patterns

PHP
62
star
28

Build-An-Activity-Feed-in-Laravel

https://laracasts.com/lessons/build-an-activity-feed-in-laravel
JavaScript
58
star
29

Laravel-Redis-and-Socket.io

PHP
56
star
30

Laravel-OAuth-and-Socialite

PHP
55
star
31

Laravel-and-Vue

JavaScript
54
star
32

Email-Only-Authentication-With-Laravel

https://laracasts.com/series/laravel-authentication-techniques/episodes/1
PHP
54
star
33

transcriptions

Load and parse VTT files.
PHP
53
star
34

Laravel-and-Angular-Goodness

PHP
53
star
35

testingvue

http://testingvue.com
PHP
50
star
36

simple-di-container

PHP
48
star
37

Vue-SPA-Essentials-Routing

JavaScript
45
star
38

Mass-User-Settings

PHP
40
star
39

Users-and-Roles-in-Laravel

What if you want to assign a user to a particular role? For example, some of them might be classified as members, while others could be administrators. How might we allow for such things?
PHP
40
star
40

Nested-Comments

PHP
38
star
41

Gilded-Rose-Kata-in-PHP

PHP
38
star
42

Laravel-Elixir-Vueify-Setup

JavaScript
38
star
43

Blade-Component-Examples

PHP
37
star
44

In-Stock-Tracker

PHP
34
star
45

roles-and-abilities

PHP
33
star
46

socket-io-chat-example-app

HTML
32
star
47

Reports-and-Graphs

Using ChartJS to build line graphs with Laravel.
PHP
32
star
48

Accept-Payments-With-Stripe

https://laracasts.com/series/how-to-accept-payments-with-stripe
PHP
31
star
49

The-Vast-World-of-Vuejs

Lesson 1 Source
HTML
30
star
50

How-Do-I-Create-A-Star-Rating-System

https://laracasts.com/series/how-do-i/episodes/22
PHP
29
star
51

Learn-Flexbox-Through-Examples

HTML
29
star
52

JS-Component-Playground

https://laracasts.com/series/practical-vue-components
PHP
28
star
53

The-PHP-Practitioner-Episode-20

https://laracasts.com/series/php-for-beginners/episodes/20
PHP
27
star
54

GitHub-Authentication-With-Laravel

There are a number of excellent OAuth packages available, however, this is Laracasts, and we want to know how to, not reinvent the wheel, but rebuild the wheel! With that in mind, in this lesson, let's review the general process of how to allow your users to login to your application, using GitHub (or any provider).
PHP
26
star
55

Building-User-Profiles

In this lesson, we'll review the process of adding user profiles to an application. In the process, we'll review everything from database design, to migrations, to security, to validation. Let's get going!
PHP
24
star
56

Vue-and-Laravel-Workflow

JavaScript
24
star
57

Testing-Vue

JavaScript
23
star
58

Behat-Laravel-Extension-Example-App

Quick example app to demonstrate setting up Behat with Mink and Laravel extension
CSS
23
star
59

Pjax-and-Laravel

PHP
22
star
60

Billing-With-Stripe

PHP
21
star
61

Build-Command-line-Apps

PHP
21
star
62

Widget

Simple view widgets.
PHP
20
star
63

todomvc-alpine

A quick TodoMVC implementation with Alpine.js
HTML
20
star
64

laravel-preset

The Laracasts default Laravel preset.
PHP
19
star
65

Russian-Doll-Caching-in-Laravel

https://laracasts.com/series/russian-doll-caching-in-laravel
PHP
19
star
66

Authentication-With-GitHub

https://laracasts.com/series/laravel-authentication-techniques/episodes/2
PHP
18
star
67

Build-Artisan-Commands-With-TDD

In this fun two-part series, we'll use TDD to build a helpful Artisan command. Along the way, we'll leverage both Codeception (for the end-to-end tests) and PHPSpec (for unit tests) to drive our code. There's lots to learn, so let's get going.
PHP
18
star
68

Pusher-Lesson

So you run a forum, and need some way to notify readers, if new replies have been left on a thread since their last page load. Well, how the heck do we do that? How do we say, "If a new reply is saved to the server, instantly update all viewers who might be reading the associated forum thread"? Well, Pusher can make these sorts of tasks a cinch! You'll love it.
JavaScript
18
star
69

PHP-Testing-Jargon

PHP
17
star
70

Document-Adjustments-Demo

https://laracasts.com/series/eloquent-techniques/episodes/3
PHP
17
star
71

Bash-Bootstraps

Often, it can prove helpful to write simple Bash scripts to bootstrap your new applications. The only question isโ€ฆhow do we do that? Let me show you!
Shell
17
star
72

form-objects-lesson

https://laracasts.com/series/whipping-monstrous-code-into-shape/episodes/1
PHP
17
star
73

Reusable-Repositories

So you're using repositories, but have found the process of constantly reimplementing common methods to be cumbersome?
PHP
17
star
74

Snippets-Project

https://laracasts.com/series/how-do-i/episodes/13
PHP
16
star
75

VideoJS-Events-and-AJAX

PHP
16
star
76

Transactional-Emails-in-Laravel-with-Campaign-Monitor

PHP
16
star
77

assets-website

PHP
15
star
78

build_a_forum_with_laravel_2023

Vue
15
star
79

Design-a-Fluent-API-with-TDD

https://laracasts.com/series/phpunit-testing-in-laravel/episodes/11
PHP
15
star
80

Help-Me-Understand-When-to-Use-Polymorphic-Relations

PHP
15
star
81

PHPSpec-Rocks

PHPSpec is the best test framework that you likely haven't used. That just might change after watching this video, though. It's excellent!
PHP
15
star
82

PHPSpec-Laravel-and-Refactoring

Any confusion that surrounds PHPSpec likely stems from a misunderstanding of what the framework is for. There are multiple styles and forms of testing; PHPSpec is not meant to fill all of those checkboxes. Let's talk about that in this lesson, while using BDD to build a class within a Laravel app.
PHP
14
star
83

Crazy-Simple-Pagination

PHP
13
star
84

the-specification-pattern-in-php

PHP
13
star
85

Flexible-Flash-Messages

You'll frequently find yourself in the position of needing to notify your users, in response to some particular action. In this lesson, we'll uses tests to drive flexible flash messaging.
PHP
13
star
86

laravel-workflow-for-swapping-vue-components

JavaScript
13
star
87

Bulk-Email-Notifications

In this lesson, we'll finish up our Mailchimp email notifications mini-project. Specifically, we'll focus on putting all the pieces that we built in the previous lesson together. This will include the creation of a UsersController, as well as a custom Artisan command to manually notify lesson subscribers.
PHP
13
star
88

Dynamic-Graphs-Lesson

https://laracasts.com/series/charting-and-you/episodes/8
JavaScript
13
star
89

Form-Validation-Simplified

Form validation is an interesting thing. It's trivial to implement, yet everyone tackles it differently. In this lesson, I'd like to show you my current approach (as of April, 2014) for handling this incredibly common task.
PHP
12
star
90

Laracasts-Docs

https://laracasts.com/series/how-to-read-code/episodes/6
PHP
12
star
91

Getting-Jiggy-With-Adapters

An adapter is one of the easier design patterns to learn. The reason why is because you use them in the real world all the time! In this lesson, let's review a handful of examples to figure out how it all works.
PHP
12
star
92

How-Do-I-Dry-Up-My-Forms

PHP
12
star
93

Laravel-4.1-Password-Resets

PHP
12
star
94

6-html-tags

6 New'ish HTML Tags You Can Use Right Now
HTML
11
star
95

gilded-rose-with-phpunit

Original Kata and Description: https://github.com/notmyself/GildedRose
PHP
10
star
96

Hands-On-Community-Contributions

https://laracasts.com/series/hands-on-community-contributions/episodes/13
PHP
10
star
97

Small-Objects-Are-a-Good-Thing-and-Other-Refactoring-Lessons

How many times have you written (or come across) a controller method that's dozens of lines long. Surely, there are better ways to structure our code, right? Of course. In this lesson, let's learn about everything from security, to small objects, to events.
PHP
10
star
98

Testing-Jargon

Illustrations of various pieces of testing terminology.
PHP
9
star
99

passwordless-login

PHP
9
star
100

Sanitizers-and-PHPSpec

Many applications will require some level of sanitization. With that in mind, as a learning experience, why don't we use TDD (using PHPSpec) to implement this functionality from scratch.
PHP
9
star