mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Disable wave huddles while bot members resolve
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import type { Channel } from "@/shared/api/types";
|
||||
import { normalizePubkey } from "@/shared/lib/pubkey";
|
||||
|
||||
export function getDmHuddleMemberPubkeys(
|
||||
channel: Channel | null,
|
||||
agentPubkeys: ReadonlySet<string> | undefined,
|
||||
currentPubkey: string | undefined,
|
||||
) {
|
||||
if (channel?.channelType !== "dm" || !agentPubkeys) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const normalizedCurrentPubkey = currentPubkey
|
||||
? normalizePubkey(currentPubkey)
|
||||
: null;
|
||||
const seen = new Set<string>();
|
||||
|
||||
return channel.participantPubkeys.filter((pubkey) => {
|
||||
const normalizedPubkey = normalizePubkey(pubkey);
|
||||
if (
|
||||
normalizedCurrentPubkey &&
|
||||
normalizedPubkey === normalizedCurrentPubkey
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!agentPubkeys.has(normalizedPubkey) || seen.has(normalizedPubkey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
seen.add(normalizedPubkey);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
export function hasOtherDmParticipant(
|
||||
channel: Channel | null,
|
||||
currentPubkey: string | undefined,
|
||||
) {
|
||||
if (channel?.channelType !== "dm") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalizedCurrentPubkey = currentPubkey
|
||||
? normalizePubkey(currentPubkey)
|
||||
: null;
|
||||
|
||||
return channel.participantPubkeys.some((pubkey) => {
|
||||
const normalizedPubkey = normalizePubkey(pubkey);
|
||||
return (
|
||||
!normalizedCurrentPubkey || normalizedPubkey !== normalizedCurrentPubkey
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -13,6 +13,10 @@ import {
|
||||
} from "@/features/messages/ui/MessageTimeline";
|
||||
import type { ImetaMedia } from "@/features/messages/lib/imetaMediaMarkdown";
|
||||
import { buildDirectMessageIntro } from "@/features/channels/lib/dmParticipantDisplay";
|
||||
import {
|
||||
getDmHuddleMemberPubkeys,
|
||||
hasOtherDmParticipant,
|
||||
} from "@/features/channels/lib/dmHuddleMembers";
|
||||
import {
|
||||
buildVideoReviewCommentsByRootId,
|
||||
buildVideoReviewContextForMessage,
|
||||
@@ -65,11 +69,11 @@ import type { Channel } from "@/shared/api/types";
|
||||
import { useIsThreadPanelOverlay } from "@/shared/hooks/use-mobile";
|
||||
import { channelChrome } from "@/shared/layout/chromeLayout";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
import { normalizePubkey } from "@/shared/lib/pubkey";
|
||||
type ChannelPaneProps = {
|
||||
activeChannel: Channel | null;
|
||||
activityAgents?: BotActivityAgent[];
|
||||
agentPubkeys?: ReadonlySet<string>;
|
||||
agentPubkeysPending?: boolean;
|
||||
agentSessionAgents: ChannelAgentSessionAgent[];
|
||||
botTypingEntries: TypingIndicatorEntry[];
|
||||
channelFind: ReturnType<typeof useChannelFind>;
|
||||
@@ -181,6 +185,7 @@ type ChannelPaneProps = {
|
||||
export const ChannelPane = React.memo(function ChannelPane({
|
||||
activeChannel,
|
||||
agentPubkeys,
|
||||
agentPubkeysPending = false,
|
||||
agentSessionAgents,
|
||||
activityAgents = agentSessionAgents,
|
||||
botTypingEntries,
|
||||
@@ -275,33 +280,14 @@ export const ChannelPane = React.memo(function ChannelPane({
|
||||
!activeChannel.archivedAt;
|
||||
const hasMainComposerOverlay = !isNonMemberView;
|
||||
const activeChannelId = activeChannel?.id ?? null;
|
||||
const huddleMemberPubkeys = React.useMemo(() => {
|
||||
if (activeChannel?.channelType !== "dm" || !agentPubkeys) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const normalizedCurrentPubkey = currentPubkey
|
||||
? normalizePubkey(currentPubkey)
|
||||
: null;
|
||||
const seen = new Set<string>();
|
||||
|
||||
return activeChannel.participantPubkeys.filter((pubkey) => {
|
||||
const normalizedPubkey = normalizePubkey(pubkey);
|
||||
if (
|
||||
normalizedCurrentPubkey &&
|
||||
normalizedPubkey === normalizedCurrentPubkey
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!agentPubkeys.has(normalizedPubkey) || seen.has(normalizedPubkey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
seen.add(normalizedPubkey);
|
||||
return true;
|
||||
});
|
||||
}, [activeChannel, agentPubkeys, currentPubkey]);
|
||||
const huddleMemberPubkeys = React.useMemo(
|
||||
() => getDmHuddleMemberPubkeys(activeChannel, agentPubkeys, currentPubkey),
|
||||
[activeChannel, agentPubkeys, currentPubkey],
|
||||
);
|
||||
const huddleMemberPubkeysPending =
|
||||
agentPubkeysPending &&
|
||||
huddleMemberPubkeys.length === 0 &&
|
||||
hasOtherDmParticipant(activeChannel, currentPubkey);
|
||||
const isActiveWelcomeChannel =
|
||||
activeChannel !== null && isWelcomeChannel(activeChannel);
|
||||
useComposerHeightPadding(
|
||||
@@ -706,6 +692,7 @@ export const ChannelPane = React.memo(function ChannelPane({
|
||||
hasComposerOverlay={hasMainComposerOverlay}
|
||||
hasOlderMessages={hasOlderMessages}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFetchingOlder={isFetchingOlder}
|
||||
isFollowingThreadById={isFollowingThreadById}
|
||||
isMessageUnreadById={isMessageUnreadById}
|
||||
@@ -872,6 +859,7 @@ export const ChannelPane = React.memo(function ChannelPane({
|
||||
editTarget={threadEditTarget}
|
||||
firstUnreadReplyId={threadFirstUnreadReplyId}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFollowingThread={isFollowingThread}
|
||||
isMessageUnreadById={isMessageUnreadById}
|
||||
isSending={isSending}
|
||||
|
||||
@@ -320,6 +320,12 @@ export function ChannelScreen({
|
||||
}
|
||||
return pubkeys;
|
||||
}, [channelMembers, managedAgents, messageProfilesQuery.data, relayAgents]);
|
||||
const agentPubkeysPending =
|
||||
activeChannel?.channelType === "dm" &&
|
||||
(channelMembersQuery.isPending ||
|
||||
managedAgentsQuery.isPending ||
|
||||
relayAgentsQuery.isPending ||
|
||||
(messageProfilePubkeys.length > 0 && messageProfilesQuery.isPending));
|
||||
const {
|
||||
agentSessionCandidates,
|
||||
botTypingEntries,
|
||||
@@ -765,6 +771,7 @@ export function ChannelScreen({
|
||||
activeChannel={activeChannel}
|
||||
activityAgents={channelAgentSessionAgents}
|
||||
agentPubkeys={agentPubkeys}
|
||||
agentPubkeysPending={agentPubkeysPending}
|
||||
agentSessionAgents={agentSessionAgents}
|
||||
botTypingEntries={botTypingEntries}
|
||||
channelFind={channelFind}
|
||||
|
||||
@@ -57,6 +57,7 @@ export const MessageRow = React.memo(
|
||||
highlightThreadLineDepths,
|
||||
hoverBackground = true,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending = false,
|
||||
actionBarPlacement = "floating",
|
||||
collapseDescendantsLabel,
|
||||
isFollowingThread,
|
||||
@@ -92,6 +93,7 @@ export const MessageRow = React.memo(
|
||||
highlightThreadLineDepths?: ReadonlyArray<number>;
|
||||
hoverBackground?: boolean;
|
||||
huddleMemberPubkeys?: readonly string[];
|
||||
huddleMemberPubkeysPending?: boolean;
|
||||
actionBarPlacement?: "floating" | "inside";
|
||||
collapseDescendantsLabel?: string;
|
||||
isFollowingThread?: boolean;
|
||||
@@ -293,6 +295,7 @@ export const MessageRow = React.memo(
|
||||
channelId={channelId}
|
||||
fallbackText={waveMessage.fallbackText}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -779,6 +782,7 @@ export const MessageRow = React.memo(
|
||||
prev.highlightThreadLineDepths === next.highlightThreadLineDepths &&
|
||||
prev.hoverBackground === next.hoverBackground &&
|
||||
prev.huddleMemberPubkeys === next.huddleMemberPubkeys &&
|
||||
prev.huddleMemberPubkeysPending === next.huddleMemberPubkeysPending &&
|
||||
prev.isFollowingThread === next.isFollowingThread &&
|
||||
prev.isUnread === next.isUnread &&
|
||||
prev.layoutVariant === next.layoutVariant &&
|
||||
|
||||
@@ -47,6 +47,7 @@ type MessageThreadPanelProps = {
|
||||
disabled?: boolean;
|
||||
firstUnreadReplyId?: string | null;
|
||||
huddleMemberPubkeys?: readonly string[];
|
||||
huddleMemberPubkeysPending?: boolean;
|
||||
layout?: "standalone" | "split";
|
||||
editTarget?: {
|
||||
author: string;
|
||||
@@ -348,6 +349,7 @@ export function MessageThreadPanel({
|
||||
disabled = false,
|
||||
firstUnreadReplyId,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending = false,
|
||||
layout = "standalone",
|
||||
editTarget,
|
||||
isSending,
|
||||
@@ -633,6 +635,7 @@ export function MessageThreadPanel({
|
||||
agentPubkeys={agentPubkeys}
|
||||
channelId={channelId}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFollowingThread={isFollowingThread}
|
||||
isUnread={isMessageUnreadById?.(threadHead.id)}
|
||||
layoutVariant="thread-reply"
|
||||
@@ -752,6 +755,7 @@ export function MessageThreadPanel({
|
||||
highlightThreadLineDepths={highlightedLineDepths}
|
||||
hoverBackground={!entry.summary}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isUnread={isMessageUnreadById?.(entry.message.id)}
|
||||
layoutVariant="thread-reply"
|
||||
message={entry.message}
|
||||
|
||||
@@ -38,6 +38,7 @@ type MessageTimelineProps = {
|
||||
channelName?: string;
|
||||
channelType?: ChannelType | null;
|
||||
huddleMemberPubkeys?: readonly string[];
|
||||
huddleMemberPubkeysPending?: boolean;
|
||||
messages: TimelineMessage[];
|
||||
mainEntries?: MainTimelineEntry[];
|
||||
directMessageIntro?: {
|
||||
@@ -156,6 +157,7 @@ const MessageTimelineBase = React.forwardRef<
|
||||
isFetchingOlder = false,
|
||||
followThreadById,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending = false,
|
||||
isFollowingThreadById,
|
||||
isMessageUnreadById,
|
||||
messageFooters,
|
||||
@@ -705,6 +707,7 @@ const MessageTimelineBase = React.forwardRef<
|
||||
followThreadById={followThreadById}
|
||||
highlightedMessageId={highlightedMessageId}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFollowingThreadById={isFollowingThreadById}
|
||||
isMessageUnreadById={isMessageUnreadById}
|
||||
messageFooters={messageFooters}
|
||||
|
||||
@@ -36,6 +36,7 @@ type TimelineMessageListProps = {
|
||||
channelType?: ChannelType | null;
|
||||
currentPubkey?: string;
|
||||
huddleMemberPubkeys?: readonly string[];
|
||||
huddleMemberPubkeysPending?: boolean;
|
||||
/** Event id of the oldest unread top-level message; renders a "New" divider above it. */
|
||||
firstUnreadMessageId?: string | null;
|
||||
followThreadById?: (rootId: string) => void;
|
||||
@@ -96,6 +97,7 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
|
||||
followThreadById,
|
||||
highlightedMessageId = null,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending = false,
|
||||
isFollowingThreadById,
|
||||
isMessageUnreadById,
|
||||
messageFooters,
|
||||
@@ -209,6 +211,7 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
|
||||
footer={messageFooters?.[item.entry.message.id] ?? null}
|
||||
highlightedMessageId={highlightedMessageId}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFollowingThreadById={isFollowingThreadById}
|
||||
isUnread={isMessageUnreadById?.(item.entry.message.id)}
|
||||
onDelete={onDelete}
|
||||
@@ -237,6 +240,7 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
|
||||
followThreadById,
|
||||
highlightedMessageId,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending,
|
||||
isFollowingThreadById,
|
||||
isMessageUnreadById,
|
||||
messageFooters,
|
||||
@@ -323,6 +327,7 @@ type MessageRowItemProps = Pick<
|
||||
| "followThreadById"
|
||||
| "highlightedMessageId"
|
||||
| "huddleMemberPubkeys"
|
||||
| "huddleMemberPubkeysPending"
|
||||
| "isFollowingThreadById"
|
||||
| "onDelete"
|
||||
| "onEdit"
|
||||
@@ -352,6 +357,7 @@ function MessageRowItem({
|
||||
footer,
|
||||
highlightedMessageId,
|
||||
huddleMemberPubkeys,
|
||||
huddleMemberPubkeysPending,
|
||||
isFollowingThreadById,
|
||||
isUnread,
|
||||
onDelete,
|
||||
@@ -394,6 +400,7 @@ function MessageRowItem({
|
||||
highlighted={false}
|
||||
hoverBackground={false}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isFollowingThread={
|
||||
isFollowingThreadById
|
||||
? isFollowingThreadById(message.id)
|
||||
@@ -442,6 +449,7 @@ function MessageRowItem({
|
||||
channelId={channelId}
|
||||
highlighted={message.id === highlightedMessageId || isSearchActive}
|
||||
huddleMemberPubkeys={huddleMemberPubkeys}
|
||||
huddleMemberPubkeysPending={huddleMemberPubkeysPending}
|
||||
isUnread={isUnread}
|
||||
message={message}
|
||||
onDelete={canDelete}
|
||||
|
||||
@@ -18,22 +18,26 @@ type WaveMessageAttachmentProps = {
|
||||
channelId?: string | null;
|
||||
fallbackText: string;
|
||||
huddleMemberPubkeys?: readonly string[];
|
||||
huddleMemberPubkeysPending?: boolean;
|
||||
};
|
||||
|
||||
export function WaveMessageAttachment({
|
||||
channelId,
|
||||
fallbackText,
|
||||
huddleMemberPubkeys = [],
|
||||
huddleMemberPubkeysPending = false,
|
||||
}: WaveMessageAttachmentProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const { isStarting, startHuddle } = useHuddle();
|
||||
const startHuddleDisabled =
|
||||
!channelId || isStarting || huddleMemberPubkeysPending;
|
||||
|
||||
const handleStartHuddle = React.useCallback(
|
||||
async (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (!channelId || isStarting) {
|
||||
if (startHuddleDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,7 +50,13 @@ export function WaveMessageAttachment({
|
||||
);
|
||||
}
|
||||
},
|
||||
[channelId, huddleMemberPubkeys, isStarting, queryClient, startHuddle],
|
||||
[
|
||||
channelId,
|
||||
huddleMemberPubkeys,
|
||||
queryClient,
|
||||
startHuddle,
|
||||
startHuddleDisabled,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -66,7 +76,7 @@ export function WaveMessageAttachment({
|
||||
</AttachmentContent>
|
||||
<AttachmentActions>
|
||||
<AttachmentAction
|
||||
disabled={!channelId || isStarting}
|
||||
disabled={startHuddleDisabled}
|
||||
onClick={handleStartHuddle}
|
||||
size="xs"
|
||||
type="button"
|
||||
|
||||
@@ -80,6 +80,7 @@ type E2eConfig = {
|
||||
};
|
||||
managedAgents?: MockManagedAgentSeed[];
|
||||
relayAgents?: MockRelayAgentSeed[];
|
||||
agentListDelayMs?: number;
|
||||
agentMemory?: RawAgentMemoryListing | Record<string, RawAgentMemoryListing>;
|
||||
createManagedAgentDelayMs?: number;
|
||||
channelsReadError?: string;
|
||||
@@ -4615,7 +4616,19 @@ async function handleGetFeed(
|
||||
};
|
||||
}
|
||||
|
||||
async function handleListRelayAgents(): Promise<RawRelayAgent[]> {
|
||||
async function delayAgentList(config: E2eConfig | undefined) {
|
||||
const agentListDelayMs = config?.mock?.agentListDelayMs ?? 0;
|
||||
if (agentListDelayMs > 0) {
|
||||
await new Promise<void>((resolve) => {
|
||||
window.setTimeout(resolve, agentListDelayMs);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleListRelayAgents(
|
||||
config: E2eConfig | undefined,
|
||||
): Promise<RawRelayAgent[]> {
|
||||
await delayAgentList(config);
|
||||
syncMockRelayAgentsFromManagedAgents();
|
||||
return mockRelayAgents.map(cloneRelayAgent);
|
||||
}
|
||||
@@ -4742,7 +4755,10 @@ async function handleDiscoverManagedAgentPrereqs(
|
||||
};
|
||||
}
|
||||
|
||||
async function handleListManagedAgents(): Promise<RawManagedAgent[]> {
|
||||
async function handleListManagedAgents(
|
||||
config: E2eConfig | undefined,
|
||||
): Promise<RawManagedAgent[]> {
|
||||
await delayAgentList(config);
|
||||
return mockManagedAgents.map(cloneManagedAgent);
|
||||
}
|
||||
|
||||
@@ -6687,7 +6703,7 @@ export function maybeInstallE2eTauriMocks() {
|
||||
activeConfig,
|
||||
);
|
||||
case "list_relay_agents":
|
||||
return handleListRelayAgents();
|
||||
return handleListRelayAgents(activeConfig);
|
||||
case "list_personas":
|
||||
return handleListPersonas();
|
||||
case "create_persona":
|
||||
@@ -6796,7 +6812,7 @@ export function maybeInstallE2eTauriMocks() {
|
||||
case "export_persona_to_json":
|
||||
return handleExportPersonaToJson(payload as { id: string });
|
||||
case "list_managed_agents":
|
||||
return handleListManagedAgents();
|
||||
return handleListManagedAgents(activeConfig);
|
||||
case "get_agent_memory":
|
||||
return handleGetAgentMemory(
|
||||
(payload as Parameters<typeof handleGetAgentMemory>[0]) ?? {},
|
||||
|
||||
@@ -20,6 +20,8 @@ const REUSABLE_PERSONA_AGENT_PUBKEY =
|
||||
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
|
||||
const ALLOWLIST_RELAY_AGENT_PUBKEY =
|
||||
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
||||
const DELAYED_RELAY_AGENT_PUBKEY =
|
||||
"9999999999999999999999999999999999999999999999999999999999999999";
|
||||
const CASEY_PROFILE_PUBKEY =
|
||||
"1111111111111111111111111111111111111111111111111111111111111111";
|
||||
const PROFILE_ONLY_AGENT_PUBKEY =
|
||||
@@ -1358,3 +1360,59 @@ test("wave attachment huddle passes the bot DM pubkey", async ({ page }) => {
|
||||
.poll(() => readStartHuddleMemberPubkeys(page))
|
||||
.toEqual(expect.arrayContaining([TEST_IDENTITIES.charlie.pubkey]));
|
||||
});
|
||||
|
||||
test("wave attachment huddle waits for delayed bot DM pubkey", async ({
|
||||
page,
|
||||
}) => {
|
||||
await installMockBridge(page, {
|
||||
agentListDelayMs: 5_000,
|
||||
relayAgents: [
|
||||
{
|
||||
pubkey: DELAYED_RELAY_AGENT_PUBKEY,
|
||||
name: "orbit",
|
||||
channelNames: ["general"],
|
||||
},
|
||||
],
|
||||
searchProfiles: [
|
||||
{
|
||||
pubkey: DELAYED_RELAY_AGENT_PUBKEY,
|
||||
displayName: "orbit",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
await page.getByTestId("channel-general").click();
|
||||
await expect(page.getByTestId("chat-title")).toHaveText("general");
|
||||
await waitForMockLiveSubscription(page, "general");
|
||||
|
||||
await emitMockMessage(page, "general", "Orbit checking in.", {
|
||||
pubkey: DELAYED_RELAY_AGENT_PUBKEY,
|
||||
});
|
||||
await waitForTimelineSettled(page);
|
||||
|
||||
const orbitMessage = page
|
||||
.getByTestId("message-row")
|
||||
.filter({ hasText: "Orbit checking in." })
|
||||
.first();
|
||||
await orbitMessage.locator("button").first().hover();
|
||||
|
||||
const profilePopover = page.locator(
|
||||
'[data-testid="user-profile-popover"][data-state="open"]',
|
||||
);
|
||||
await expect(profilePopover).toBeVisible();
|
||||
await profilePopover
|
||||
.getByTestId(`user-profile-popover-wave-${DELAYED_RELAY_AGENT_PUBKEY}`)
|
||||
.click();
|
||||
|
||||
const startHuddleButton = page
|
||||
.getByTestId("message-wave-attachment")
|
||||
.getByRole("button", { name: "Start huddle" });
|
||||
await expect(startHuddleButton).toBeDisabled();
|
||||
await expect(startHuddleButton).toBeEnabled({ timeout: 7_000 });
|
||||
await startHuddleButton.click();
|
||||
|
||||
await expect
|
||||
.poll(() => readStartHuddleMemberPubkeys(page))
|
||||
.toEqual(expect.arrayContaining([DELAYED_RELAY_AGENT_PUBKEY]));
|
||||
});
|
||||
|
||||
@@ -105,6 +105,7 @@ type MockBridgeOptions = {
|
||||
};
|
||||
managedAgents?: MockManagedAgentSeed[];
|
||||
relayAgents?: MockRelayAgentSeed[];
|
||||
agentListDelayMs?: number;
|
||||
createManagedAgentDelayMs?: number;
|
||||
channelsReadError?: string;
|
||||
feedReadError?: string;
|
||||
|
||||
Reference in New Issue
Block a user