Chapters
32 Chapters
|
4:16:27
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!
Subscribe to download the code!
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"babdev/pagerfanta-bundle": "4.x-dev", // 4.x-dev
"doctrine/doctrine-bundle": "^2.10", // 2.12.x-dev
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.4.x-dev
"doctrine/orm": "^2.16", // 2.18.x-dev
"knplabs/knp-time-bundle": "dev-main", // dev-main
"pagerfanta/doctrine-orm-adapter": "4.x-dev", // 4.x-dev
"pagerfanta/twig": "4.x-dev", // 4.x-dev
"symfony/asset": "6.4.*", // 6.4.x-dev
"symfony/asset-mapper": "6.4.*", // 6.4.x-dev
"symfony/console": "6.4.x-dev", // 6.4.x-dev
"symfony/dotenv": "6.4.x-dev", // 6.4.x-dev
"symfony/flex": "^2", // 2.x-dev
"symfony/form": "6.4.x-dev", // 6.4.x-dev
"symfony/framework-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/monolog-bundle": "^3.0", // dev-master
"symfony/runtime": "6.4.x-dev", // 6.4.x-dev
"symfony/security-csrf": "6.4.x-dev", // 6.4.x-dev
"symfony/stimulus-bundle": "2.x-dev", // 2.x-dev
"symfony/twig-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/ux-autocomplete": "2.x-dev", // 2.x-dev
"symfony/ux-live-component": "2.x-dev", // 2.x-dev
"symfony/ux-turbo": "2.x-dev", // 2.x-dev
"symfony/ux-twig-component": "2.x-dev", // 2.x-dev
"symfony/validator": "6.4.x-dev", // 6.4.x-dev
"symfony/web-link": "6.4.*", // 6.4.x-dev
"symfony/yaml": "6.4.x-dev", // 6.4.x-dev
"symfonycasts/dynamic-forms": "dev-main", // dev-main
"symfonycasts/tailwind-bundle": "dev-main", // dev-main
"tales-from-a-dev/flowbite-bundle": "dev-main", // dev-main
"twig/extra-bundle": "^2.12|^3.0", // 3.x-dev
"twig/twig": "^2.12|^3.0" // 3.x-dev
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.6.x-dev
"phpunit/phpunit": "^9.5", // 9.6.x-dev
"symfony/browser-kit": "6.4.*", // 6.4.x-dev
"symfony/css-selector": "6.4.*", // 6.4.x-dev
"symfony/debug-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/maker-bundle": "^1.51", // dev-main
"symfony/panther": "^2.1", // v2.1.1
"symfony/phpunit-bridge": "7.1.x-dev", // 7.1.x-dev
"symfony/stopwatch": "6.4.x-dev", // 6.4.x-dev
"symfony/web-profiler-bundle": "6.4.x-dev", // 6.4.x-dev
"zenstruck/browser": "1.x-dev", // 1.x-dev
"zenstruck/foundry": "^1.36" // 1.x-dev
}
}
What JavaScript libraries does this tutorial use?
// importmap.php
return [
'app' => [
'path' => './assets/app.js',
'entrypoint' => true,
],
'js-confetti' => [
'version' => '0.11.0',
],
'@hotwired/stimulus' => [
'version' => '3.2.2',
],
'@symfony/stimulus-bundle' => [
'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
],
'tom-select' => [
'version' => '2.3.1',
],
'tom-select/dist/css/tom-select.default.css' => [
'version' => '2.3.1',
'type' => 'css',
],
'@hotwired/turbo' => [
'version' => '7.3.0',
],
'stimulus-popover' => [
'version' => '6.2.0',
],
'debounce' => [
'version' => '1.2.1',
],
'turbo-view-transitions' => [
'version' => '0.3.0',
],
'stimulus-use' => [
'version' => '0.52.1',
],
'flowbite' => [
'version' => '2.2.1',
],
'@popperjs/core' => [
'version' => '2.11.8',
],
'flowbite-datepicker' => [
'version' => '1.2.6',
],
];
15 Comments
Right after
composer require symfony/panther --devI had to runcomposer require --dev dbrekelmans/bdi && vendor/bin/bdi detect driversHey @apphancer ,
Thanks for sharing this with others! It might be helpful :)
Cheers!
If you enable
autocomplete=truefor theplanetfield in theVoyageTypeform (It's works great with Live Components at the moment), your Panther test might not work, because for selecting planet field (selectFieldOption('Planet', 'Earth')), crawler detects htmlinputfield instead ofselectfield, and throws an exception.To fix this, set
autocomplete=falsefor testing:Hey @Olexandr!
You're solution definitely works and sometimes, to stay sane when working with Panther, it's what you have to do. :)
I am curious: was it finding the autocomplete
inputor not finding theselect? I believe Panther cannot find things that aren't visible so I would have expected an "element not found" exception (because autocomplete hides the select and replaces with an input).--Kevin
Hi @kbond!
Actually, an exception throws by crawler on
autocomplete=truesetting, looks like:Xdebug shows that crawler detects an
inputtype field, which is not whatselectFieldOptionmethod expects. So the simplest way, is to disable autocomplete and to give crawler the expected type)Exception thrown on: https://github.com/symfony/panther/blob/main/src/DomCrawler/Field/ChoiceFormField.php#L199
The state of variables in that moment:
autocomplete=falsegives:Hmm, I see... Then yeah, sounds like your solution is the easiest, reasonable fix...
I have issues with test execution speed :/
It looks like that
waitForTurboFrameLoadcheck for anyturbo-frame[aria-busy="true"]in the page is executed before Turbo adds thearia-busy="true"attribute to the frame.I had similar issue with the modal loading. The tests complain about not finding the Purpose input. I added a wait for the
form[name="voyage"]before callingfillField.Does anyone have an idea of what can be done to get proper waiting?
Hello @fbourigault
Great catch. in fact with turbo you should first wait for it to appear on the page, and then wait for disappear, it can be achieved with some
spin()functions like here described https://docs.behat.org/en/v2.5/cookbook/using_spin_functions.htmlCheers!
Hey everyone
If anyone tries to get this whole Panther system working in the context of a containerized environment (in my case: a DDEV wrapper around Docker), you will need to jump through some extra hoops. And read some stackoverflow stuff. And documentation entries. Blergh...
Anyway, here's the idea: we want to get Panther working with Chromium in a DDEV context, and if you try that just using your "standard" DDEV config, you will be greeted by the following error:
Seems obvious enough; just run that entire suggestion, right? Except
vendor/bin/bdi detect driversdoes not do anything. That is because our web container is lacking Chromium. Let's fix that:Awesome, lots of installation text. Run
vendor/bin/bdi detect driversagain, and hooray:Try to run the tests again:
php ./vendor/bin/simple-phpunit. I do so from within the DDEV web container as I am already there, but you could of course also run it from outside. But, alas:If you Google that error a bit, you will find a whole bunch of expert tech talk on configuring Selenium in the context of Python or Java or whatever, all of which is more or less impossible for me to understand properly. But apparently it might be solved by starting the chromium instance with a
--no-sandboxargument. And luckily, the Panther docs cover that topic specifically here: https://symfony.com/doc/current/testing/end_to_end.html#chrome-specific-environment-variables. UsePANTHER_NO_SANDBOXto "Disable Chrome's sandboxing (unsafe, but allows to use Panther in containers)" - that sounds like it is exactly what we need. Add this to your.env.test.local:If you now run the tests again, things will appear to work. Hooray, right? Except the browser that is running here is not finding your assets. It is explained in the main script how you need to use the
tests/router.phpto get this to work, but you also need to start the Chromium browser with the extra environment argument--disable-dev-shm-usage. This can be added to.env.test.localas well:Note: these
.envthings can of course also be added tophpunit.xml.distas<server>tags under<php>, but since we are assuming DDEV to be a purely local develoment environment, we do not want to activate all this stuff in a version controlled file.TLDR: let us automate a great deal of this process in DDEV by working with a custom Dockerfile and a custom phpunit DDEV command.
File:
.ddev/web-build/Dockerfile.chromium:File:
.ddev/commands/web/phpunitYou may also want to add
/driversto your local.gitignore, as this is probably only useful for local development. No need to pester your non-containered colleagues with it.Do not forget our
.env.test.localfile:And finally, remember to have
dbrekelmans/bdias a composer dev package throughcomposer require dbrekelmans/bdi --dev.With these things in place, all you need to do to get started on an otherwise standard DDEV config is:
Your initial DDEV start-up will take some time due to Chromium installation, but I haven't found a way around using the full Chrome and that takes a while to install... Maybe some other
glorious fooltech hero can figure that out.Yo @TomDeRoo!
This is a crazy amount of work I'd love for us to make it LESS work but for now, your comment can at least be here to help.
Thanks!
Hey @TomDeRoo
Nicely done, thank you for sharing your solution with others!
Cheers!
I was struggling a bit with issues with the
->click('New Voyage')resulting in the dialog not opening.Eventually, it turned out that the first line
$this->client()->waitFor('html[aria-busy="true"]');in thewaitForPageLoad()method was preventing this from working. Any ideas why?Anyway, I've commented it out and the dialog is displaying and tests are all green again.
Hey @apphancer
That's unexpected. I believe your site is running so fast that Turbo finishes loading before your
waitFor()call. IIRC the second argument of that method is the amount of milliseconds it should wait before it "gives up", you could set it to 1 second so it doesn't wait for too long.Let me know if it worked or if I'm completely wrong :P
Cheers!
Thanks for the suggestion. I gave it a shot but no luck. Looking at the images in the error-screenshot folder, it looks like the /voyage page loads but no dialog opens.
This is the actual error:
There was 1 error:
1) App\Tests\Functional\VoyageControllerTest::testCreateVoyage
Facebook\WebDriver\Exception\TimeoutException:
/Users/m/Desktop/code-last-stack/vendor/php-webdriver/webdriver/lib/WebDriverWait.php:71
I don't really get it why it's saying that it's timing out because of that line, even when I've reduced the $timeoutInSecond parameter to 1 second.
It's no big deal. As I said, it's working after having commented out the first line of the waitForPageLoad() method. It's more curiosity than anything else.
Yea, that's intriguing, but sadly I don't know the answer. At least you found a solution :)
Let me know if you discover the mystery. Cheers!
"Houston: no signs of life"
Start the conversation!