mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-28 04:13:22 -04:00
Fix/issue 46081 fetch with error throwing network error (#47597)
Some checks are pending
Weblate Sync / Trigger Weblate to pull the latest changes (push) Waiting to run
Some checks are pending
Weblate Sync / Trigger Weblate to pull the latest changes (push) Waiting to run
closes #46081 Signed-off-by: Jimmy Chakkalakal <jimmy.chakkalakal@ibm.com>
This commit is contained in:
parent
be17c5e747
commit
f1055ab5ab
3 changed files with 98 additions and 29 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { assertLastAlert, login } from "../support/actions.ts";
|
||||
import { createTestBed } from "../support/testbed.ts";
|
||||
import { retryOperation, waitForRealmReady } from "../support/test-utils.ts";
|
||||
import userProfile from "./user-profile.json" with { type: "json" };
|
||||
import { adminClient } from "../support/admin-client.ts";
|
||||
import userProfileRealm from "../realms/user-profile-realm.json" with { type: "json" };
|
||||
|
|
@ -23,68 +24,80 @@ test.describe("Personal info", () => {
|
|||
test.describe("Personal info (user profile enabled)", () => {
|
||||
test("renders user profile fields", async ({ page }) => {
|
||||
await using testBed = await createTestBed(userProfileRealm);
|
||||
await waitForRealmReady();
|
||||
|
||||
await adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
});
|
||||
await retryOperation(() =>
|
||||
adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
}),
|
||||
);
|
||||
await login(page, testBed.realm);
|
||||
|
||||
await expect(page.locator("#select")).toBeVisible();
|
||||
await expect(page.getByTestId("help-label-select")).toBeVisible();
|
||||
await expect(page.getByText("Alternative email")).toHaveCount(1);
|
||||
await expect(page.getByPlaceholder("Deutsch")).toHaveCount(1);
|
||||
await expect(page.getByText("Alternative email")).toBeVisible();
|
||||
await expect(page.getByPlaceholder("Deutsch")).toBeVisible();
|
||||
await page.getByTestId("help-label-email2").click();
|
||||
await expect(page.getByText("Español")).toHaveCount(1);
|
||||
await expect(page.getByText("Español")).toBeVisible();
|
||||
});
|
||||
|
||||
test("renders long select options as typeahead", async ({ page }) => {
|
||||
await using testBed = await createTestBed(userProfileRealm);
|
||||
await waitForRealmReady();
|
||||
|
||||
await adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
});
|
||||
await retryOperation(() =>
|
||||
adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
}),
|
||||
);
|
||||
await login(page, testBed.realm);
|
||||
|
||||
await page.locator("#alternatelang").click();
|
||||
await page.waitForSelector("text=Italiano");
|
||||
await expect(page.getByText("Italiano")).toBeVisible();
|
||||
|
||||
await page.locator("#alternatelang").click();
|
||||
await page.locator("*:focus").press("Control+A");
|
||||
await page.locator("*:focus").pressSequentially("S");
|
||||
await expect(page.getByText("Italiano")).toHaveCount(0);
|
||||
await expect(page.getByText("Italiano")).toBeHidden();
|
||||
await expect(page.getByText("Slovak")).toBeVisible();
|
||||
await expect(page.getByText('Create "S"')).toBeHidden();
|
||||
});
|
||||
|
||||
test("renders long list of locales as typeahead", async ({ page }) => {
|
||||
await using testBed = await createTestBed(userProfileRealm);
|
||||
await waitForRealmReady();
|
||||
|
||||
await adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
});
|
||||
await retryOperation(() =>
|
||||
adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
}),
|
||||
);
|
||||
await login(page, testBed.realm);
|
||||
|
||||
await page.locator("#attributes\\.locale").click();
|
||||
await page.waitForSelector("text=Italiano");
|
||||
await expect(page.getByText("Italiano")).toBeVisible();
|
||||
|
||||
await page.locator("#attributes\\.locale").click();
|
||||
await page.locator("*:focus").press("Control+A");
|
||||
await page.locator("*:focus").pressSequentially("S");
|
||||
await expect(page.getByText("Italiano")).toHaveCount(0);
|
||||
await expect(page.getByText("Italiano")).toBeHidden();
|
||||
await expect(page.getByText("Slovak")).toBeVisible();
|
||||
await expect(page.getByText('Create "S"')).toBeHidden();
|
||||
});
|
||||
|
||||
test("saves user profile", async ({ page }) => {
|
||||
await using testBed = await createTestBed(userProfileRealm);
|
||||
await waitForRealmReady();
|
||||
|
||||
await adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
});
|
||||
await retryOperation(() =>
|
||||
adminClient.users.updateProfile({
|
||||
...userProfile,
|
||||
realm: testBed.realm,
|
||||
}),
|
||||
);
|
||||
await login(page, testBed.realm);
|
||||
|
||||
await page.locator("#select").click();
|
||||
|
|
@ -106,7 +119,6 @@ test.describe("Personal info (user profile enabled)", () => {
|
|||
await assertLastAlert(page, "Your account has been updated.");
|
||||
|
||||
await page.reload();
|
||||
await page.locator("delete-account").isVisible();
|
||||
await expect(page.getByTestId("email2")).toHaveValue("valid@email.com");
|
||||
});
|
||||
});
|
||||
|
|
@ -117,18 +129,25 @@ test.describe("Realm localization", () => {
|
|||
internationalizationEnabled: true,
|
||||
supportedLocales: ["en", "nl", "de"],
|
||||
});
|
||||
await waitForRealmReady();
|
||||
|
||||
await login(page, testBed.realm);
|
||||
|
||||
await page.locator("#attributes\\.locale").waitFor({ state: "visible" });
|
||||
await page.locator("#attributes\\.locale").click();
|
||||
page.getByRole("option").filter({ hasText: "Deutsch" });
|
||||
|
||||
await page
|
||||
.getByRole("option", { name: "English" })
|
||||
.waitFor({ state: "visible" });
|
||||
await page.getByRole("option", { name: "English" }).click();
|
||||
|
||||
await page.getByTestId("save").click();
|
||||
await assertLastAlert(page, "Your account has been updated.");
|
||||
|
||||
await page.reload();
|
||||
|
||||
expect(
|
||||
page.locator("#attributes\\.locale").filter({ hasText: /^English$/ }),
|
||||
).toBeDefined();
|
||||
await page.locator("#attributes\\.locale").waitFor({ state: "visible" });
|
||||
|
||||
await expect(page.locator("#attributes\\.locale")).toContainText("English");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,15 +3,22 @@ import { expect, test } from "@playwright/test";
|
|||
import resourcesRealm from "./realms/resources-realm.json" with { type: "json" };
|
||||
import { login } from "./support/actions.ts";
|
||||
import { createTestBed } from "./support/testbed.ts";
|
||||
import { waitForRealmReady } from "./support/test-utils.ts";
|
||||
|
||||
test.describe("Resources", () => {
|
||||
test("shows the resources owned by the user", async ({ page }) => {
|
||||
await using testBed = await createTestBed(
|
||||
resourcesRealm as RealmRepresentation,
|
||||
);
|
||||
await waitForRealmReady();
|
||||
|
||||
await login(page, testBed.realm);
|
||||
const responsePromise = page.waitForResponse(
|
||||
(resp) => resp.url().includes("/realms/") && resp.status() === 200,
|
||||
);
|
||||
|
||||
await page.getByTestId("resources").click();
|
||||
await responsePromise;
|
||||
|
||||
await expect(page.getByRole("gridcell", { name: "one" })).toBeVisible();
|
||||
});
|
||||
|
|
@ -20,11 +27,14 @@ test.describe("Resources", () => {
|
|||
await using testBed = await createTestBed(
|
||||
resourcesRealm as RealmRepresentation,
|
||||
);
|
||||
await waitForRealmReady();
|
||||
|
||||
await login(page, testBed.realm, "alice", "alice");
|
||||
await page.getByTestId("resources").click();
|
||||
|
||||
await page.getByTestId("sharedWithMe").click();
|
||||
|
||||
const table = page.locator("table");
|
||||
await expect(table).toBeVisible();
|
||||
const tableData = await page.locator("table > tr").count();
|
||||
expect(tableData).toBe(0);
|
||||
});
|
||||
|
|
@ -33,6 +43,7 @@ test.describe("Resources", () => {
|
|||
await using testBed = await createTestBed(
|
||||
resourcesRealm as RealmRepresentation,
|
||||
);
|
||||
await waitForRealmReady();
|
||||
|
||||
await using context1 = await browser.newContext();
|
||||
await using context2 = await browser.newContext();
|
||||
|
|
@ -76,6 +87,8 @@ test.describe("Resources", () => {
|
|||
await page2.getByTestId("resources").click();
|
||||
|
||||
await page2.getByTestId("sharedWithMe").click();
|
||||
const table = page2.locator("table");
|
||||
await expect(table).toBeVisible();
|
||||
const rowData = page2.getByTestId("row[0].name");
|
||||
await expect(rowData).toHaveText("one");
|
||||
});
|
||||
|
|
|
|||
37
js/apps/account-ui/test/support/test-utils.ts
Normal file
37
js/apps/account-ui/test/support/test-utils.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
export async function retryOperation<T>(
|
||||
operation: () => Promise<T>,
|
||||
maxRetries = 15,
|
||||
initialDelay = 300,
|
||||
): Promise<T> {
|
||||
let lastError: Error | undefined;
|
||||
|
||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
lastError = error as Error;
|
||||
|
||||
// Only retry on server errors or network errors, not on validation errors
|
||||
const isRetryableError =
|
||||
error instanceof Error &&
|
||||
(error.message.includes("unknown_error") ||
|
||||
error.message.includes("500") ||
|
||||
error.message.includes("ECONNREFUSED"));
|
||||
|
||||
if (isRetryableError) {
|
||||
const delay = initialDelay * Math.pow(1.5, attempt);
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
continue;
|
||||
}
|
||||
|
||||
// For other errors (validation, 4xx, etc.), throw immediately
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
export async function waitForRealmReady(delayMs = 500): Promise<void> {
|
||||
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
||||
}
|
||||
Loading…
Reference in a new issue