Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test fixes, improved Playwright tests #496

Merged
merged 1 commit into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ jobs:
- name: Git Checkout
uses: actions/checkout@v3

- name: Configure and refresh repositories
# disable unused repositories to have faster refresh
run: zypper modifyrepo -d repo-non-oss repo-openh264 repo-update && ( zypper ref || zypper ref || zypper ref )

- name: Install Ruby development files
run: zypper --non-interactive install gcc gcc-c++ make openssl-devel ruby-devel npm augeas-devel

Expand Down Expand Up @@ -148,6 +152,10 @@ jobs:
- name: Git Checkout
uses: actions/checkout@v3

- name: Configure and refresh repositories
# disable unused repositories to have faster refresh
run: zypper modifyrepo -d repo-non-oss repo-openh264 repo-update && ( zypper ref || zypper ref || zypper ref )

- name: Install Ruby development files
run: zypper --non-interactive install gcc gcc-c++ make openssl-devel ruby-devel npm augeas-devel

Expand Down
72 changes: 72 additions & 0 deletions playwright/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,75 @@
## 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
```

This will install the NPM packages into the `node_modules` subdirectory
and download the browsers into the `~/.cache/ms-playwright` directory.

*Note: The downloaded browsers need almost 1GB, make sure you have enough
space in your `$HOME` directory.*

## 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

To run all tests use this command:

```
npx playwright test
```

To run just a specific test:

```
npx playwright test tests/root_password.spec.ts
```

## 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

## Troubleshooting Failed Integration Tests in CI

### Single Test Failure
Expand Down
14 changes: 13 additions & 1 deletion playwright/global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { expect, chromium, FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
// explicitly skip login if you know it is not needed,
// this avoids waiting for the timeout
if (process.env.SKIP_LOGIN) return;

const browser = await chromium.launch();
Expand All @@ -10,7 +12,17 @@ async function globalSetup(config: FullConfig) {
ignoreHTTPSErrors: true
});

await page.goto('/cockpit/@localhost/d-installer/index.html');
// 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').fill('linux');
Expand Down
15 changes: 15 additions & 0 deletions playwright/lib/installer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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/d-installer/index.html" : "/";
}

export {
mainPagePath
};
3 changes: 2 additions & 1 deletion playwright/tests/main_page.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { test, expect } from '@playwright/test';
import { mainPagePath } from "../lib/installer";

test.describe('The main page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/cockpit/@localhost/d-installer/index.html');
await page.goto(mainPagePath());
});

test('has the "D-Installer" title', async ({ page }) => {
Expand Down
28 changes: 21 additions & 7 deletions playwright/tests/root_password.spec.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import { test, expect } from '@playwright/test';
import { mainPagePath } from "../lib/installer";

test.describe('The user section', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/cockpit/@localhost/d-installer/index.html');
await page.goto(mainPagePath());
});

test('can set the root password', async ({ page }) => {
// See https://playwright.dev/docs/selectors#text-selector
// click the button
await page.locator('text=Root password is not set').locator('button').click();
// See https://playwright.dev/docs/api/class-locator

// initial expectation - the root password is not configured yet
await expect(page.getByText("None authentication method defined for root user")).toBeVisible();

// click the "Users" header
await page.locator("a[href='#/users']").click();

// display the actions menu for the root password
await page.locator("#actions-for-root-password").click();

// click the "Set" item
await page.getByRole("menuitem", { name: "Set" }).click();

// fill a new password
await page.locator('#password').fill('d-installer');
await page.locator('#passwordConfirmation').fill('d-installer');
await page.locator('button[type="submit"]').click();

// wait until the dialog is closed
await expect(page.locator('[role="dialog"]')).toHaveCount(0);
// wait until the popup is closed
await expect(page.locator('[role="dialog"]')).not.toBeVisible();

// go back to the main page
await page.getByText('Back').click();

// check the summary text
await expect(page.locator('text=Root password is set')).toHaveCount(1);
await expect(page.getByText("Root authentication set")).toBeVisible();
});
})