From 397be240e189ed759ca355a4cfbc5e5c3da7362a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Thu, 18 Jul 2024 17:31:14 +0200 Subject: [PATCH] Drop Playwright support --- .github/workflows/obs-release.yml | 2 +- .github/workflows/obs-staging-playwright.yml | 22 -- README.md | 3 - Rakefile | 9 - doc/yupdate.md | 4 - live/src/agama-installer-openSUSE.changes | 6 + playwright/.gitignore | 6 - playwright/LICENSE | 339 ------------------- playwright/README.md | 233 ------------- playwright/config/agama.yaml | 112 ------ playwright/global-setup.ts | 76 ----- playwright/lib/installer.ts | 15 - playwright/package/_service | 20 -- playwright/package/agama-playwright.changes | 5 - playwright/package/agama-playwright.spec | 52 --- playwright/playwright.config.ts | 77 ----- playwright/tests/main_page.spec.ts | 17 - playwright/tests/root_password.spec.ts | 35 -- playwright/tests/take_screenshots.spec.ts | 121 ------- 19 files changed, 7 insertions(+), 1147 deletions(-) delete mode 100644 .github/workflows/obs-staging-playwright.yml delete mode 100644 playwright/.gitignore delete mode 100644 playwright/LICENSE delete mode 100644 playwright/README.md delete mode 100644 playwright/config/agama.yaml delete mode 100644 playwright/global-setup.ts delete mode 100644 playwright/lib/installer.ts delete mode 100644 playwright/package/_service delete mode 100644 playwright/package/agama-playwright.changes delete mode 100644 playwright/package/agama-playwright.spec delete mode 100644 playwright/playwright.config.ts delete mode 100644 playwright/tests/main_page.spec.ts delete mode 100644 playwright/tests/root_password.spec.ts delete mode 100644 playwright/tests/take_screenshots.spec.ts diff --git a/.github/workflows/obs-release.yml b/.github/workflows/obs-release.yml index 77d1f0049a..2f24512a7d 100644 --- a/.github/workflows/obs-release.yml +++ b/.github/workflows/obs-release.yml @@ -11,7 +11,7 @@ on: - v[0-9]* jobs: - # Note: cockpit-agama-playwright is currently not submitted + # Note: agama-integration-tests and the Live ISO are currently not submitted update_rust: uses: ./.github/workflows/obs-staging-shared.yml diff --git a/.github/workflows/obs-staging-playwright.yml b/.github/workflows/obs-staging-playwright.yml deleted file mode 100644 index dc4a22990f..0000000000 --- a/.github/workflows/obs-staging-playwright.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Submit agama-playwright - -on: - # runs on pushes targeting the default branch - push: - branches: - - master - paths: - # run only when a Playwright source is changed - - playwright/** - - # allow running manually - workflow_dispatch: - -jobs: - update_staging: - uses: ./.github/workflows/obs-staging-shared.yml - # pass all secrets - secrets: inherit - with: - package_name: agama-playwright - service_file: playwright/package/_service diff --git a/README.md b/README.md index 897281f845..5220d6d9ff 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,6 @@ interfaces over it. | ------------------------------------------------------ | --------------------------------------------------------------- | | ![Installing](./doc/images/screenshots/installing.png) | ![Installation finished](./doc/images/screenshots/finished.png) | -_Note for developers: For updating the screenshots see the -[integration test documentation](playwright/README.md#updating-the-screenshots)._ - ## Why a New Installer diff --git a/Rakefile b/Rakefile index e11a7524e8..ec78d0e974 100644 --- a/Rakefile +++ b/Rakefile @@ -177,15 +177,6 @@ if ENV["YUPDATE_FORCE"] == "1" || File.exist?("/.packages.initrd") || live_iso? end end - # update also the tests if they are present in the system - if ENV["YUPDATE_SKIP_TESTS"] != "1" && File.exist?("/usr/share/agama-playwright") - puts "Installing the integration tests..." - - # we are installing into an empty chroot, make sure the target exists - FileUtils.mkdir_p(File.join(destdir, "/usr/share")) - FileUtils.cp_r("playwright/.", File.join(destdir, "/usr/share/agama-playwright")) - end - if ENV["YUPDATE_SKIP_PRODUCTS"] != "1" files = Dir.glob("products.d/*.y{a}ml") files.each do |f| diff --git a/doc/yupdate.md b/doc/yupdate.md index 0792f2a710..aec1863ac7 100644 --- a/doc/yupdate.md +++ b/doc/yupdate.md @@ -59,10 +59,6 @@ You can modify the update process with these environment variables: - `YUPDATE_SKIP_BACKEND=1` - Skip updating the D-Bus service backend. This is similar to the previous option, use it when you do want to keep the D-Bus service unchanged. -- `YUPDATE_SKIP_TESTS=1` - Skip updating the integration tests if they are - installed. If the tests are not installed they are not added automatically. - If you want to add them first create the `/usr/share/agama-playwright` - directory where the tests will be added and then run the `yupdate` command. ## Notes diff --git a/live/src/agama-installer-openSUSE.changes b/live/src/agama-installer-openSUSE.changes index bdf33516df..dc8f179dbc 100644 --- a/live/src/agama-installer-openSUSE.changes +++ b/live/src/agama-installer-openSUSE.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Jul 18 15:25:39 UTC 2024 - Ladislav Slezák + +- Include Puppeteer in all ISO images (gh#openSUSE/agama#1477) +- Drop Playwright ISO flavor (gh#openSUSE/agama#1481) + ------------------------------------------------------------------- Tue Jul 9 13:26:38 UTC 2024 - Knut Anderssen diff --git a/playwright/.gitignore b/playwright/.gitignore deleted file mode 100644 index 27c6b32018..0000000000 --- a/playwright/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules/ -/test-results/ -/playwright-report/ -/playwright/.cache/ -storageState.json -/screenshots/ diff --git a/playwright/LICENSE b/playwright/LICENSE deleted file mode 100644 index d159169d10..0000000000 --- a/playwright/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/playwright/README.md b/playwright/README.md deleted file mode 100644 index 9b5d815f80..0000000000 --- a/playwright/README.md +++ /dev/null @@ -1,233 +0,0 @@ -## Integration Tests - -This directory contains integration tests which use the [Playwright]( -https://playwright.dev/) testing framework. - -## Installation - -To install the Playwright tool run this command in the `playwright` subdirectory: - -```shell -npm install --no-save @playwright/test -``` - -This will install the NPM packages into the `node_modules` subdirectory. - -Alternatively you can install it as an RPM package from the -[systemsmanagement:Agama:Devel](https://build.opensuse.org/project/show/systemsmanagement:Agama:Devel) -OBS project. - -## Files - -- `playwright.config.ts` - Playwright configuration, see [documentation]( - https://playwright.dev/docs/test-configuration) for more details -- `global-setup.ts` - a helper for logging-in -- `tests/\*.spec.ts` - individual test files -- `lib/*` - shared library files - -## Running the Tests - -*Note: If you install Playwright from the RPM package then omit the `npx` -tool from all commands below.* - -By default the tests are used against the local running server, if you -want to test a remote server see the [Target Server](#target-server) -section below. - -To run all tests use this command: - -``` -npx playwright test -``` - -To run just a specific test: - -``` -npx playwright test tests/root_password.spec.ts -``` - -By default it runs tests in all configured projects (browsers), -if you want to use only a specific browser use the `--project` option: - -``` -npx playwright test --project chromium -- tests/root_password.spec.ts -``` - -See the `playwright.config.ts` file for the list of configured projects. - -### Running Tests Directly from the Live ISO - -You can download the `openSUSE-Playwright` image type from the [systemsmanagement:Agama:Devel]( -https://download.opensuse.org/repositories/systemsmanagement:/Agama:/Devel/images/iso/) repository. - -This ISO additionally includes the Playwright tool, Chromium browser and the -Agama integration tests. - -To start a test in a console or in a SSH session use this command: - -``` -playwright test --project chromium --config /usr/share/agama-playwright -``` - -*Note the missing `npx` tool in the command, in this case Playwright is -installed into the system directories.* - -You can also start the tests in headed mode (with `--headed` option) either -via `ssh -X` or using a local X terminal session: - -```shell -# from a Linux console -DISPLAY=:0 xterm & -# then switch to console 7 using the Alt+F7 keyboard shortcut -# and run Playwright from the xterm -``` - -## Updating the Screenshots - -There is one test specially designed for refreshing the screenshots displayed -in the main `README.md` file. - -To fully run the installation type this: - -``` -SCREENSHOT_MODE=1 RUN_INSTALLATION=1 BASE_URL=https://:9090 npx playwright test --headed --project chromium take_screenshots -``` - -The `--headed` option shows the browser window so you can see the progress. -You can use the `--debug` option to run the test step-by-step. - -The screenshots are saved to the `screenshots/` subdirectory. - -## Target Server - -By default the tests use the installer instance running locally at -`http://localhost:9090`. If you want to run the tests against -another instance set the `BASE_URL` environment variable: - -``` -BASE_URL=https://192.168.1.12:9090 npx playwright ... -``` - -You can use it also with the [webpack development server]( -../web/README.md#using-a-development-server): - -``` -BASE_URL=https://localhost:8080/ npx playwright ... -``` - -### Options - -The tests by default run in a headless mode, if you want to see the actions -in the browser use the `--headed` option. - -If you want to manually run a test step by step use the `--debug` option. This -also allows to easily get the object selectors using the `Explore` button. - -## Links - -- https://playwright.dev/docs/intro - Playwright Documentation -- https://playwright.dev/docs/test-assertions - Test assetions (`expect`) -- https://playwright.dev/docs/api/class-locator - Finding the elements on the page - -## Tips for Writing Tests - -The installer runs in another process in a browser, it does not run -synchronously with the test. Additionally the installer uses the React -framework, that means the initial web page is empty and the content is added -asynchronously by Javascript code. - -These features have some consequences for writing the tests. - -### Timeouts - -As mentioned above, the page content is updated asynchronously so if something -is missing on the page it does not mean the test fails immediately. -The tested object might appear on the page after a small delay, -Playwright uses timeouts for most of the checks. If something is missing -then it tries the search again until the timeout is reached. - -The default timeout is set in the `playwright.config.ts` configuration file. -That should be enough for most operations even on a slow machine. -However, for some long running operations like refreshing repositories or -installing packages you might need to use a longer timeout. - -Playwright allows setting explicit timeout for each test or action: - -```js -// refreshing the repositories and evaluating the package dependencies might take long time -await expect(page.getByText("Installation will take")).toBeVisible({timeout: 2 * minute}); -``` - -or you can set how long the whole test should run: - -```js -test.setTimeout(60 * minute); -``` - -### Testing Not Displayed Elements - -This is also related to the asynchronous work. You should never test that something -is NOT displayed on the page because it is not guaranteed that it will not -be displayed one millisecond after you check for it. - -The only exception is that you first check that an element is displayed, do some -action and then check that the element is not displayed anymore. - -```js -// clicking a 'Details' button -await page.getByText('Details').click(); -// opens a modal dialog (popup) -await expect(page.locator('[role="dialog"]')).toBeVisible(); - -// after clicking the 'Close' button -await page.getByText('Close').click(); -// the popup disappears -await expect(page.locator('[role="dialog"]')).not.toBeVisible(); -``` - -The last check actually waits until the popup disappears. It is OK if it takes -some short time to close the popup. - -### Locators - -By default the text locators search for a *substring*! If there are similar -labels present you might get errors for multiple elements found. - -For example when there are "Password" and "Password Confirmation" fields -displayed on the page then simple - -```js -await page.getByLabel('Password').click() -``` - -would actually match *both* elements and Playwright would not know which one you -wanted to click. In that case the test would fail with an error. - -The solution is to use the exact matching: - -```js -await page.getByLabel('Password', { exact: true }).click() -``` - -This will match only one field without any conflict. - -## Troubleshooting Failed Integration Tests in CI - -### Single Test Failure - -There are stored artifacts in the GitHub CI. Go to the failed job and there is -a link "Summary". At the bottom of the page there is "Artifacts" section which -contains the `y2log` and also `trace.zip` file. The trace can be browsed using -the playwright tool locally or at page https://trace.playwright.dev/ to get -details of the failure. - -### Stuck at D-Bus Loading - -It usually indicates an issue with the Agama D-Bus services. There is a step -called "Show D-Bus Services Logs" which should give a hint what is going wrong. -Additional help can be the `y2log` file in the artifacts (see above). - -### Missing Package/Wrong Container - -Packages lives in container at https://build.opensuse.org/package/show/systemsmanagement:Agama:Devel/agama-testing. -Feel free to modify it as the only purpose of this container is CI testing. diff --git a/playwright/config/agama.yaml b/playwright/config/agama.yaml deleted file mode 100644 index cff3888d3f..0000000000 --- a/playwright/config/agama.yaml +++ /dev/null @@ -1,112 +0,0 @@ ---- -products: - Tumbleweed: - name: openSUSE Tumbleweed - description: The Tumbleweed distribution is a pure rolling release version of - openSUSE containing the latest "stable" versions of all software instead of - relying on rigid periodic release cycles. The project does this for users that - want the newest stable software. -web: - ssl: - ssl_cert: - ssl_key: -Tumbleweed: - software: - installation_repositories: - - url: https://download.opensuse.org/tumbleweed/repo/oss/ - archs: x86_64 - - url: https://download.opensuse.org/ports/aarch64/tumbleweed/repo/oss/ - archs: aarch64 - - url: https://download.opensuse.org/ports/zsystems/tumbleweed/repo/oss/ - archs: s390 - - url: https://download.opensuse.org/ports/ppc/tumbleweed/repo/oss/ - archs: ppc - - url: https://download.opensuse.org/tumbleweed/repo/non-oss/ - archs: x86_64 - - url: https://download.opensuse.org/ports/zsystems/tumbleweed/repo/non-oss/ - archs: s390 - - url: https://download.opensuse.org/ports/ppc/tumbleweed/repo/non-oss/ - archs: ppc - - url: https://download.opensuse.org/update/tumbleweed/ - archs: x86_64 - - url: https://download.opensuse.org/ports/aarch64/update/tumbleweed/ - archs: aarch64 - - url: https://download.opensuse.org/ports/zsystems/update/tumbleweed/ - archs: s390 - - url: https://download.opensuse.org/ports/ppc/tumbleweed/repo/oss/ - archs: ppc - mandatory_patterns: - - enhanced_base - optional_patterns: - mandatory_packages: - - NetworkManager - optional_packages: - base_product: openSUSE - security: - lsm: apparmor - available_lsms: - apparmor: - patterns: - - apparmor - selinux: - patterns: - - selinux - policy: permissive - none: - patterns: - storage: - volumes: - - mount_point: "/" - fs_type: btrfs - min_size: 5 GiB - max_size: 15 GiB - weight: 1 - proposed_configurable: false - snapshots: true - snapshots_percentage: 250 - snapshots_configurable: true - disable_order: 3 - btrfs_default_subvolume: "@" - subvolumes: - - path: home - - path: opt - - path: root - - path: srv - - path: usr/local - - path: var - copy_on_write: false - - path: boot/grub2/arm64-efi - archs: aarch64 - - path: boot/grub2/arm-efi - archs: arm - - path: boot/grub2/i386-pc - archs: x86_64 - - path: boot/grub2/powerpc-ieee1275 - archs: ppc,!board_powernv - - path: boot/grub2/s390x-emu - archs: s390 - - path: boot/grub2/x86_64-efi - archs: x86_64 - - path: boot/grub2/riscv64-efi - archs: riscv64 - - mount_point: "/home" - fs_type: xfs - min_size: 10 GiB - max_size: unlimited - max_size_lvm: unlimited - weight: 1 - proposed: false - proposed_configurable: true - disable_order: 1 - fallback_for_max_size: "/" - fallback_for_max_size_lvm: "/" - - mount_point: swap - fs_type: swap - desired_size: 2 GiB - min_size: 1 GiB - max_size: 2 GiB - weight: 1 - adjust_by_ram: false - adjust_by_ram_configurable: true - proposed_configurable: true - disable_order: 2 diff --git a/playwright/global-setup.ts b/playwright/global-setup.ts deleted file mode 100644 index ff16dc3309..0000000000 --- a/playwright/global-setup.ts +++ /dev/null @@ -1,76 +0,0 @@ -// See https://playwright.dev/docs/auth#reuse-signed-in-state -// and https://playwright.dev/docs/test-global-setup-teardown -import { expect, chromium, firefox, FullConfig, BrowserType, FullProject } from '@playwright/test'; -const fs = require('fs'); - -function browserType(typeName:string):BrowserType { - if (typeName === "firefox") { - return firefox; - } else if (typeName === "chromium") { - return chromium; - } else { - throw new Error(`Unsupported browser type "${typeName}"`); - } -} - -// find the project (browser) to use for logging in: -// - specified by the "--project" command line option -// - or find the first installed browser -function findProject(config: FullConfig):FullProject { - let project : FullProject; - - const optionIndex = process.argv.findIndex(a => a === "--project"); - if (optionIndex >= 0) { - const projectName = process.argv[optionIndex + 1]; - project = config.projects.find(p => p.name === projectName); - } - else { - project = config.projects.find(p => fs.existsSync(p.use.launchOptions.executablePath)); - } - - if (project === undefined) { - throw new Error("Web browser not found"); - } - - return project; -} - -async function globalSetup(config: FullConfig) { - // baseURL and storageState are the same for all projects, use the first one - const { baseURL, storageState } = config.projects[0].use; - // storage not configure => login was disabled - if (storageState === undefined) return; - - const project = findProject(config); - const browser = await browserType(project.use.defaultBrowserType).launch(project.use.launchOptions); - const page = await browser.newPage({ - baseURL, - ignoreHTTPSErrors: true - }); - - // go to the terminal app to see if the user needs to log into the system - await page.goto("/cockpit/@localhost/system/terminal.html"); - - // login page displayed? - try { - await page.waitForSelector("#login-user-input", { timeout: 5000 }); - } - catch { - // form not found, login not required - return; - } - - await page.getByLabel('User name').fill('root'); - await page.getByLabel('Password', { exact: true }).fill('linux'); - - await page.getByRole('button', { name: 'Log in' }).click(); - - await expect(page.getByLabel('Password', { exact: true })).not.toBeVisible(); - - // Save the signed-in state to a file - await page.context().storageState({ path: storageState as string }); - - await browser.close(); -} - -export default globalSetup; diff --git a/playwright/lib/installer.ts b/playwright/lib/installer.ts deleted file mode 100644 index 8c547e3677..0000000000 --- a/playwright/lib/installer.ts +++ /dev/null @@ -1,15 +0,0 @@ -// shared functions - -// return the URL path to the installer plugin -function mainPagePath():string { - let baseURL = new URL(process.env.BASE_URL || "http://localhost:9090"); - - // when running at the default cockpit port use the full cockpit path, - // otherwise expect the webpack development server where the installer - // is available at the root path - return (baseURL.port == "9090") ? "/cockpit/@localhost/agama/index.html" : "/"; -} - -export { - mainPagePath -}; diff --git a/playwright/package/_service b/playwright/package/_service deleted file mode 100644 index 183d4985f7..0000000000 --- a/playwright/package/_service +++ /dev/null @@ -1,20 +0,0 @@ - - - @PARENT_TAG@+@TAG_OFFSET@ - v(.*) - https://github.com/openSUSE/agama.git - git - master - playwright - enable - package/agama-playwright.changes - package/agama-playwright.spec - - - agama.obsinfo - agama - - - agama - - diff --git a/playwright/package/agama-playwright.changes b/playwright/package/agama-playwright.changes deleted file mode 100644 index 6f7f7dfd40..0000000000 --- a/playwright/package/agama-playwright.changes +++ /dev/null @@ -1,5 +0,0 @@ -------------------------------------------------------------------- -Thu Mar 30 07:32:54 UTC 2023 - Ladislav Slezák - -- Initial version - diff --git a/playwright/package/agama-playwright.spec b/playwright/package/agama-playwright.spec deleted file mode 100644 index 35d2be7dd7..0000000000 --- a/playwright/package/agama-playwright.spec +++ /dev/null @@ -1,52 +0,0 @@ -# -# spec file for package agama-playwright -# -# Copyright (c) 2023 SUSE LLC -# -# All modifications and additions to the file contributed by third parties -# remain the property of their copyright owners, unless otherwise agreed -# upon. The license for this file, and modifications and additions to the -# file, is the same license as for the pristine package itself (unless the -# license for the pristine package is not an Open Source License, in which -# case the license is the MIT License). An "Open Source License" is a -# license that conforms to the Open Source Definition (Version 1.9) -# published by the Open Source Initiative. - -# Please submit bugfixes or comments via https://bugs.opensuse.org/ -# - - -Name: agama-playwright -Version: 0 -Release: 0 -Summary: Integration tests for the Agama installer -License: GPL-2.0-only -URL: https://github.com/openSUSE/agama -# source_validator insists that if obscpio has no version then -# tarball must neither -Source0: agama.tar -BuildArch: noarch -BuildRequires: coreutils -Requires: playwright - -%description -Playwright integration tests for the Agama installer. - -%prep -%autosetup -p1 -n agama - -%build - -%install -mkdir -p %{buildroot}%{_datadir} -tar -xf %{SOURCE0} -C %{buildroot}%{_datadir} -# rename the target directory -mv %{buildroot}%{_datadir}/agama %{buildroot}%{_datadir}/agama-playwright - -%files -%defattr(-,root,root,-) -%doc README.md -%license LICENSE -%{_datadir}/agama-playwright - -%changelog diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts deleted file mode 100644 index da6f8a5a51..0000000000 --- a/playwright/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * Read environment variables from file. - * https://github.com/motdotla/dotenv - */ -// require('dotenv').config(); - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 60 * 1000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 60 * 1000 - }, - /* Do not run tests in files in parallel by default */ - fullyParallel: false, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Because of test dependencies or race conditions run all tests in sequence, */ - /* later we could use a serial-parallel approach using the test lists, */ - /* see https://playwright.dev/docs/test-parallel#use-a-test-list-file */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: process.env.GITHUB_ACTIONS ? 'github' : 'list', - globalSetup: require.resolve('./global-setup'), - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 30000, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: process.env.BASE_URL || 'http://localhost:9090', - - /* load signed-in state from 'storageState.json' */ - storageState: process.env.SKIP_LOGIN ? undefined : 'storageState.json', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - contextOptions: { - ignoreHTTPSErrors: true - }, - launchOptions: { - executablePath: '/usr/bin/chromium', - }, - }, - }, - { - name: 'firefox', - use: { - ...devices['Desktop Firefox'], - contextOptions: { - ignoreHTTPSErrors: true - }, - launchOptions: { - executablePath: '/usr/bin/firefox', - }, - }, - }, - ], -}; - -export default config; diff --git a/playwright/tests/main_page.spec.ts b/playwright/tests/main_page.spec.ts deleted file mode 100644 index abdf8cbaa1..0000000000 --- a/playwright/tests/main_page.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { test, expect } from '@playwright/test'; -import { mainPagePath } from "../lib/installer"; - -test.describe('The main page', () => { - test.beforeEach(async ({ page }) => { - await page.goto(mainPagePath()); - }); - - test('has the "Agama" title', async ({ page }) => { - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Agama/); - }); - - test('has the Install button', async ({ page }) => { - await expect(page.getByRole('button', { name: 'Install', exact: true })).toBeVisible(); - }); -}) diff --git a/playwright/tests/root_password.spec.ts b/playwright/tests/root_password.spec.ts deleted file mode 100644 index 93ea8a8332..0000000000 --- a/playwright/tests/root_password.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { test, expect } from '@playwright/test'; -import { mainPagePath } from "../lib/installer"; - -test.describe('The user section', () => { - test.beforeEach(async ({ page }) => { - await page.goto(mainPagePath()); - }); - - test('can set the root password', async ({ page }) => { - // See https://playwright.dev/docs/api/class-locator - - // initial expectation - the root password is not configured yet - await expect(page.getByText("No root authentication method defined")).toBeVisible(); - - // click the "Users" header - await page.locator("a[href='#/users']").click(); - - // click on the "Set a password" button - await page.getByRole("button", { name: "Set a password" }).click(); - - // fill a new password - await page.locator('#password').fill('agama'); - await page.locator('#passwordConfirmation').fill('agama'); - await page.locator('button[type="submit"]').click(); - - // wait until the popup is closed - await expect(page.locator('[role="dialog"]')).not.toBeVisible(); - - // go back to the main page - await page.getByRole('button', { name: 'Back', exact: true }).click(); - - // check the summary text - await expect(page.getByText("Root authentication set")).toBeVisible(); - }); -}) diff --git a/playwright/tests/take_screenshots.spec.ts b/playwright/tests/take_screenshots.spec.ts deleted file mode 100644 index d4853e412b..0000000000 --- a/playwright/tests/take_screenshots.spec.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { test, expect } from "@playwright/test"; -import { mainPagePath } from "../lib/installer"; - -// This test was designed for collecting the screenshots for the main -// README.md file. To take screenshots of the installation process run this: -// -// RUN_INSTALLATION=1 BASE_URL=https:// npx playwright test --headed take_screenshots -// -// The "--headed" option shows the browser window so you can see the progress. -// You can use the "--debug" option to run the test step-by-step. -// The screenshots are saved to the "screenshots/" subdirectory. - -// minute in miliseconds -const minute = 60 * 1000; - -test.describe("The Installer", () => { - test.beforeEach(async ({ page }) => { - await page.goto(mainPagePath()); - }); - - test("installs the system", async ({ page }) => { - // maximum time for this test to run - test.setTimeout(60 * minute); - - if (process.env.SCREENSHOT_MODE === "1") { - // set screenshot size to 768x1024 - page.setViewportSize({ width: 768, height: 1024 }); - } - - // optional actions done on the page - const actions = Object.freeze({ - setProduct: Symbol("product"), - setPassword: Symbol("password"), - done: Symbol("done") - }); - - // check for multiple texts in parallel, avoid waiting for timeouts - let action = await Promise.any([ - page.getByText("Product selection").waitFor().then(() => actions.setProduct), - page.getByText("No root authentication method").waitFor().then(() => actions.setPassword), - page.getByText("Root authentication set").waitFor().then(() => actions.done), - ]); - - // optional product selection - if (action === actions.setProduct) { - await test.step("Select the product", async () => { - // select openSUSE Tumbleweed - await page.getByText("openSUSE Tumbleweed").click(); - await page.screenshot({ path: "screenshots/product-selection.png" }); - await page.getByRole("button", { name: "Select" }).click(); - }); - - // update the action for the next step - action = await Promise.any([ - page.getByText("No root authentication method").waitFor().then(() => actions.setPassword), - page.getByText("Root authentication set").waitFor().then(() => actions.done), - ]); - } - - if (action === actions.setPassword) { - // the the root password must be set - await test.step("Set the root password", async () => { - await page.locator("a[href='#/users']").click(); - // Create users page screenshot - await page.screenshot({ path: "screenshots/users-page.png" }); - // click on the "Set a password" button - await page.getByRole("button", { name: "Set a password" }).click(); - await page.locator("#password").fill("linux"); - await page.locator("#passwordConfirmation").fill("linux"); - await page.locator('button[type="submit"]').click(); - await page.getByText("Back").click(); - }); - } - - // ensure the software proposal is ready, use longer timeout, - // refreshing the repositories takes some time - await expect(page.getByText("Installation will take")).toBeVisible({timeout: 2 * minute}); - await page.screenshot({ path: "screenshots/overview.png" }); - - await test.step("Storage configuration", async () => { - // create storage page screenshot - await page.locator("a[href='#/storage']").click(); - await expect(page.getByRole("heading", { name: "Settings" })).toBeVisible(); - // skip this in GitHub CI, there is no suitable disk for installation - if (process.env.GITHUB_ACTIONS !== "true") { - await expect(page.getByText("Installation device")).toBeVisible({timeout: minute / 2}); - } - await page.screenshot({ path: "screenshots/storage-page.png" }); - }); - - // confirm the installation only when explicitly set via the environment - if (process.env.RUN_INSTALLATION === "1") { - await test.step("Run installation", async () => { - // start the installation - await page.getByRole("button", { name: "Install", exact: true }).click(); - await expect(page.getByText("Confirm Installation")).toBeVisible(); - await page.getByRole("button", { name: "Continue" }).click(); - - // wait for the package installation progress - await expect(page.getByText("Installing packages")).toBeVisible({timeout: 5 * minute}); - - // create package installation screenshot every half a minute - let screenshot_index = 0; - while (true) { - await page.screenshot({ path: `screenshots/installation_${screenshot_index++}.png` }); - - try { - await page.getByRole("heading", { name: "Congratulations!" }).waitFor({timeout: minute / 2}); - // the finish screen is displayed - await page.screenshot({ path: "screenshots/finished.png" }); - break; - } - catch (error) { - // do not ignore other errors - if (error.constructor.name !== "TimeoutError") throw(error); - } - } - }); - } - }); -})