9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
141 lines
5.1 KiB
TypeScript
141 lines
5.1 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
|
|
import { installMockBridge } from "../helpers/bridge";
|
|
|
|
// NIP-IA archive button + "Archived" flair gate matrix.
|
|
//
|
|
// Guards the composition `canArchive = isSelf || isRelayAdminOrOwner ||
|
|
// isOaOwnerOfViewee` in UserProfilePanel.tsx. Unit tests cover each input in
|
|
// isolation; this spec covers the OR composition where silent regressions
|
|
// (refactor turns OR into AND, role expansion bypasses a branch, etc.) would
|
|
// otherwise slip past code review.
|
|
|
|
const ALICE_PUBKEY =
|
|
"953d3363262e86b770419834c53d2446409db6d918a57f8f339d495d54ab001f";
|
|
|
|
async function openSelfProfile(page: import("@playwright/test").Page) {
|
|
await page.goto("/");
|
|
await page.getByTestId("channel-general").click();
|
|
await expect(page.getByTestId("chat-title")).toHaveText("general");
|
|
// First seed message in #general is from the active identity.
|
|
const firstMessage = page.getByTestId("message-row").first();
|
|
await firstMessage.locator("button", { hasText: "npub1mock..." }).click();
|
|
await expect(page.getByTestId("user-profile-panel")).toBeVisible();
|
|
}
|
|
|
|
async function openAliceProfile(page: import("@playwright/test").Page) {
|
|
await page.goto("/");
|
|
await page.getByTestId("channel-general").click();
|
|
await expect(page.getByTestId("chat-title")).toHaveText("general");
|
|
// Second seed message in #general is from Alice. Her display name "alice"
|
|
// is registered in mockDisplayNames, so the author button text is "alice".
|
|
const aliceMessage = page.getByTestId("message-row").nth(1);
|
|
await aliceMessage.locator("button", { hasText: "alice" }).first().click();
|
|
const panel = page.getByTestId("user-profile-panel");
|
|
await expect(panel).toBeVisible();
|
|
await expect(panel).toContainText(ALICE_PUBKEY.slice(0, 8));
|
|
}
|
|
|
|
async function openProfileSettingsMenu(page: import("@playwright/test").Page) {
|
|
const trigger = page.getByTestId("user-profile-settings-menu-trigger");
|
|
await expect(trigger).toBeVisible();
|
|
await trigger.click();
|
|
}
|
|
|
|
test.describe("NIP-IA archive button gate", () => {
|
|
test("case 1 — self viewer + self target: Archive visible, no flair", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(page, { relayRole: null, oaOwnerIsMe: false });
|
|
await openSelfProfile(page);
|
|
await openProfileSettingsMenu(page);
|
|
const archiveButton = page.getByTestId("user-profile-archive-identity");
|
|
await expect(archiveButton).toBeVisible();
|
|
await expect(page.getByTestId("user-profile-archived-flair")).toHaveCount(
|
|
0,
|
|
);
|
|
|
|
// Archive is now gated behind a confirmation modal — clicking the button
|
|
// opens the dialog rather than firing immediately. Drive the full flow so
|
|
// the gate stays meaningful: the modal must surface, then confirm fires.
|
|
await expect(page.getByTestId("archive-confirm-dialog")).toHaveCount(0);
|
|
await archiveButton.click();
|
|
await expect(page.getByTestId("archive-confirm-dialog")).toBeVisible();
|
|
const confirm = page.getByTestId("archive-confirm-action");
|
|
await expect(confirm).toBeVisible();
|
|
await confirm.click();
|
|
await expect(page.getByTestId("archive-confirm-dialog")).toHaveCount(0);
|
|
});
|
|
|
|
test("case 2 — relay admin viewing Alice: Archive visible", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(page, {
|
|
relayRole: "admin",
|
|
relayRequiresMembership: true,
|
|
oaOwnerIsMe: false,
|
|
archivedIdentities: [],
|
|
});
|
|
await openAliceProfile(page);
|
|
await openProfileSettingsMenu(page);
|
|
await expect(
|
|
page.getByTestId("user-profile-archive-identity"),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("case 3 — verified OA owner viewing Alice: Archive visible", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(page, {
|
|
relayRole: null,
|
|
oaOwnerIsMe: true,
|
|
archivedIdentities: [],
|
|
});
|
|
await openAliceProfile(page);
|
|
await openProfileSettingsMenu(page);
|
|
await expect(
|
|
page.getByTestId("user-profile-archive-identity"),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("case 4 — no authority viewing Alice: Archive hidden", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(page, {
|
|
relayRole: null,
|
|
oaOwnerIsMe: false,
|
|
archivedIdentities: [],
|
|
});
|
|
await openAliceProfile(page);
|
|
await expect(
|
|
page.getByTestId("user-profile-settings-menu-trigger"),
|
|
).toHaveCount(0);
|
|
await expect(page.getByTestId("user-profile-archive-identity")).toHaveCount(
|
|
0,
|
|
);
|
|
await expect(
|
|
page.getByTestId("user-profile-unarchive-identity"),
|
|
).toHaveCount(0);
|
|
});
|
|
|
|
test("case 5 — Alice archived: flair + Unarchive button (under admin gate)", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(page, {
|
|
relayRole: "admin",
|
|
relayRequiresMembership: true,
|
|
oaOwnerIsMe: false,
|
|
archivedIdentities: [ALICE_PUBKEY],
|
|
});
|
|
await openAliceProfile(page);
|
|
await expect(page.getByTestId("user-profile-archived-flair")).toBeVisible();
|
|
await openProfileSettingsMenu(page);
|
|
await expect(
|
|
page.getByTestId("user-profile-unarchive-identity"),
|
|
).toBeVisible();
|
|
await expect(page.getByTestId("user-profile-archive-identity")).toHaveCount(
|
|
0,
|
|
);
|
|
});
|
|
});
|