feat: import Chinese-localized Buzz source snapshot
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
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>
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
import { installMockBridge } from "../helpers/bridge";
|
||||
|
||||
async function openLocalArchiveSettings(page: import("@playwright/test").Page) {
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
await page.getByTestId("open-settings").click();
|
||||
await page.getByTestId("profile-popover-settings").click();
|
||||
await expect(page.getByTestId("settings-view")).toBeVisible();
|
||||
await page.getByTestId("settings-nav-local-archive").click();
|
||||
const card = page.getByTestId("settings-local-archive");
|
||||
await expect(card).toBeVisible({ timeout: 10_000 });
|
||||
return card;
|
||||
}
|
||||
|
||||
test.describe("observer archive policy — Settings toggle", () => {
|
||||
test("fresh identity: observer toggle is enabled and checked by default", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Archive is default-on for all builds. A fresh identity (no stored opt-out)
|
||||
// should show the toggle enabled and checked after reconciliation seeds the
|
||||
// kind-24200 subscription.
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [
|
||||
{
|
||||
scope_type: "owner_p",
|
||||
scope_value: "deadbeef".repeat(8),
|
||||
kinds: "[24200]",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const card = await openLocalArchiveSettings(page);
|
||||
const toggle = card.getByTestId("local-archive-observer-toggle");
|
||||
await expect(toggle).toBeVisible({ timeout: 5_000 });
|
||||
await expect(toggle).toBeEnabled();
|
||||
await expect(toggle).toBeChecked();
|
||||
});
|
||||
|
||||
test("toggle click OFF disables, then ON re-enables", async ({ page }) => {
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [
|
||||
{
|
||||
scope_type: "owner_p",
|
||||
scope_value: "deadbeef".repeat(8),
|
||||
kinds: "[24200]",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const card = await openLocalArchiveSettings(page);
|
||||
const toggle = card.getByTestId("local-archive-observer-toggle");
|
||||
await expect(toggle).toBeVisible({ timeout: 5_000 });
|
||||
await expect(toggle).toBeChecked();
|
||||
|
||||
// OFF: removes kind 24200.
|
||||
await toggle.click();
|
||||
await expect(toggle).not.toBeChecked();
|
||||
|
||||
// ON again: re-creates the row from empty.
|
||||
await toggle.click();
|
||||
await expect(toggle).toBeChecked();
|
||||
});
|
||||
|
||||
test("explicit opt-out persists across reload: toggle stays OFF", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Simulate a user who previously clicked OFF: the identity-scoped opt-out
|
||||
// is recorded in localStorage ("0") and the owner_p/24200 subscription row
|
||||
// is absent. Reconciliation must honour the stored choice and leave the
|
||||
// toggle unchecked (user can re-enable via the toggle).
|
||||
const MOCK_PUBKEY = "deadbeef".repeat(8);
|
||||
await page.addInitScript(
|
||||
({ storageKey }) => {
|
||||
window.localStorage.setItem(storageKey, "0");
|
||||
},
|
||||
{
|
||||
storageKey: `buzz:observer-archive-default-seeded:${MOCK_PUBKEY}`,
|
||||
},
|
||||
);
|
||||
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [],
|
||||
});
|
||||
|
||||
const card = await openLocalArchiveSettings(page);
|
||||
const toggle = card.getByTestId("local-archive-observer-toggle");
|
||||
await expect(toggle).toBeVisible({ timeout: 5_000 });
|
||||
await expect(toggle).toBeEnabled();
|
||||
await expect(toggle).not.toBeChecked();
|
||||
});
|
||||
|
||||
test("no subscriptions, no stored choice: defaults ON then OFF removes, ON re-creates", async ({
|
||||
page,
|
||||
}) => {
|
||||
// A fresh identity with no stored choice and an empty subscription table
|
||||
// must be seeded to ON by reconciliation. Thereafter the toggle must
|
||||
// function: OFF removes kind 24200, ON re-creates it.
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [],
|
||||
});
|
||||
|
||||
const card = await openLocalArchiveSettings(page);
|
||||
const toggle = card.getByTestId("local-archive-observer-toggle");
|
||||
await expect(toggle).toBeVisible({ timeout: 5_000 });
|
||||
|
||||
// Default-on: reconciliation seeds the row, toggle must be checked.
|
||||
await expect(toggle).toBeChecked();
|
||||
|
||||
// OFF: removes kind 24200.
|
||||
await toggle.click();
|
||||
await expect(toggle).not.toBeChecked();
|
||||
|
||||
// ON again: re-creates the row from empty.
|
||||
await toggle.click();
|
||||
await expect(toggle).toBeChecked();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("observer archive policy — reconciliation gate", () => {
|
||||
test("archive sync reaches subscription path after reconciliation", async ({
|
||||
page,
|
||||
}) => {
|
||||
// The reconciliation gate (useObserverArchiveReconciliation) must resolve
|
||||
// successfully for a fresh identity, allowing useArchiveSync to start the
|
||||
// ArchiveSyncManager, which calls list_save_subscriptions.
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [
|
||||
{
|
||||
scope_type: "owner_p",
|
||||
scope_value: "deadbeef".repeat(8),
|
||||
kinds: "[24200]",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
// Wait for the channel list (proves AppShell mounted fully).
|
||||
await expect(page.getByTestId("channel-general")).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
|
||||
// The IPC counter proves the subscription path was reached.
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const counters = (window as Record<string, unknown>)
|
||||
.__BUZZ_E2E_IPC_COUNTERS__ as Record<string, number> | undefined;
|
||||
return (counters?.list_save_subscriptions ?? 0) > 0;
|
||||
},
|
||||
null,
|
||||
{ timeout: 10_000 },
|
||||
);
|
||||
|
||||
const count = await page.evaluate(() => {
|
||||
const counters = (window as Record<string, unknown>)
|
||||
.__BUZZ_E2E_IPC_COUNTERS__ as Record<string, number> | undefined;
|
||||
return counters?.list_save_subscriptions ?? 0;
|
||||
});
|
||||
expect(count).toBeGreaterThan(0);
|
||||
|
||||
// The reconciliation gate must also result in a real `#p` + kind-24200
|
||||
// live REQ filter.
|
||||
const hasOwnerKindSubscription = await page.evaluate(
|
||||
(ownerPubkey) =>
|
||||
(
|
||||
window as Window & {
|
||||
__BUZZ_E2E_HAS_MOCK_OWNER_KIND_SUBSCRIPTION__?: (input: {
|
||||
ownerPubkey: string;
|
||||
kind: number;
|
||||
}) => boolean;
|
||||
}
|
||||
).__BUZZ_E2E_HAS_MOCK_OWNER_KIND_SUBSCRIPTION__?.({
|
||||
ownerPubkey,
|
||||
kind: 24200,
|
||||
}) ?? false,
|
||||
"deadbeef".repeat(8),
|
||||
);
|
||||
expect(hasOwnerKindSubscription).toBe(true);
|
||||
});
|
||||
|
||||
test("fresh install with empty subscriptions: reconciliation seeds kind 24200", async ({
|
||||
page,
|
||||
}) => {
|
||||
// A fresh install with no owner_p/24200 row must end up with one after
|
||||
// startup reconciliation runs — the actual production repair path.
|
||||
await installMockBridge(page, {
|
||||
saveSubscriptions: [],
|
||||
});
|
||||
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
await expect(page.getByTestId("channel-general")).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
() =>
|
||||
page.evaluate(
|
||||
(ownerPubkey) =>
|
||||
(
|
||||
window as Window & {
|
||||
__BUZZ_E2E_HAS_MOCK_OWNER_KIND_SUBSCRIPTION__?: (input: {
|
||||
ownerPubkey: string;
|
||||
kind: number;
|
||||
}) => boolean;
|
||||
}
|
||||
).__BUZZ_E2E_HAS_MOCK_OWNER_KIND_SUBSCRIPTION__?.({
|
||||
ownerPubkey,
|
||||
kind: 24200,
|
||||
}) ?? false,
|
||||
"deadbeef".repeat(8),
|
||||
),
|
||||
{ timeout: 10_000 },
|
||||
)
|
||||
.toBe(true);
|
||||
|
||||
const commands = await page.evaluate(
|
||||
() =>
|
||||
(window as Window & { __BUZZ_E2E_COMMANDS__?: string[] })
|
||||
.__BUZZ_E2E_COMMANDS__ ?? [],
|
||||
);
|
||||
expect(commands).toContain("merge_save_subscription_kinds");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user