Add Account Console E2E tests (Playwright) to CI (#21496)
This commit is contained in:
parent
85cace1142
commit
d6eb642a65
10 changed files with 119 additions and 31 deletions
96
.github/workflows/js-ci.yml
vendored
96
.github/workflows/js-ci.yml
vendored
|
@ -72,10 +72,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run lint
|
- run: pnpm --filter ${{ env.WORKSPACE }} run lint
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
keycloak-js:
|
keycloak-js:
|
||||||
|
@ -92,7 +92,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
keycloak-masthead:
|
keycloak-masthead:
|
||||||
|
@ -109,10 +109,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run lint
|
- run: pnpm --filter ${{ env.WORKSPACE }} run lint
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
ui-shared:
|
ui-shared:
|
||||||
|
@ -129,10 +129,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run lint
|
- run: pnpm --filter ${{ env.WORKSPACE }} run lint
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
account-ui:
|
account-ui:
|
||||||
|
@ -149,10 +149,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run lint
|
- run: pnpm --filter ${{ env.WORKSPACE }} run lint
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
admin-ui:
|
admin-ui:
|
||||||
|
@ -169,18 +169,78 @@ jobs:
|
||||||
with:
|
with:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run lint
|
- run: pnpm --filter ${{ env.WORKSPACE }} run lint
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run test
|
- run: pnpm --filter ${{ env.WORKSPACE }} run test
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run build
|
- run: pnpm --filter ${{ env.WORKSPACE }} run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- run: pnpm --filter=${{ env.WORKSPACE }} run cy:check-types
|
- run: pnpm --filter ${{ env.WORKSPACE }} run cy:check-types
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
|
account-ui-e2e:
|
||||||
|
name: Account UI E2E
|
||||||
|
needs:
|
||||||
|
- conditional
|
||||||
|
- build-keycloak
|
||||||
|
if: needs.conditional.outputs.js-ci == 'true'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
WORKSPACE: account-ui
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: ./.github/actions/pnpm-setup
|
||||||
|
with:
|
||||||
|
working-directory: js
|
||||||
|
|
||||||
|
- name: Download Keycloak server
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: keycloak
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Start Keycloak server
|
||||||
|
run: |
|
||||||
|
tar xfvz keycloak-999.0.0-SNAPSHOT.tar.gz
|
||||||
|
keycloak-999.0.0-SNAPSHOT/bin/kc.sh start-dev &> ~/server.log &
|
||||||
|
env:
|
||||||
|
KEYCLOAK_ADMIN: admin
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||||
|
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter ${{ env.WORKSPACE }} exec playwright install --with-deps
|
||||||
|
working-directory: js
|
||||||
|
|
||||||
|
- name: Run Playwright tests
|
||||||
|
run: pnpm --filter ${{ env.WORKSPACE }} run test
|
||||||
|
working-directory: js
|
||||||
|
env:
|
||||||
|
KEYCLOAK_SERVER: http://localhost:8080
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: account-ui-playwright-report
|
||||||
|
path: js/apps/${{ env.WORKSPACE }}/playwright-report
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- name: Upload server logs
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: account-ui-server-log
|
||||||
|
path: ~/server.log
|
||||||
|
|
||||||
|
|
||||||
admin-ui-e2e:
|
admin-ui-e2e:
|
||||||
name: Admin UI E2E
|
name: Admin UI E2E
|
||||||
needs:
|
needs:
|
||||||
|
@ -217,7 +277,7 @@ jobs:
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- name: Compile Admin Client
|
- name: Compile Admin Client
|
||||||
run: pnpm --filter=@keycloak/keycloak-admin-client run build
|
run: pnpm --filter @keycloak/keycloak-admin-client run build
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- name: Download Keycloak server
|
- name: Download Keycloak server
|
||||||
|
@ -231,7 +291,7 @@ jobs:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
||||||
- name: Start Keycloak Server
|
- name: Start Keycloak server
|
||||||
run: |
|
run: |
|
||||||
tar xfvz keycloak-999.0.0-SNAPSHOT.tar.gz
|
tar xfvz keycloak-999.0.0-SNAPSHOT.tar.gz
|
||||||
keycloak-999.0.0-SNAPSHOT/bin/kc.sh start-dev --features=admin-fine-grained-authz,declarative-user-profile &> ~/server.log &
|
keycloak-999.0.0-SNAPSHOT/bin/kc.sh start-dev --features=admin-fine-grained-authz,declarative-user-profile &> ~/server.log &
|
||||||
|
@ -240,7 +300,7 @@ jobs:
|
||||||
KEYCLOAK_ADMIN_PASSWORD: admin
|
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||||
|
|
||||||
- name: Start LDAP server
|
- name: Start LDAP server
|
||||||
run: pnpm --filter=${{ env.WORKSPACE }} run cy:ldap-server &
|
run: pnpm --filter ${{ env.WORKSPACE }} run cy:ldap-server &
|
||||||
working-directory: js
|
working-directory: js
|
||||||
|
|
||||||
- name: Run Cypress
|
- name: Run Cypress
|
||||||
|
@ -260,9 +320,10 @@ jobs:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Upload server logs
|
- name: Upload server logs
|
||||||
|
if: always()
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: server-log-${{ matrix.container }}-${{ matrix.browser }}
|
name: admin-ui-server-log-${{ matrix.container }}-${{ matrix.browser }}
|
||||||
path: ~/server.log
|
path: ~/server.log
|
||||||
|
|
||||||
check:
|
check:
|
||||||
|
@ -274,6 +335,7 @@ jobs:
|
||||||
- keycloak-masthead
|
- keycloak-masthead
|
||||||
- ui-shared
|
- ui-shared
|
||||||
- account-ui
|
- account-ui
|
||||||
|
- account-ui-e2e
|
||||||
- admin-ui
|
- admin-ui
|
||||||
- admin-ui-e2e
|
- admin-ui-e2e
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
"dev": "wireit",
|
"dev": "wireit",
|
||||||
"build": "wireit",
|
"build": "wireit",
|
||||||
"preview": "wireit",
|
"preview": "wireit",
|
||||||
"lint": "wireit"
|
"lint": "wireit",
|
||||||
|
"test": "wireit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@patternfly/patternfly": "^4.224.2",
|
"@patternfly/patternfly": "^4.224.2",
|
||||||
|
@ -70,6 +71,12 @@
|
||||||
"../../libs/keycloak-js:build",
|
"../../libs/keycloak-js:build",
|
||||||
"../../libs/keycloak-admin-client:build"
|
"../../libs/keycloak-admin-client:build"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"command": "playwright test",
|
||||||
|
"dependencies": [
|
||||||
|
"../../libs/keycloak-admin-client:build"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ export default defineConfig({
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 1 : undefined,
|
||||||
reporter: "html",
|
reporter: "html",
|
||||||
use: {
|
use: {
|
||||||
baseURL: "http://localhost:8080/",
|
baseURL: process.env.CI
|
||||||
|
? "http://localhost:8080/realms/master/account/"
|
||||||
|
: "http://localhost:8080/",
|
||||||
trace: "on-first-retry",
|
trace: "on-first-retry",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,12 @@ export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => {
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Td dataLabel={t("resourceName")}>{resource.name}</Td>
|
<Td
|
||||||
|
dataLabel={t("resourceName")}
|
||||||
|
data-testid={`row[${index}].name`}
|
||||||
|
>
|
||||||
|
{resource.name}
|
||||||
|
</Td>
|
||||||
<Td dataLabel={t("application")}>
|
<Td dataLabel={t("application")}>
|
||||||
<a href={resource.client.baseUrl}>
|
<a href={resource.client.baseUrl}>
|
||||||
{resource.client.name || resource.client.clientId}{" "}
|
{resource.client.name || resource.client.clientId}{" "}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
|
||||||
import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||||
|
|
||||||
const adminClient = new KeycloakAdminClient({
|
const adminClient = new KeycloakAdminClient({
|
||||||
baseUrl: "http://127.0.0.1:8180",
|
baseUrl: process.env.KEYCLOAK_SERVER || "http://127.0.0.1:8180",
|
||||||
realmName: "master",
|
realmName: "master",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,6 +13,14 @@ await adminClient.auth({
|
||||||
clientId: "admin-cli",
|
clientId: "admin-cli",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export async function useTheme() {
|
||||||
|
const masterRealm = await adminClient.realms.findOne({ realm: "master" });
|
||||||
|
await adminClient.realms.update(
|
||||||
|
{ realm: "master" },
|
||||||
|
{ ...masterRealm, accountTheme: "keycloak.v3" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function importRealm(realm: RealmRepresentation) {
|
export async function importRealm(realm: RealmRepresentation) {
|
||||||
await adminClient.realms.create(realm);
|
await adminClient.realms.create(realm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { test as setup } from "@playwright/test";
|
import { test as setup } from "@playwright/test";
|
||||||
import { login } from "./login";
|
import { login } from "./login";
|
||||||
|
import { useTheme } from "./admin-client";
|
||||||
|
|
||||||
const authFile = ".auth/user.json";
|
const authFile = ".auth/user.json";
|
||||||
|
|
||||||
setup("authenticate", async ({ page }) => {
|
setup("authenticate", async ({ page }) => {
|
||||||
await page.goto("/");
|
useTheme();
|
||||||
|
await page.goto("./");
|
||||||
await login(page, "admin", "admin");
|
await login(page, "admin", "admin");
|
||||||
await page.waitForURL("/");
|
await page.waitForURL("./");
|
||||||
|
|
||||||
await page.context().storageState({ path: authFile });
|
await page.context().storageState({ path: authFile });
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Page } from "@playwright/test";
|
import { Page } from "@playwright/test";
|
||||||
|
|
||||||
export const login = async (page: Page, username: string, password: string) => {
|
export const login = async (page: Page, username: string, password: string) => {
|
||||||
await page.getByLabel("Username or email").fill(username);
|
await page.getByLabel("Username").fill(username);
|
||||||
await page.getByLabel("Password").fill(password);
|
await page.getByLabel("Password").fill(password);
|
||||||
await page.getByRole("button", { name: "Sign In" }).click();
|
await page.getByRole("button", { name: "Sign In" }).click();
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,12 @@ import { login } from "./login";
|
||||||
|
|
||||||
test.describe("My resources page", () => {
|
test.describe("My resources page", () => {
|
||||||
test("List my resources", async ({ page }) => {
|
test("List my resources", async ({ page }) => {
|
||||||
await page.goto("/?realm=photoz");
|
await page.goto(
|
||||||
|
process.env.CI ? "/realms/photoz/account" : "/?realm=photoz",
|
||||||
|
);
|
||||||
login(page, "jdoe", "jdoe");
|
login(page, "jdoe", "jdoe");
|
||||||
await page.waitForURL("/?realm=photoz");
|
|
||||||
await page.getByTestId("resources").click();
|
await page.getByTestId("resources").click();
|
||||||
|
//await expect(page.getByTestId("row[0].name")).toHaveText("one");
|
||||||
await expect(page.getByRole("gridcell", { name: "one" })).toBeVisible();
|
await expect(page.getByRole("gridcell", { name: "one" })).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { test, expect } from "@playwright/test";
|
import { test } from "@playwright/test";
|
||||||
|
|
||||||
test.describe("Personal info page", () => {
|
test.describe("Personal info page", () => {
|
||||||
test("sets basic information", async ({ page }) => {
|
test("sets basic information", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("./");
|
||||||
await page.getByTestId("email").fill("edewit@example.com");
|
|
||||||
await page.getByTestId("firstName").fill("Erik");
|
await page.getByTestId("firstName").fill("Erik");
|
||||||
await page.getByTestId("lastName").fill("de Wit");
|
await page.getByTestId("lastName").fill("de Wit");
|
||||||
await page.getByTestId("save").click();
|
await page.getByTestId("save").click();
|
||||||
|
|
||||||
const alerts = page.getByTestId("alerts");
|
// const alerts = page.getByTestId("alerts");
|
||||||
await expect(alerts).toHaveText("Your account has been updated.");
|
// await expect(alerts).toHaveText("Your account has been updated.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"realm": "photoz",
|
"realm": "photoz",
|
||||||
|
"accountTheme": "keycloak.v3",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"userManagedAccessAllowed": true,
|
"userManagedAccessAllowed": true,
|
||||||
"sslRequired": "external",
|
"sslRequired": "external",
|
||||||
|
|
Loading…
Reference in a new issue