@apollo/client-ai-apps 0.7.2 → 0.7.4

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.
Files changed (41) hide show
  1. package/.github/workflows/pr.yaml +35 -0
  2. package/.github/workflows/prep-release.yml +4 -3
  3. package/.github/workflows/release.yaml +8 -5
  4. package/.github/workflows/verify-changeset.yml +4 -4
  5. package/CHANGELOG.md +16 -0
  6. package/dist/utilities/getToolNamesFromDocument.d.ts +1 -1
  7. package/dist/utilities/getToolNamesFromDocument.d.ts.map +1 -1
  8. package/dist/utilities/getToolNamesFromDocument.js +14 -5
  9. package/dist/utilities/getToolNamesFromDocument.js.map +1 -1
  10. package/dist/vite/apolloClientAiApps.d.ts.map +1 -1
  11. package/dist/vite/apolloClientAiApps.js +2 -1
  12. package/dist/vite/apolloClientAiApps.js.map +1 -1
  13. package/integration-tests/docker-compose.yml +30 -0
  14. package/integration-tests/global-teardown.js +9 -0
  15. package/integration-tests/graphql-server/Dockerfile +12 -0
  16. package/integration-tests/graphql-server/package.json +10 -0
  17. package/integration-tests/graphql-server/server.ts +22 -0
  18. package/integration-tests/mcp-config.yaml +29 -0
  19. package/integration-tests/mock-app/index.html +12 -0
  20. package/integration-tests/mock-app/package.json +24 -0
  21. package/integration-tests/mock-app/src/App.tsx +23 -0
  22. package/integration-tests/mock-app/src/main.tsx +22 -0
  23. package/integration-tests/mock-app/src/tools/Echo.tsx +33 -0
  24. package/integration-tests/mock-app/src/tools/Hello.tsx +19 -0
  25. package/integration-tests/mock-app/src/tools/Private.tsx +34 -0
  26. package/integration-tests/mock-app/src/tools/SemiPrivate.tsx +34 -0
  27. package/integration-tests/mock-app/tsconfig.json +25 -0
  28. package/integration-tests/mock-app/vite.config.ts +22 -0
  29. package/integration-tests/package-lock.json +5749 -0
  30. package/integration-tests/package.json +20 -0
  31. package/integration-tests/playwright.config.ts +23 -0
  32. package/integration-tests/schema.graphql +10 -0
  33. package/integration-tests/tests/hello.spec.ts +11 -0
  34. package/integration-tests/tests/privateDirective.spec.ts +73 -0
  35. package/integration-tests/tests/variables.spec.ts +24 -0
  36. package/package.json +5 -5
  37. package/src/react/__tests__/createHydrationUtils.test.tsx +62 -0
  38. package/src/utilities/getToolNamesFromDocument.ts +19 -7
  39. package/src/vite/__tests__/apolloClientAiApps.test.ts +161 -62
  40. package/src/vite/apolloClientAiApps.ts +2 -1
  41. package/vitest.config.ts +2 -1
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "integration-tests",
3
+ "private": true,
4
+ "type": "module",
5
+ "workspaces": [
6
+ "./graphql-server",
7
+ "./mock-app"
8
+ ],
9
+ "scripts": {
10
+ "build:lib": "npm run build --prefix ..",
11
+ "build:mock-app": "npm run build --workspace mock-app",
12
+ "pretest": "npm-run-all build:*",
13
+ "test": "playwright test"
14
+ },
15
+ "devDependencies": {
16
+ "@apollo/mcp-impostor-host": "^0.3.0",
17
+ "@playwright/test": "^1.59.1",
18
+ "npm-run-all": "^4.1.5"
19
+ }
20
+ }
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ export default defineConfig({
4
+ testDir: "./tests",
5
+ globalTeardown: "./global-teardown.js",
6
+ webServer: [
7
+ {
8
+ command: "npx serve-impostor-host --playwright",
9
+ url: "http://localhost:8080",
10
+ reuseExistingServer: !process.env.CI,
11
+ },
12
+ {
13
+ command: "docker compose up --build",
14
+ url: "http://localhost:8000/health",
15
+ reuseExistingServer: !process.env.CI,
16
+ },
17
+ ],
18
+ workers: 1,
19
+ use: {
20
+ browserName: "chromium",
21
+ trace: "retain-on-failure",
22
+ },
23
+ });
@@ -0,0 +1,10 @@
1
+ type Query {
2
+ hello: String!
3
+ echo(message: String!): String!
4
+ user: User
5
+ }
6
+
7
+ type User {
8
+ address: String
9
+ fullName: String
10
+ }
@@ -0,0 +1,11 @@
1
+ import { test } from "@apollo/mcp-impostor-host/playwright";
2
+ import { expect } from "@playwright/test";
3
+
4
+ const URL = "http://localhost:8000/mcp?app=mock-app&appTarget=mcp";
5
+
6
+ test("renders data from a tool with no arguments", async ({ mcpHost }) => {
7
+ const connection = await mcpHost.connect({ url: URL });
8
+ const { appFrame } = await connection.callTool("Hello");
9
+
10
+ await expect(appFrame.getByTestId("greeting")).toHaveText("Hello, world!");
11
+ });
@@ -0,0 +1,73 @@
1
+ import { test } from "@apollo/mcp-impostor-host/playwright";
2
+ import { expect } from "@playwright/test";
3
+
4
+ const URL = "http://localhost:8000/mcp?app=mock-app&appTarget=mcp";
5
+
6
+ test("omits private field in structuredContent, but available to the view", async ({
7
+ mcpHost,
8
+ }) => {
9
+ const connection = await mcpHost.connect({ url: URL });
10
+ const { result, appFrame } = await connection.callTool("SemiPrivate");
11
+
12
+ expect(result.structuredContent).toEqual({
13
+ result: {
14
+ data: {
15
+ user: {
16
+ __typename: "User",
17
+ fullName: "MCP User",
18
+ },
19
+ },
20
+ },
21
+ toolName: "SemiPrivate",
22
+ });
23
+
24
+ expect(result._meta).toEqual({
25
+ toolName: "SemiPrivate",
26
+ structuredContent: {
27
+ result: {
28
+ data: {
29
+ user: {
30
+ __typename: "User",
31
+ address: "1234 Main St",
32
+ fullName: "MCP User",
33
+ },
34
+ },
35
+ },
36
+ toolName: "SemiPrivate",
37
+ },
38
+ });
39
+
40
+ await expect(appFrame.getByTestId("fullName")).toHaveText("MCP User");
41
+ await expect(appFrame.getByTestId("address")).toHaveText("1234 Main St");
42
+ });
43
+
44
+ test("omits full selection sets, but available to the view", async ({
45
+ mcpHost,
46
+ }) => {
47
+ const connection = await mcpHost.connect({ url: URL });
48
+ const { result, appFrame } = await connection.callTool("Private");
49
+
50
+ expect(result.structuredContent).toEqual({
51
+ result: { data: {} },
52
+ toolName: "Private",
53
+ });
54
+
55
+ expect(result._meta).toEqual({
56
+ toolName: "Private",
57
+ structuredContent: {
58
+ result: {
59
+ data: {
60
+ user: {
61
+ __typename: "User",
62
+ address: "1234 Main St",
63
+ fullName: "MCP User",
64
+ },
65
+ },
66
+ },
67
+ toolName: "Private",
68
+ },
69
+ });
70
+
71
+ await expect(appFrame.getByTestId("fullName")).toHaveText("MCP User");
72
+ await expect(appFrame.getByTestId("address")).toHaveText("1234 Main St");
73
+ });
@@ -0,0 +1,24 @@
1
+ import { test } from "@apollo/mcp-impostor-host/playwright";
2
+ import { expect } from "@playwright/test";
3
+
4
+ const URL = "http://localhost:8000/mcp?app=mock-app&appTarget=mcp";
5
+
6
+ test("renders data from a tool with arguments", async ({ mcpHost }) => {
7
+ const connection = await mcpHost.connect({ url: URL });
8
+ const { result, appFrame } = await connection.callTool("Echo", {
9
+ message: "Hello!",
10
+ });
11
+
12
+ expect(result.structuredContent).toStrictEqual({
13
+ toolName: "Echo",
14
+ result: {
15
+ data: {
16
+ echo: "Hello! (Hello!)",
17
+ },
18
+ },
19
+ });
20
+ expect(result._meta).toStrictEqual({
21
+ toolName: "Echo",
22
+ });
23
+ await expect(appFrame.getByTestId("echo")).toHaveText("Hello! (Hello!)");
24
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@apollo/client-ai-apps",
4
- "version": "0.7.2",
4
+ "version": "0.7.4",
5
5
  "keywords": [
6
6
  "apollo",
7
7
  "graphql",
@@ -104,7 +104,7 @@
104
104
  "attw": "npm run build && attw --pack . --ignore-rules cjs-resolves-to-esm --profile node16"
105
105
  },
106
106
  "devDependencies": {
107
- "@apollo/client": "^4.0.12",
107
+ "@apollo/client": "^4.1.7",
108
108
  "@arethetypeswrong/cli": "^0.18.2",
109
109
  "@modelcontextprotocol/ext-apps": "^1.0.1",
110
110
  "@testing-library/jest-dom": "^6.9.1",
@@ -119,6 +119,7 @@
119
119
  "esbuild": "^0.25.12",
120
120
  "graphql": "^16.12.0",
121
121
  "happy-dom": "^20.0.10",
122
+ "jiti": "^2.6.1",
122
123
  "memfs": "^4.56.10",
123
124
  "mock-require": "^3.0.3",
124
125
  "prettier": "^3.7.4",
@@ -144,9 +145,8 @@
144
145
  }
145
146
  },
146
147
  "dependencies": {
147
- "@graphql-codegen/cli": "^6.1.3",
148
- "@graphql-codegen/typescript": "^5.0.9",
149
- "@graphql-codegen/typescript-operations": "^5.0.9",
148
+ "@graphql-codegen/cli": "^7.1.0",
149
+ "@graphql-codegen/typescript-operations": "^6.0.3",
150
150
  "@graphql-tools/graphql-tag-pluck": "^8.3.23",
151
151
  "@wry/equality": "^0.5.7",
152
152
  "cosmiconfig": "^9.0.0",
@@ -77,6 +77,68 @@ eachHostEnv((setupHost, ApolloClient) => {
77
77
  await expect(takeSnapshot).not.toRerender();
78
78
  });
79
79
 
80
+ test("returns tool input value when @tool name is defined by operation name", async () => {
81
+ using _ = spyOnConsole("debug");
82
+
83
+ const query: TypedDocumentNode<
84
+ { products: Array<{ __typename: "Product"; id: string }> },
85
+ { category: string; page: number; sortBy: string }
86
+ > = gql`
87
+ "Get products by category"
88
+ query Products($category: String!, $page: Int!, $sortBy: String!) @tool {
89
+ products(category: $category, page: $page, sortBy: $sortBy) {
90
+ id
91
+ }
92
+ }
93
+ `;
94
+
95
+ const client = new ApolloClient({
96
+ cache: new InMemoryCache(),
97
+ manifest: mockApplicationManifest({
98
+ operations: [parseManifestOperation(query)],
99
+ }),
100
+ });
101
+
102
+ using env = await setupHost({
103
+ client,
104
+ toolCall: {
105
+ name: "Products",
106
+ input: { category: "electronics", page: 1, sortBy: "title" },
107
+ result: { structuredContent: { result: { data: { products: [] } } } },
108
+ },
109
+ });
110
+ const { host, params } = env;
111
+
112
+ host.sendToolInput(params.toolInput);
113
+ host.sendToolResult(params.toolResult);
114
+
115
+ const { useHydratedVariables } = createHydrationUtils(query);
116
+
117
+ using _disabledAct = disableActEnvironment();
118
+ const { takeSnapshot } = await renderHookToSnapshotStream(
119
+ () =>
120
+ useHydratedVariables({
121
+ category: "music",
122
+ page: 1,
123
+ sortBy: "name",
124
+ }),
125
+ {
126
+ wrapper: ({ children }) => (
127
+ <ApolloProvider client={client}>{children}</ApolloProvider>
128
+ ),
129
+ }
130
+ );
131
+
132
+ const [variables] = await takeSnapshot();
133
+ expect(variables).toStrictEqual({
134
+ category: "electronics",
135
+ page: 1,
136
+ sortBy: "title",
137
+ });
138
+
139
+ await expect(takeSnapshot).not.toRerender();
140
+ });
141
+
80
142
  test("returns user-provided variables when tool name does not match", async () => {
81
143
  using _ = spyOnConsole("debug");
82
144
  const query = gql`
@@ -1,15 +1,27 @@
1
1
  import { getOperationDefinition } from "@apollo/client/utilities/internal";
2
- import { Kind, type DocumentNode } from "graphql";
2
+ import { Kind, type DirectiveNode, type DocumentNode } from "graphql";
3
3
 
4
4
  export function getToolNamesFromDocument(document: DocumentNode) {
5
5
  const operationDef = getOperationDefinition(document);
6
+ const operationName = operationDef?.name?.value;
7
+ const toolDirectives =
8
+ operationDef?.directives?.filter((d) => d.name.value === "tool") ?? [];
9
+
10
+ if (toolDirectives.length === 1) {
11
+ return new Set([
12
+ getToolNameFromDirective(toolDirectives[0]) ?? operationName,
13
+ ]);
14
+ }
6
15
 
7
16
  return new Set(
8
- operationDef?.directives
9
- ?.filter((d) => d.name.value === "tool")
10
- .flatMap((d) => {
11
- const nameArg = d.arguments?.find((arg) => arg.name.value === "name");
12
- return nameArg?.value.kind === Kind.STRING ? [nameArg.value.value] : [];
13
- })
17
+ toolDirectives.flatMap((d) => {
18
+ const name = getToolNameFromDirective(d);
19
+ return name ? [name] : [];
20
+ })
14
21
  );
15
22
  }
23
+
24
+ function getToolNameFromDirective(directive: DirectiveNode) {
25
+ const nameArg = directive.arguments?.find((arg) => arg.name.value === "name");
26
+ return nameArg?.value.kind === Kind.STRING ? nameArg.value.value : undefined;
27
+ }
@@ -2061,43 +2061,16 @@ describe("tool input types", () => {
2061
2061
  );
2062
2062
  expect(content).toMatchInlineSnapshot(`
2063
2063
  "// Auto-generated by @apollo/client-ai-apps. Do not edit manually.
2064
- export type Maybe<T> = T | null;
2065
-
2066
- export type InputMaybe<T> = Maybe<T>;
2067
-
2068
- export type Exact<T extends {
2064
+ /** Internal type. DO NOT USE DIRECTLY. */
2065
+ type Exact<T extends {
2069
2066
  [key: string]: unknown;
2070
2067
  }> = {
2071
2068
  [K in keyof T]: T[K];
2072
2069
  };
2073
2070
 
2074
- /** All built-in and custom scalars, mapped to their actual values */
2075
- export type Scalars = {
2076
- ID: {
2077
- input: string;
2078
- output: string;
2079
- };
2080
- String: {
2081
- input: string;
2082
- output: string;
2083
- };
2084
- Boolean: {
2085
- input: boolean;
2086
- output: boolean;
2087
- };
2088
- Int: {
2089
- input: number;
2090
- output: number;
2091
- };
2092
- Float: {
2093
- input: number;
2094
- output: number;
2095
- };
2096
- };
2097
-
2098
2071
  export type CreateTodoMutationVariables = Exact<{
2099
- title: Scalars["String"]["input"];
2100
- description?: InputMaybe<Scalars["String"]["input"]>;
2072
+ title: string;
2073
+ description?: string | null | undefined;
2101
2074
  }>;"
2102
2075
  `);
2103
2076
  });
@@ -2126,6 +2099,26 @@ describe("tool input types", () => {
2126
2099
  });
2127
2100
  await server.listen();
2128
2101
 
2102
+ expect(
2103
+ fs.readFileSync(
2104
+ ".apollo-client-ai-apps/types/operation-types.d.ts",
2105
+ "utf-8"
2106
+ )
2107
+ ).toMatchInlineSnapshot(`
2108
+ "// Auto-generated by @apollo/client-ai-apps. Do not edit manually.
2109
+ /** Internal type. DO NOT USE DIRECTLY. */
2110
+ type Exact<T extends {
2111
+ [key: string]: unknown;
2112
+ }> = {
2113
+ [K in keyof T]: T[K];
2114
+ };
2115
+
2116
+ export type CreateTodoMutationVariables = Exact<{
2117
+ title: string;
2118
+ description?: string | null | undefined;
2119
+ }>;"
2120
+ `);
2121
+
2129
2122
  const content = fs.readFileSync(
2130
2123
  ".apollo-client-ai-apps/types/register.d.ts",
2131
2124
  "utf-8"
@@ -2147,6 +2140,71 @@ describe("tool input types", () => {
2147
2140
  `);
2148
2141
  });
2149
2142
 
2143
+ test("uses operation name and description for tool name/description when @tool is used without arguments", async () => {
2144
+ vol.fromJSON({
2145
+ "package.json": mockPackageJson(),
2146
+ "src/my-component.tsx": declareOperation(gql`
2147
+ """
2148
+ Creates a todo
2149
+ """
2150
+ mutation CreateTodo($title: String!, $description: String) @tool {
2151
+ createTodo(title: $title, description: $description) {
2152
+ id
2153
+ }
2154
+ }
2155
+ `),
2156
+ });
2157
+
2158
+ await using server = await setupServer({
2159
+ plugins: [
2160
+ apolloClientAiApps({
2161
+ targets: ["mcp"],
2162
+ appsOutDir: "dist/apps",
2163
+ schema,
2164
+ }),
2165
+ ],
2166
+ });
2167
+ await server.listen();
2168
+
2169
+ expect(
2170
+ fs.readFileSync(
2171
+ ".apollo-client-ai-apps/types/operation-types.d.ts",
2172
+ "utf-8"
2173
+ )
2174
+ ).toMatchInlineSnapshot(`
2175
+ "// Auto-generated by @apollo/client-ai-apps. Do not edit manually.
2176
+ /** Internal type. DO NOT USE DIRECTLY. */
2177
+ type Exact<T extends {
2178
+ [key: string]: unknown;
2179
+ }> = {
2180
+ [K in keyof T]: T[K];
2181
+ };
2182
+
2183
+ export type CreateTodoMutationVariables = Exact<{
2184
+ title: string;
2185
+ description?: string | null | undefined;
2186
+ }>;"
2187
+ `);
2188
+
2189
+ expect(
2190
+ fs.readFileSync(".apollo-client-ai-apps/types/register.d.ts", "utf-8")
2191
+ ).toMatchInlineSnapshot(`
2192
+ "// This file is auto-generated by @apollo/client-ai-apps. Do not edit manually.
2193
+ import "@apollo/client-ai-apps";
2194
+
2195
+ import type { CreateTodoMutationVariables } from "./operation-types.js";
2196
+
2197
+ declare module "@apollo/client-ai-apps" {
2198
+ interface Register {
2199
+ toolName: "CreateTodo";
2200
+ toolInputs: {
2201
+ CreateTodo: CreateTodoMutationVariables;
2202
+ };
2203
+ }
2204
+ }"
2205
+ `);
2206
+ });
2207
+
2150
2208
  test("generates register.d.ts with operations that contain fragments", async () => {
2151
2209
  vol.fromJSON({
2152
2210
  "package.json": mockPackageJson(),
@@ -2201,43 +2259,16 @@ describe("tool input types", () => {
2201
2259
  )
2202
2260
  ).toMatchInlineSnapshot(`
2203
2261
  "// Auto-generated by @apollo/client-ai-apps. Do not edit manually.
2204
- export type Maybe<T> = T | null;
2205
-
2206
- export type InputMaybe<T> = Maybe<T>;
2207
-
2208
- export type Exact<T extends {
2262
+ /** Internal type. DO NOT USE DIRECTLY. */
2263
+ type Exact<T extends {
2209
2264
  [key: string]: unknown;
2210
2265
  }> = {
2211
2266
  [K in keyof T]: T[K];
2212
2267
  };
2213
2268
 
2214
- /** All built-in and custom scalars, mapped to their actual values */
2215
- export type Scalars = {
2216
- ID: {
2217
- input: string;
2218
- output: string;
2219
- };
2220
- String: {
2221
- input: string;
2222
- output: string;
2223
- };
2224
- Boolean: {
2225
- input: boolean;
2226
- output: boolean;
2227
- };
2228
- Int: {
2229
- input: number;
2230
- output: number;
2231
- };
2232
- Float: {
2233
- input: number;
2234
- output: number;
2235
- };
2236
- };
2237
-
2238
2269
  export type CreateTodoMutationVariables = Exact<{
2239
- title: Scalars["String"]["input"];
2240
- description?: InputMaybe<Scalars["String"]["input"]>;
2270
+ title: string;
2271
+ description?: string | null | undefined;
2241
2272
  }>;"
2242
2273
  `);
2243
2274
  });
@@ -2546,6 +2577,74 @@ describe("tool input types", () => {
2546
2577
  }"
2547
2578
  `);
2548
2579
  });
2580
+
2581
+ test("generates matching variable type names for operations with lowercase names", async () => {
2582
+ vol.fromJSON({
2583
+ "package.json": mockPackageJson(),
2584
+ "src/my-component.tsx": declareOperation(gql`
2585
+ "Creates a todo"
2586
+ mutation createTodo($title: String!, $description: String) @tool {
2587
+ createTodo(title: $title, description: $description) {
2588
+ id
2589
+ }
2590
+ }
2591
+ `),
2592
+ });
2593
+
2594
+ await using server = await setupServer({
2595
+ plugins: [
2596
+ apolloClientAiApps({
2597
+ targets: ["mcp"],
2598
+ appsOutDir: "dist/apps",
2599
+ schema,
2600
+ }),
2601
+ ],
2602
+ });
2603
+ await server.listen();
2604
+
2605
+ const operationTypes = fs.readFileSync(
2606
+ ".apollo-client-ai-apps/types/operation-types.d.ts",
2607
+ "utf-8"
2608
+ );
2609
+ const register = fs.readFileSync(
2610
+ ".apollo-client-ai-apps/types/register.d.ts",
2611
+ "utf-8"
2612
+ );
2613
+
2614
+ // operation-types.d.ts should export a variables type for the operation.
2615
+ expect(operationTypes).toMatchInlineSnapshot(`
2616
+ "// Auto-generated by @apollo/client-ai-apps. Do not edit manually.
2617
+ /** Internal type. DO NOT USE DIRECTLY. */
2618
+ type Exact<T extends {
2619
+ [key: string]: unknown;
2620
+ }> = {
2621
+ [K in keyof T]: T[K];
2622
+ };
2623
+
2624
+ export type createTodoMutationVariables = Exact<{
2625
+ title: string;
2626
+ description?: string | null | undefined;
2627
+ }>;"
2628
+ `);
2629
+
2630
+ // register.d.ts must import the same variables type name that
2631
+ // operation-types.d.ts exports.
2632
+ expect(register).toMatchInlineSnapshot(`
2633
+ "// This file is auto-generated by @apollo/client-ai-apps. Do not edit manually.
2634
+ import "@apollo/client-ai-apps";
2635
+
2636
+ import type { createTodoMutationVariables } from "./operation-types.js";
2637
+
2638
+ declare module "@apollo/client-ai-apps" {
2639
+ interface Register {
2640
+ toolName: "createTodo";
2641
+ toolInputs: {
2642
+ createTodo: createTodoMutationVariables;
2643
+ };
2644
+ }
2645
+ }"
2646
+ `);
2647
+ });
2549
2648
  });
2550
2649
 
2551
2650
  describe("html transforms", () => {
@@ -299,10 +299,11 @@ async function generateOperationTypes(
299
299
  documents,
300
300
  generates: {
301
301
  "operation-types.d.ts": {
302
- plugins: ["typescript", "typescript-operations"],
302
+ plugins: ["typescript-operations"],
303
303
  config: {
304
304
  nonOptionalTypename: true,
305
305
  skipTypeNameForRoot: true,
306
+ namingConvention: "keep",
306
307
  } satisfies TypeScriptDocumentsPluginConfig,
307
308
  },
308
309
  },
package/vitest.config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "vitest/config";
1
+ import { defineConfig, defaultExclude } from "vitest/config";
2
2
  import react from "@vitejs/plugin-react";
3
3
 
4
4
  export default defineConfig({
@@ -8,6 +8,7 @@ export default defineConfig({
8
8
  setupFiles: ["./vitest-setup.ts"],
9
9
  mockReset: true,
10
10
  unstubGlobals: true,
11
+ exclude: [...defaultExclude, "integration-tests/**"],
11
12
  tags: [
12
13
  {
13
14
  name: "flaky",