@agent-native/dispatch 0.23.3 → 0.23.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/provider-api-register.d.ts +11 -11
- package/dist/components/app-list-row.d.ts +1 -1
- package/dist/components/app-list-row.d.ts.map +1 -1
- package/dist/components/app-list-row.js +2 -2
- package/dist/components/app-list-row.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +11 -0
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +3 -2
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +1 -0
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +41 -3
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
- package/dist/components/layout/workspace-apps-rail.js +2 -2
- package/dist/components/layout/workspace-apps-rail.js.map +1 -1
- package/dist/components/other-apps-section.d.ts.map +1 -1
- package/dist/components/other-apps-section.js +5 -1
- package/dist/components/other-apps-section.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/lib/other-apps.d.ts.map +1 -1
- package/dist/lib/other-apps.js +2 -0
- package/dist/lib/other-apps.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +3 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +10 -0
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +2 -1
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/server/plugins/auth.d.ts.map +1 -1
- package/dist/server/plugins/auth.js +1 -0
- package/dist/server/plugins/auth.js.map +1 -1
- package/package.json +3 -3
- package/src/components/app-list-row.tsx +3 -2
- package/src/components/create-app-popover.spec.tsx +26 -2
- package/src/components/create-app-popover.tsx +10 -0
- package/src/components/dispatch-control-plane.spec.tsx +1 -0
- package/src/components/dispatch-control-plane.tsx +8 -2
- package/src/components/layout/Layout.spec.tsx +9 -0
- package/src/components/layout/Layout.tsx +71 -4
- package/src/components/layout/workspace-apps-rail.tsx +2 -1
- package/src/components/other-apps-section.tsx +8 -1
- package/src/config.ts +2 -0
- package/src/lib/other-apps.spec.ts +26 -0
- package/src/lib/other-apps.ts +3 -0
- package/src/lib/workspace-apps.spec.ts +24 -1
- package/src/lib/workspace-apps.ts +15 -0
- package/src/routes/pages/apps.tsx +5 -2
- package/src/server/plugins/auth.spec.ts +45 -0
- package/src/server/plugins/auth.ts +1 -0
|
@@ -9,6 +9,7 @@ import { TooltipProvider } from "../ui/tooltip";
|
|
|
9
9
|
import {
|
|
10
10
|
buildChatFirstEmbedSessionInput,
|
|
11
11
|
formatThreadAge,
|
|
12
|
+
isElectronEmbeddedSearch,
|
|
12
13
|
NavContent,
|
|
13
14
|
} from "./Layout";
|
|
14
15
|
|
|
@@ -119,6 +120,14 @@ describe("chat-first embed sessions", () => {
|
|
|
119
120
|
});
|
|
120
121
|
});
|
|
121
122
|
|
|
123
|
+
describe("Electron control-plane mode", () => {
|
|
124
|
+
it("recognizes only the explicit Electron query flag", () => {
|
|
125
|
+
expect(isElectronEmbeddedSearch("?electron=1")).toBe(true);
|
|
126
|
+
expect(isElectronEmbeddedSearch("?electron=0")).toBe(false);
|
|
127
|
+
expect(isElectronEmbeddedSearch("?chatFirst=1")).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
122
131
|
describe("Dispatch NavContent", () => {
|
|
123
132
|
let container: HTMLDivElement;
|
|
124
133
|
let root: Root;
|
|
@@ -104,6 +104,8 @@ import { toast } from "sonner";
|
|
|
104
104
|
|
|
105
105
|
import { cn } from "../../lib/utils";
|
|
106
106
|
import {
|
|
107
|
+
isDispatchWorkspaceAppId,
|
|
108
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
107
109
|
mergeChatFirstWorkspaceApps,
|
|
108
110
|
workspaceAppIdFromRoute,
|
|
109
111
|
workspaceAppRoute,
|
|
@@ -299,6 +301,10 @@ function localDispatchPath(pathname: string): string {
|
|
|
299
301
|
return pathname;
|
|
300
302
|
}
|
|
301
303
|
|
|
304
|
+
export function isElectronEmbeddedSearch(search: string): boolean {
|
|
305
|
+
return new URLSearchParams(search).get("electron") === "1";
|
|
306
|
+
}
|
|
307
|
+
|
|
302
308
|
function chatFirstPrimaryTabForPath(
|
|
303
309
|
pathname: string,
|
|
304
310
|
): ChatFirstPrimaryTab | undefined {
|
|
@@ -1330,6 +1336,11 @@ export function Layout({
|
|
|
1330
1336
|
}
|
|
1331
1337
|
});
|
|
1332
1338
|
const localPathname = localDispatchPath(location.pathname);
|
|
1339
|
+
const [electronEmbedded] = useState(() =>
|
|
1340
|
+
typeof window !== "undefined"
|
|
1341
|
+
? isElectronEmbeddedSearch(window.location.search)
|
|
1342
|
+
: false,
|
|
1343
|
+
);
|
|
1333
1344
|
const isChatRoute =
|
|
1334
1345
|
localPathname === "/chat" || localPathname.startsWith("/chat/");
|
|
1335
1346
|
const chatFirstSurfaceScope = threadIdFromPath(localPathname) ?? "new";
|
|
@@ -1347,6 +1358,17 @@ export function Layout({
|
|
|
1347
1358
|
const chatFirstMode =
|
|
1348
1359
|
extensions?.chatFirst === true || chatFirstPreference || chatFirstEmbedded;
|
|
1349
1360
|
const chatFirstHasActiveChat = chatFirstSurfaceScope !== "new";
|
|
1361
|
+
useEffect(() => {
|
|
1362
|
+
if (!electronEmbedded || typeof window === "undefined") return;
|
|
1363
|
+
const url = new URL(window.location.href);
|
|
1364
|
+
if (isElectronEmbeddedSearch(url.search)) return;
|
|
1365
|
+
url.searchParams.set("electron", "1");
|
|
1366
|
+
window.history.replaceState(
|
|
1367
|
+
window.history.state,
|
|
1368
|
+
"",
|
|
1369
|
+
`${url.pathname}${url.search}${url.hash}`,
|
|
1370
|
+
);
|
|
1371
|
+
}, [electronEmbedded, location.pathname, location.search]);
|
|
1350
1372
|
useEffect(() => {
|
|
1351
1373
|
if (!chatFirstMode || chatFirstEmbedded || localPathname !== "/overview") {
|
|
1352
1374
|
return;
|
|
@@ -1396,7 +1418,9 @@ export function Layout({
|
|
|
1396
1418
|
const chatFirstAppItems = useMemo<ChatFirstAppItem[]>(
|
|
1397
1419
|
() =>
|
|
1398
1420
|
chatFirstAppRegistrations
|
|
1399
|
-
.filter(
|
|
1421
|
+
.filter(
|
|
1422
|
+
(app) => app.enabled && isWorkspaceAppVisibleInDefaultLaunchers(app),
|
|
1423
|
+
)
|
|
1400
1424
|
.map((app) => ({
|
|
1401
1425
|
id: app.id,
|
|
1402
1426
|
name: app.name ?? app.id,
|
|
@@ -1729,6 +1753,19 @@ export function Layout({
|
|
|
1729
1753
|
setChatFirstNotice(chatFirstResolutionMessage(resolution.reason));
|
|
1730
1754
|
return;
|
|
1731
1755
|
}
|
|
1756
|
+
if (isDispatchWorkspaceAppId(resolution.target.appId)) {
|
|
1757
|
+
closeChatFirstSessionWatch();
|
|
1758
|
+
chatFirstSurfaceTabsStore.closeAll();
|
|
1759
|
+
setChatFirstSurfacePanelOpen(false);
|
|
1760
|
+
persistChatFirstPane(null);
|
|
1761
|
+
if (resolution.target.path) {
|
|
1762
|
+
navigateWithAgentChatViewTransition(
|
|
1763
|
+
navigate,
|
|
1764
|
+
dispatchNavLinkTarget(resolution.target.path),
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1732
1769
|
openChatFirstPane(resolution.target);
|
|
1733
1770
|
},
|
|
1734
1771
|
[
|
|
@@ -1736,7 +1773,12 @@ export function Layout({
|
|
|
1736
1773
|
chatFirstAppsQuery.isError,
|
|
1737
1774
|
chatFirstAppsQuery.isLoading,
|
|
1738
1775
|
chatFirstGrantedAppsQuery.isLoading,
|
|
1776
|
+
chatFirstSurfaceTabsStore,
|
|
1777
|
+
closeChatFirstSessionWatch,
|
|
1739
1778
|
openChatFirstPane,
|
|
1779
|
+
navigate,
|
|
1780
|
+
persistChatFirstPane,
|
|
1781
|
+
setChatFirstSurfacePanelOpen,
|
|
1740
1782
|
],
|
|
1741
1783
|
);
|
|
1742
1784
|
const chatHomeHandoffActive = useAgentChatHomeHandoff({
|
|
@@ -2204,6 +2246,29 @@ export function Layout({
|
|
|
2204
2246
|
return <>{children}</>;
|
|
2205
2247
|
}
|
|
2206
2248
|
|
|
2249
|
+
if (electronEmbedded) {
|
|
2250
|
+
return (
|
|
2251
|
+
<DispatchExtensionsContext.Provider value={extensions}>
|
|
2252
|
+
<HeaderActionsProvider>
|
|
2253
|
+
<div
|
|
2254
|
+
data-dispatch-electron-control-plane
|
|
2255
|
+
className="flex h-screen w-full overflow-hidden bg-background"
|
|
2256
|
+
>
|
|
2257
|
+
<div className="relative flex min-w-0 flex-1 flex-col overflow-hidden">
|
|
2258
|
+
<Header showAgentToggle={false} />
|
|
2259
|
+
<InvitationBanner />
|
|
2260
|
+
<main className="flex-1 overflow-y-auto">
|
|
2261
|
+
<div className="mx-auto max-w-7xl space-y-10 px-4 py-6 sm:px-6">
|
|
2262
|
+
{children}
|
|
2263
|
+
</div>
|
|
2264
|
+
</main>
|
|
2265
|
+
</div>
|
|
2266
|
+
</div>
|
|
2267
|
+
</HeaderActionsProvider>
|
|
2268
|
+
</DispatchExtensionsContext.Provider>
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2207
2272
|
if (isWorkspaceAppHostRoute) {
|
|
2208
2273
|
return (
|
|
2209
2274
|
<DispatchExtensionsContext.Provider value={extensions}>
|
|
@@ -2403,9 +2468,11 @@ export function Layout({
|
|
|
2403
2468
|
chatFirstSurfaceTabsStore.closeAll();
|
|
2404
2469
|
setChatFirstSurfacePanelOpen(false);
|
|
2405
2470
|
}}
|
|
2406
|
-
onChatFirstAppOpen={(app) =>
|
|
2407
|
-
|
|
2408
|
-
|
|
2471
|
+
onChatFirstAppOpen={(app) => {
|
|
2472
|
+
if (isDispatchWorkspaceAppId(app.id)) return;
|
|
2473
|
+
setSidebarCollapsed(true);
|
|
2474
|
+
navigate(dispatchNavLinkTarget(workspaceAppRoute(app.id)));
|
|
2475
|
+
}}
|
|
2409
2476
|
onChatFirstAppsRetry={() => void chatFirstAppsQuery.refetch()}
|
|
2410
2477
|
collapsible
|
|
2411
2478
|
onCollapsedChange={setSidebarCollapsed}
|
|
@@ -5,6 +5,7 @@ import { Link, useLocation } from "react-router";
|
|
|
5
5
|
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
7
|
import {
|
|
8
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
8
9
|
workspaceAppIdFromRoute,
|
|
9
10
|
workspaceAppRoute,
|
|
10
11
|
workspaceAppHref,
|
|
@@ -41,7 +42,7 @@ export function WorkspaceAppsRail({
|
|
|
41
42
|
const apps = appsQuery.data
|
|
42
43
|
.filter(
|
|
43
44
|
(app) =>
|
|
44
|
-
|
|
45
|
+
isWorkspaceAppVisibleInDefaultLaunchers(app) &&
|
|
45
46
|
!app.archived &&
|
|
46
47
|
app.status !== "pending" &&
|
|
47
48
|
!!workspaceAppHref(app),
|
|
@@ -3,6 +3,7 @@ import { useT } from "@agent-native/core/client/i18n";
|
|
|
3
3
|
import { filterOtherApps, type ConnectedAppSummary } from "../lib/other-apps";
|
|
4
4
|
import type { WorkspaceAppId } from "../lib/other-apps";
|
|
5
5
|
import { cn } from "../lib/utils";
|
|
6
|
+
import { isDefaultWorkspaceAppHiddenId } from "../lib/workspace-apps";
|
|
6
7
|
import { ActionQueryError } from "./action-query-error";
|
|
7
8
|
import {
|
|
8
9
|
APP_LIST_GRID_CLASS,
|
|
@@ -52,7 +53,13 @@ export function mergeOtherAppEntries({
|
|
|
52
53
|
|
|
53
54
|
for (const template of getTemplateItems(templates)) {
|
|
54
55
|
const id = templateKey(template);
|
|
55
|
-
if (
|
|
56
|
+
if (
|
|
57
|
+
!id ||
|
|
58
|
+
isDefaultWorkspaceAppHiddenId(id) ||
|
|
59
|
+
template.installed ||
|
|
60
|
+
workspaceAppIds.has(id)
|
|
61
|
+
)
|
|
62
|
+
continue;
|
|
56
63
|
seen.add(id);
|
|
57
64
|
entries.push({ kind: "template", template });
|
|
58
65
|
}
|
package/src/config.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface DispatchAuthConfig {
|
|
|
13
13
|
googleOnly?: boolean;
|
|
14
14
|
/** Marketing/branding copy passed straight through to `createAuthPlugin`. */
|
|
15
15
|
marketing?: Record<string, unknown>;
|
|
16
|
+
/** Exact framework routes that perform their own authentication checks. */
|
|
17
|
+
publicPaths?: string[];
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export interface DispatchIntegrationsConfig {
|
|
@@ -104,4 +104,30 @@ describe("filterOtherApps", () => {
|
|
|
104
104
|
},
|
|
105
105
|
]);
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
it("hides the generic chat starter from connected app launchers", () => {
|
|
109
|
+
expect(
|
|
110
|
+
filterOtherApps(
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
id: "chat",
|
|
114
|
+
name: "Chat",
|
|
115
|
+
url: "https://chat.agent-native.com",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "mail",
|
|
119
|
+
name: "Mail",
|
|
120
|
+
url: "https://mail.agent-native.com",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
[],
|
|
124
|
+
),
|
|
125
|
+
).toEqual([
|
|
126
|
+
{
|
|
127
|
+
id: "mail",
|
|
128
|
+
name: "Mail",
|
|
129
|
+
url: "https://mail.agent-native.com",
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
107
133
|
});
|
package/src/lib/other-apps.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isDefaultWorkspaceAppHiddenId } from "./workspace-apps";
|
|
2
|
+
|
|
1
3
|
export interface ConnectedAppSummary {
|
|
2
4
|
id: string;
|
|
3
5
|
name: string;
|
|
@@ -38,6 +40,7 @@ export function filterOtherApps(
|
|
|
38
40
|
const id = app.id.trim().toLowerCase();
|
|
39
41
|
if (
|
|
40
42
|
!id ||
|
|
43
|
+
isDefaultWorkspaceAppHiddenId(id) ||
|
|
41
44
|
HIDDEN_OTHER_APP_IDS.has(id) ||
|
|
42
45
|
workspaceAppIds.has(id) ||
|
|
43
46
|
seen.has(id)
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
isDefaultWorkspaceAppHiddenId,
|
|
5
|
+
isDispatchWorkspaceAppId,
|
|
6
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
7
|
+
workspaceAppIdFromRoute,
|
|
8
|
+
workspaceAppRoute,
|
|
9
|
+
} from "./workspace-apps";
|
|
4
10
|
|
|
5
11
|
describe("workspace app routes", () => {
|
|
6
12
|
it("round-trips encoded app ids", () => {
|
|
@@ -18,4 +24,21 @@ describe("workspace app routes", () => {
|
|
|
18
24
|
it("accepts nested app routes while preserving the app id", () => {
|
|
19
25
|
expect(workspaceAppIdFromRoute("/apps/mail/inbox")).toBe("mail");
|
|
20
26
|
});
|
|
27
|
+
|
|
28
|
+
it("identifies Dispatch regardless of casing or surrounding whitespace", () => {
|
|
29
|
+
expect(isDispatchWorkspaceAppId(" Dispatch ")).toBe(true);
|
|
30
|
+
expect(isDispatchWorkspaceAppId("dispatch-tools")).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("hides the generic chat starter and Dispatch from default launchers", () => {
|
|
34
|
+
expect(isDefaultWorkspaceAppHiddenId(" Chat ")).toBe(true);
|
|
35
|
+
expect(isWorkspaceAppVisibleInDefaultLaunchers({ id: "chat" })).toBe(false);
|
|
36
|
+
expect(
|
|
37
|
+
isWorkspaceAppVisibleInDefaultLaunchers({
|
|
38
|
+
id: "dispatch",
|
|
39
|
+
isDispatch: true,
|
|
40
|
+
}),
|
|
41
|
+
).toBe(false);
|
|
42
|
+
expect(isWorkspaceAppVisibleInDefaultLaunchers({ id: "mail" })).toBe(true);
|
|
43
|
+
});
|
|
21
44
|
});
|
|
@@ -27,6 +27,21 @@ export interface WorkspaceAppSummary {
|
|
|
27
27
|
archived?: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export function isDispatchWorkspaceAppId(appId: string): boolean {
|
|
31
|
+
return appId.trim().toLowerCase() === "dispatch";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isDefaultWorkspaceAppHiddenId(appId: string): boolean {
|
|
35
|
+
const normalized = appId.trim().toLowerCase();
|
|
36
|
+
return normalized === "chat" || isDispatchWorkspaceAppId(normalized);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isWorkspaceAppVisibleInDefaultLaunchers(
|
|
40
|
+
app: Pick<WorkspaceAppSummary, "id" | "isDispatch">,
|
|
41
|
+
): boolean {
|
|
42
|
+
return !app.isDispatch && !isDefaultWorkspaceAppHiddenId(app.id);
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
export function workspaceAppRoute(appId: string): string {
|
|
31
46
|
return `/apps/${encodeURIComponent(appId)}`;
|
|
32
47
|
}
|
|
@@ -33,7 +33,10 @@ import type {
|
|
|
33
33
|
} from "../../components/workspace-template-card";
|
|
34
34
|
import type { ConnectedAppSummary } from "../../lib/other-apps";
|
|
35
35
|
import { cn } from "../../lib/utils";
|
|
36
|
-
import
|
|
36
|
+
import {
|
|
37
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
38
|
+
type WorkspaceAppSummary,
|
|
39
|
+
} from "../../lib/workspace-apps";
|
|
37
40
|
|
|
38
41
|
export function meta() {
|
|
39
42
|
return [{ title: "Apps — Dispatch" }];
|
|
@@ -72,7 +75,7 @@ function AppsRoute() {
|
|
|
72
75
|
const ws = workspace as WorkspaceInfo | undefined;
|
|
73
76
|
const workspaceLabel = ws?.displayName ?? ws?.name ?? null;
|
|
74
77
|
const allApps = (apps as WorkspaceAppSummary[]).filter(
|
|
75
|
-
|
|
78
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
76
79
|
);
|
|
77
80
|
const visibleApps = allApps.filter((app) => !app.archived);
|
|
78
81
|
const activeApps = visibleApps.filter((app) => app.status !== "pending");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
const mocks = vi.hoisted(() => ({
|
|
4
|
+
authPlugin: vi.fn(),
|
|
5
|
+
createAuthPlugin: vi.fn(),
|
|
6
|
+
getDispatchConfig: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("@agent-native/core/server", () => ({
|
|
10
|
+
createAuthPlugin: mocks.createAuthPlugin,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("../index.js", () => ({
|
|
14
|
+
getDispatchConfig: mocks.getDispatchConfig,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
describe("dispatchAuthPlugin", () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.resetModules();
|
|
20
|
+
mocks.authPlugin.mockReset();
|
|
21
|
+
mocks.createAuthPlugin.mockReset();
|
|
22
|
+
mocks.createAuthPlugin.mockReturnValue(mocks.authPlugin);
|
|
23
|
+
mocks.getDispatchConfig.mockReset();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("installs template public routes on the primary auth guard", async () => {
|
|
27
|
+
const { default: dispatchAuthPlugin } = await import("./auth.js");
|
|
28
|
+
const nitroApp = {};
|
|
29
|
+
const publicPaths = [
|
|
30
|
+
"/_agent-native/identity/authorize",
|
|
31
|
+
"/_agent-native/org/apps",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
mocks.getDispatchConfig.mockReturnValue({
|
|
35
|
+
auth: { googleOnly: true, publicPaths },
|
|
36
|
+
});
|
|
37
|
+
await dispatchAuthPlugin(nitroApp);
|
|
38
|
+
|
|
39
|
+
expect(mocks.createAuthPlugin).toHaveBeenCalledOnce();
|
|
40
|
+
expect(mocks.createAuthPlugin).toHaveBeenCalledWith(
|
|
41
|
+
expect.objectContaining({ googleOnly: true, publicPaths }),
|
|
42
|
+
);
|
|
43
|
+
expect(mocks.authPlugin).toHaveBeenCalledWith(nitroApp);
|
|
44
|
+
});
|
|
45
|
+
});
|