Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slowness of constantly restarting the testing environment.

Overview

Magic Test for Laravel

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slowness of constantly restarting the testing environment.
It inverts the test-writing experience and avoids all the back and forth between tests, your terminal and your template files. See it in action here.
The easiest way to explain Magic Test is through a video. Check it out here.

Magic Test was originally created by Andrew Culver and Adam Pallozi for Ruby on Rails.
Laravel Magic Test was created by Mateus Guimarães.

Magic Test is still in early development, and that includes the documentation. Any questions you have that aren't already address in the documentation should be opened as issues so they can be appropriately addressed in the documentation.

Installation

You can install the package via composer:

composer require magic-test/magic-test-laravel --dev

Then, add the following line to your $middleware array under app/Http/Kernel.php:

\MagicTest\MagicTest\Middleware\MagicTestMiddleware::class

Usage

On your Laravel Dusk tests, simply add magic() at the end of your method chain. For example:

    public function testBasicExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->magic();
        });
    }

To run Magic Test, you must simply run the command php artisan magic. Behind the scenes, it is the same as running php artisan dusk, but it will maintain the browser window open.

This will leave you with two or three windows:

  • The browser
  • An interactive Shell
  • Your text editor if you had it open

For the Magic Experience ™️ , we suggest you organize the three windows to fit your screen. That way, you can see tests being generated in real-time.

Recording Actions

Once the browser is open, Magic Test will already be capturing all of your actions. You can click around, fill inputs, checkboxes, selects and radios just like you would do manually testing an application.

Generating Assertions

Additionally, you can generate text assertions by selecting a given text and then pressing ControlShift + A. You'll see a dialog box confirming the assertion has been recorded.

Saving the new actions to the test file

To save the actions that were recorded, simply go to the Shell and type ok. You are free to close it and come back to your Magic Sessiona any time, or just keep recording more actions.
If you're satisfied with your test, you can type finish on the Shell and it'll remove the magic() call from your test, leaving you with a clean, working test.

See how it works on this video

Magic Test is still in it's early days, so you might find that the output is not exactly what you wanted. In that case, feel free to submit an issue and we'll try to improve it ASAP.

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

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

Comments
  • Breaking with one line chained

    Breaking with one line chained

    Hi Mateus,

    I believe this is related to what we already talked about, but it has happened to me because I was not attentive to linebreak and then ->magic(). I decided to write here just to have it.

    When I make an assertion with a one line chained method $browser->visit('/')->magic();

    <?php
    
    namespace Tests\Browser;
    
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Laravel\Dusk\Browser;
    use Tests\DuskTestCase;
    
    class danTest extends DuskTestCase
    {
        /**
         * A Dusk test example.
         *
         * @return void
         */
        public function testExample()
        {
            $this->browse(function (Browser $browser) {
                $browser->visit('/')->magic();
            });
        }
    }
    

    ....It results in:

    <?php
    
    namespace Tests\Browser;
    
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Laravel\Dusk\Browser;
    use Tests\DuskTestCase;
    
    class danTest extends DuskTestCase
    {
        /**
         * A Dusk test example.
         *
         * @return void
         */
        public function testExample()
        {
            $this->browse(function (Browser $browser) {
                        ->assertSee('Language')
                $browser->visit('/')->magic();
            });
        }
    }
    
    opened by dansysanalyst 4
  • When app.debug is false, MagicTest crashes

    When app.debug is false, MagicTest crashes

    https://github.com/magic-test/magic-test-laravel/blob/b1d9d22951da5de941c3f65cfff9d9e1fcf34078/src/MagicTest.php#L38

    When setting APP_DEBUG=false in my .env, MagicTest crashes on the above line of code. Looks like it could be fixed by replacing self::minify($scripts) with self::minify($script) (removing the last 's' of the variable name).

    Can someone confirm that this would be the needed fix? Or, am I missing something :)

    opened by ThomasLaveto 3
  • Does not play nice with Inertia test assertions

    Does not play nice with Inertia test assertions

    I might have this setup incorrectly (which is a separate issue) but I did find this problem.

    When using Inertia, there are some included test helpers, assertInertia being one, that when the magic test middleware is enabled, will cause these tests to fail. I haven't dug into why, but I assume it has to do with the extra stuff that the middleware adds to a response. Removing the middleware fixes it.

    As a side note, the documentation could be clearer around where the package should be installed/enabled. If it's a dev dependency, then adding a middleware seems like the wrong approach (since it will break in prod?) (also sorry for double dipping on twitter! I found this issue afterwards)

    opened by daronspence 3
  • Windows 10 Issue? DUSK_HEADLESS_DISABLED is not recognized

    Windows 10 Issue? DUSK_HEADLESS_DISABLED is not recognized

    If I run "php artisan magic" on windows, I'm getting the following error:

    Your Magic Test session is starting... 'DUSK_HEADLESS_DISABLED' is not recognized as an internal or external command, operable program or batch file.

    I see the command is trying to shell_exec: DUSK_HEADLESS_DISABLED=1 MAGIC_TEST=1 php artisan dusk

    opened by tjhunkin 3
  • Magic test not able to run

    Magic test not able to run

    I'm testing this on a Ubuntu 20.04 VM with Chrome (latest) and I get this javascript error: 1) Tests\Browser\ExampleTest::testBasicExample Facebook\WebDriver\Exception\JavascriptErrorException: javascript error: MagicTest is not defined (Session info: headless chrome=95.0.4638.69)

    how can i fix this?

    opened by DanielvdSpoel 2
  • [WIP] AST Parser

    [WIP] AST Parser

    This PR aims to rewrite the current parser to use Nikita Popov's PHP-Parser.

    One of the biggest issues with MT right now is that it never actually knows where methods start or end, since it relies on new line characters and expects each line to have only one method. Using PHP-Parser we gain more control over the code being rewritten.

    Also, the biggest issue I'm facing is that I'm not 100% sure what I'm doing. I've never worked with PHP-Parser and there's some behavior that seems weird to me. For instance, imagine the following:

    class ExampleTest extends DuskTestCase
    {
        /**
         * A basic browser test example.
         *
         * @return void
         */
        public function testBasicExample()
        {
            $this->browse(function (Browser $browser) {
                $browser->visit('/')
                        ->clickLink('foo')
                        ->magic();
            });
        }
    }
    

    There's a PhpParser\Node\Stmt\ClassMethodthat is testBasicExample. Okay, that makes sense. There's a MethodCall that is the $this->browser call. Then there is the closure (a PhpParser\Node\Expr\Closure).

    Now, inside the closure, there's a Node that corresponds to the magic() call and is a PhpParser\Node\Stmt\MethodCall. The issue is that the previous chained methods are nested inside it's var property. So if you had 3 method calls, you'd have 3 nested MethodCall, each one being the FOLLOWING var. So you end up with something like this:

    MethodCall(
        name: 'magic',
        var: MethodCall(
            name: 'clickLink',
            var: MethodCall(
                name: visit
              )
          )
    )
    

    I'm unsure, but I think I was maybe expecting it to have an expression and several sibling nodes (or parent-child) for the chain.

    Anyway, it works, but I'm doing some nasty old magic with the nodes.

    Remaining:

    • Heavily test this
    • Try to properly understand how the nodes work
    • Refactor the existing classes
    opened by mateusjatenee 2
  • Reflecting actual requirements

    Reflecting actual requirements

    Arrow functions

    https://github.com/magic-test/magic-test-laravel/blob/1c7ea46ed8ffd881c282ad42f8281477e5c5f875/src/Parser/File.php#L63-L66

    and typed properties

    https://github.com/magic-test/magic-test-laravel/blob/1c7ea46ed8ffd881c282ad42f8281477e5c5f875/src/Parser/File.php#L12-L16

    were introduced in php 7.4 https://www.php.net/releases/7_4_0.php

    json_decode is called here: https://github.com/magic-test/magic-test-laravel/blob/1c7ea46ed8ffd881c282ad42f8281477e5c5f875/src/MagicTestManager.php#L52

    opened by ordago 2
  • Conflict with those who already import Jquery.

    Conflict with those who already import Jquery.

    This import breaks my code, since I use jquery, and this import at the end of the html code, it makes my packages that need jquery not work.

    This can be solved using your own config file. This is just an idea, as I still can't do a PR with the complete solution. This PR is more in order to warn of this behavior, since it makes the devs import the jquery just to do the tests which is not ideal.

    opened by ramonpego 2
  • Add 'dusk' as an allowed environment for the MagicTestMiddleware

    Add 'dusk' as an allowed environment for the MagicTestMiddleware

    For those of us who run our Dusk tests in a dedicated environment, scripts aren't loaded by the middleware as it requires either local or testing. I've added dusk to allow them to be included.

    I expect most people won't be affected by this, this is more niche for some apps which like to more clearly identify the execution context, but it saves having to override the middleware entirely.

    Thanks!

    opened by JackWH 1
  • Bump postcss from 8.2.6 to 8.2.13

    Bump postcss from 8.2.6 to 8.2.13

    Bumps postcss from 8.2.6 to 8.2.13.

    Release notes

    Sourced from postcss's releases.

    8.2.13

    • Fixed ReDoS vulnerabilities in source map parsing (by @​yetingli).

    8.2.12

    • Fixed package.json exports.

    8.2.11

    • Fixed DEP0148 warning in Node.js 16.
    • Fixed docs (by @​semiromid).

    8.2.10

    8.2.9

    8.2.8

    8.2.7

    Changelog

    Sourced from postcss's changelog.

    8.2.13

    • Fixed ReDoS vulnerabilities in source map parsing (by Yeting Li).

    8.2.12

    • Fixed package.json exports.

    8.2.11

    • Fixed DEP0148 warning in Node.js 16.
    • Fixed docs (by @​semiromid).

    8.2.10

    • Fixed ReDoS vulnerabilities in source map parsing.
    • Fixed webpack 5 support (by Barak Igal).
    • Fixed docs (by Roeland Moors).

    8.2.9

    • Exported NodeErrorOptions type (by Rouven Weßling).

    8.2.8

    • Fixed browser builds in webpack 4 (by Matt Jones).

    8.2.7

    • Fixed browser builds in webpack 5 (by Matt Jones).
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • javascript error: MagicTest is not defined

    javascript error: MagicTest is not defined

    Session info: chrome=95.0.4638.69

    [
        {
            "level": "WARNING",
            "message": "chrome-error:\/\/chromewebdata\/ 928:22 \"crbug\/1173575, non-JS module files deprecated.\"",
            "source": "console-api",
            "timestamp": 1636308045214
        },
        {
            "level": "WARNING",
            "message": "chrome-error:\/\/chromewebdata\/ 1249:22 \"crbug\/1173575, non-JS module files deprecated.\"",
            "source": "console-api",
            "timestamp": 1636308045215
        },
        {
            "level": "WARNING",
            "message": "chrome-error:\/\/chromewebdata\/ 2133:10 \"crbug\/1173575, non-JS module files deprecated.\"",
            "source": "console-api",
            "timestamp": 1636308045222
        }
    ]
    
    opened by Simoneu01 1
  • ok: RuntimeException with message 'Too many arguments, expected arguments

    ok: RuntimeException with message 'Too many arguments, expected arguments "command".'

    Very close to being able to use this wonderful tool, any help much appreciated.

    I run: ./artisan magic, a Chrome is being controlled by automated test software browser window comes up, dev console shows:

    Magic Test started
    

    I log in, dev console looks ok, no errors. Nothing in network tab relating to magic-test-laravel or testing generally.

    If I select text & press Ctrl + Shift + A the dialogue box pops up saying assertion generated.

    I go into psy shell, type ok but get the message:

    RuntimeException with message 'Too many arguments, expected arguments "command".' in: Psy Shell v0.10.12 (PHP 8.1.2 — cli)

    No major changes are made to the ExampleTest.php which has the simplest initial test method in it:

        public function testBasicExample()
        {
            $this->browse(function (Browser $browser) {
                $browser->visit('/')
                    //    ->assertSee('Laravel');
                    ->magic();
            });
        }
    

    What could be wrong? Full output here:

    *** Starting a 🧙 Magic Test session...
    PHPUnit 9.5.13 by Sebastian Bergmann and contributors.
    
    Psy Shell v0.10.12 (PHP 8.1.2 — cli) by Justin Hileman
    New version is available (current: v0.10.12, latest: v0.11.1)
    
    *** Welcome to your 🧙 Magic Test session! ***
    
    * To make a assertion press Ctrl + Shift + A on your browser.
    * Type ok to magically write it to your test file.
      (make as many assertions as you wish)
    * Type finish to finalize and save your test file.
    * Type exit to leave.
    
    💡 Tip: Do not close your browser window before finalizing this session here.
    >>> ok
    RuntimeException with message 'Too many arguments, expected arguments "command".'
    

    Using https://chromedriver.storage.googleapis.com/97.0.4692.71/chromedriver_mac64_m1.zip for the installed browser Version 97.0.4692.99 (Official Build) (arm64)

    ./artisan tinker works fine for the same project.

    ./artisan dusk returns OK (1 test, 1 assertion) when I switch commenting on magic() and assetSee('Laravel').

    opened by sidewaysglance 19
  • TypeError when running `ok` after actions

    TypeError when running `ok` after actions

    Description

    After installing Magic Test and following the installation and usage instructions I am receiving the following error after running the ok or finish commands.

    TypeError: Typed property MagicTest/MagicTest/Parser/File::$initialMethodLine must be an instance of MagicTest/MagicTest/Parser/Line, null used
    

    I am using the testBasicExample method of the ExampleTest in my browser tests as per the usage guide. The contents of my test is

    <?php
    
    namespace Tests\Browser;
    
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Laravel\Dusk\Browser;
    use Tests\DuskTestCase;
    
    class ExampleTest extends DuskTestCase
    {
        /**
         * A basic browser test example.
         *
         * @return void
         */
        public function testBasicExample()
        {
            $this->browse(function (Browser $browser) {
                $browser->visit('/')
                        ->magic();
            });
        }
    }
    

    Specifications

    • PHP Version: 7.4.13
    • Laravel Version: 8.9.0
    opened by rhys-steele 8
Releases(0.17)
Owner
null
Test requests in Laravel without all the boilerplate.

Request Factories Test requests in Laravel without all the boilerplate. ?? Psst. Although our examples use Pest PHP, this works just as well in PHPUni

Worksome 391 Jan 1, 2023
vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.

vfsStream vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with

null 1.4k Dec 23, 2022
Prevent none-test output in your Pest tests.

Pest Plugin Silence Often, when writing tests, we echo and dump test code to debug and check everything is working correctly. It can be easy to forget

Worksome 5 Feb 23, 2022
PHP Test Generator - A CLI tool which generates unit tests

This project make usages of PHPStan and PHPParser to generate test cases for a given PHP File.

Alexander Schranz 7 Dec 3, 2022
PHP unit testing framework with built in mocks and stubs. Runs in the browser, or via the command line.

Enhance PHP A unit testing framework with mocks and stubs. Built for PHP, in PHP! Quick Start: Just add EnhanceTestFramework.php and you are ready to

Enhance PHP 67 Sep 12, 2022
The Phoronix Test Suite is the most comprehensive testing and benchmarking platform

The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, macOS, Windows, and BSD operating systems.

Phoronix Test Suite 1.9k Jan 7, 2023
SimpleTest is a framework for unit testing, web site testing and mock objects for PHP

SimpleTest SimpleTest is a framework for unit testing, web site testing and mock objects for PHP. Installation Downloads All downloads are stored on G

SimpleTest 147 Jun 20, 2022
Wraps your Pest suite in a Laravel application instance, allowing global use of the framework in tests.

Pest Larastrap Plugin This is currently a highly experimental project and is subject to large pre-release changes. Pest PHP is an awesome PHP testing

Luke Downing 3 Jan 6, 2022
PHPUnit Application Architecture Test

PHPUnit Application Architecture Test Idea: write architecture tests as well as feature and unit tests Installation Install via composer composer requ

null 19 Dec 11, 2022
Mock HTTP requests on the server side in your PHP unit tests

HTTP Mock for PHP Mock HTTP requests on the server side in your PHP unit tests. HTTP Mock for PHP mocks the server side of an HTTP request to allow in

InterNations GmbH 386 Dec 27, 2022
Some shorthand functions for skipping and focusing tests.

Pest Plugin: Shorthands This repository contains the Pest Plugin Shorthands. If you want to start testing your application with Pest, visit the main P

Thomas Le Duc 10 Jun 24, 2022
A PHP library for mocking date and time in tests

ClockMock Slope s.r.l. ClockMock provides a way for mocking the current timestamp used by PHP for \DateTime(Immutable) objects and date/time related f

Slope 44 Dec 7, 2022
To run time/IO related unit tests (e.g., sleep function calls, database queries, API calls, etc) faster using Swoole.

To run time/IO related unit tests (e.g., sleep function calls, database queries, API calls, etc) faster using Swoole.

Demin Yin 11 Sep 9, 2022
TestDummy makes the process of preparing factories (dummy data) for your integration tests as easy as possible

TestDummy TestDummy makes the process of preparing factories (dummy data) for your integration tests as easy as possible. As easy as... Build a Post m

Laracasts 461 Sep 28, 2022
A tool to run migrations prior to running tests

cakephp-test-migrator A tool to run migrations prior to running tests The Migrator For CakePHP 3.x composer require --dev vierge-noire/cakephp-test-mi

Vierge Noire 11 Apr 29, 2022
Extension to use built-in PHP server on Behat tests

Extension to use built-in PHP server on Behat tests Instalation composer require libresign/behat-builtin-extension Configuration Add the extension to

LibreSign 2 Feb 21, 2022
Enforce consistent styling for your Pest PHP tests

A set of PHP CS rules for formatting Pest PHP tests.

Worksome 2 Mar 15, 2022
This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly

Curly Pest Plugin This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly. Installation composer require minicli/pest-pl

minicli 16 Mar 24, 2022
Example repo for writing tests in Drupal (using DDEV)

Drupal Test Writing This is a test D9 site which can be used for practicing test writing and running.

David Stinemetze 13 Nov 14, 2022