Add first Playwright test for the Account Console (#20809)

This commit is contained in:
Erik Jan de Wit 2023-06-20 14:49:48 +02:00 committed by GitHub
parent 7d3423ca5f
commit 2beedcc4c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 156 additions and 3 deletions

4
js/apps/account-ui/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/test-results/
/playwright-report/
/playwright/.cache/
.auth/

View file

@ -24,6 +24,7 @@
"ui-shared": "workspace:*" "ui-shared": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.35.1",
"@types/lodash-es": "^4.17.7", "@types/lodash-es": "^4.17.7",
"@types/react": "^18.2.13", "@types/react": "^18.2.13",
"@types/react-dom": "^18.2.6", "@types/react-dom": "^18.2.6",

View file

@ -0,0 +1,86 @@
import { defineConfig, devices } from "@playwright/test";
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./test",
/* Run tests in files in parallel */
fullyParallel: true,
/* 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,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:8080/",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{ name: "setup", testMatch: /.*\.setup\.ts/ },
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
storageState: ".auth/user.json",
},
dependencies: ["setup"],
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
storageState: ".auth/user.json",
},
dependencies: ["setup"],
},
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});

View file

@ -47,6 +47,7 @@ export const FormField = ({ attribute }: FormFieldProps) => {
control={control} control={control}
render={({ field }) => ( render={({ field }) => (
<Select <Select
data-testid={attribute.name}
toggleId={attribute.name} toggleId={attribute.name}
onToggle={toggle} onToggle={toggle}
onSelect={(_, value) => { onSelect={(_, value) => {
@ -79,6 +80,7 @@ export const FormField = ({ attribute }: FormFieldProps) => {
/> />
) : ( ) : (
<KeycloakTextInput <KeycloakTextInput
data-testid={attribute.name}
id={attribute.name} id={attribute.name}
isDisabled={attribute.readOnly} isDisabled={attribute.readOnly}
{...register(fieldName(attribute.name), { {...register(fieldName(attribute.name), {

View file

@ -83,10 +83,20 @@ const PersonalInfo = () => {
))} ))}
</FormProvider> </FormProvider>
<ActionGroup> <ActionGroup>
<Button type="submit" id="save-btn" variant="primary"> <Button
data-testid="save"
type="submit"
id="save-btn"
variant="primary"
>
{t("doSave")} {t("doSave")}
</Button> </Button>
<Button id="cancel-btn" variant="link" onClick={() => reset()}> <Button
data-testid="cancel"
id="cancel-btn"
variant="link"
onClick={() => reset()}
>
{t("doCancel")} {t("doCancel")}
</Button> </Button>
</ActionGroup> </ActionGroup>

View file

@ -148,6 +148,7 @@ const NavLink = ({
return ( return (
<NavItem <NavItem
data-testid={to}
to={href} to={href}
isActive={isActive} isActive={isActive}
onClick={(event) => onClick={(event) =>

View file

@ -0,0 +1,15 @@
import { test as setup } from "@playwright/test";
const authFile = ".auth/user.json";
setup("authenticate", async ({ page }) => {
await page.goto("/");
await page.getByRole("link", { name: "Personal info" }).click();
const userName = page.getByLabel("Username or email");
await userName.fill("admin");
await page.getByLabel("Password").fill("admin");
await page.getByRole("button", { name: "Sign In" }).click();
await page.waitForURL("/#/personal-info");
await page.context().storageState({ path: authFile });
});

View file

@ -0,0 +1,14 @@
import { test, expect } from "@playwright/test";
test.describe("Personal info page", () => {
test("Setting last and first name", async ({ page }) => {
await page.goto("/");
await page.getByTestId("personal-info").click();
await page.getByTestId("firstName").fill("Erik");
await page.getByTestId("lastName").fill("de Wit");
await page.getByTestId("save").click();
const alerts = page.getByTestId("alerts");
await expect(alerts).toHaveText("Your account has been updated.");
});
});

View file

@ -59,7 +59,7 @@ export const AlertProvider = ({ children }: PropsWithChildren) => {
return ( return (
<AlertContext.Provider value={{ addAlert, addError }}> <AlertContext.Provider value={{ addAlert, addError }}>
<AlertGroup isToast> <AlertGroup isToast data-testid="alerts">
{alerts.map(({ id, variant, message, description }) => ( {alerts.map(({ id, variant, message, description }) => (
<Alert <Alert
key={id} key={id}

View file

@ -114,6 +114,9 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../libs/ui-shared version: link:../../libs/ui-shared
devDependencies: devDependencies:
'@playwright/test':
specifier: ^1.35.1
version: 1.35.1
'@types/lodash-es': '@types/lodash-es':
specifier: ^4.17.7 specifier: ^4.17.7
version: 4.17.7 version: 4.17.7
@ -1180,6 +1183,17 @@ packages:
tslib: 2.5.3 tslib: 2.5.3
dev: true dev: true
/@playwright/test@1.35.1:
resolution: {integrity: sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==}
engines: {node: '>=16'}
hasBin: true
dependencies:
'@types/node': 20.3.1
playwright-core: 1.35.1
optionalDependencies:
fsevents: 2.3.2
dev: true
/@reactflow/background@11.2.3(react-dom@18.2.0)(react@18.2.0): /@reactflow/background@11.2.3(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-hFoxKt7ZkQclM7CXg7p3EHb+ngUslqFq122Gsrj55N5rFeEdtIkWHuoi+WS0dLRVfX+acuUs6hZl8JuC/JtQ7g==} resolution: {integrity: sha512-hFoxKt7ZkQclM7CXg7p3EHb+ngUslqFq122Gsrj55N5rFeEdtIkWHuoi+WS0dLRVfX+acuUs6hZl8JuC/JtQ7g==}
peerDependencies: peerDependencies:
@ -5378,6 +5392,12 @@ packages:
pathe: 1.1.1 pathe: 1.1.1
dev: true dev: true
/playwright-core@1.35.1:
resolution: {integrity: sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==}
engines: {node: '>=16'}
hasBin: true
dev: true
/popper.js@1.16.1: /popper.js@1.16.1:
resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==} resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==}
deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1