Skip to content

Commit 21f4a43

Browse files
feat: add E2E tests for relative clientDir configuration and implement necessary GraphQL schemas and documents
1 parent 930b906 commit 21f4a43

File tree

6 files changed

+193
-0
lines changed

6 files changed

+193
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* E2E tests for extend package with relative clientDir
3+
*
4+
* This test verifies that client documents from extend packages
5+
* can be scanned using relative paths like '../../apps/main-app/app/graphql'
6+
*
7+
* Scenario:
8+
* monorepo/
9+
* ├── packages/
10+
* │ └── shared-graphql/ ← Extend package with schema
11+
* │ ├── nitro-graphql.config.ts (clientDir: '../../apps/main-app/app/graphql')
12+
* │ └── server/graphql/schema.graphql
13+
* └── apps/
14+
* └── main-app/
15+
* ├── server/graphql/schema.graphql ← Main app schema
16+
* └── app/graphql/products.graphql ← Client documents HERE
17+
*/
18+
import type { Nitro } from 'nitro/types'
19+
import { existsSync, readFileSync } from 'node:fs'
20+
import { build, createNitro, prepare } from 'nitro/builder'
21+
import { join, resolve } from 'pathe'
22+
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
23+
import graphql from '../../src'
24+
25+
const fixturesDir = resolve(__dirname, '../fixtures')
26+
const relativeClientDirFixture = resolve(fixturesDir, 'relative-client-dir')
27+
28+
describe('extend Package with Relative clientDir E2E', () => {
29+
let nitro: Nitro
30+
31+
beforeAll(async () => {
32+
nitro = await createNitro({
33+
rootDir: resolve(relativeClientDirFixture, 'apps/main-app'),
34+
dev: true,
35+
modules: [
36+
graphql({
37+
framework: 'graphql-yoga',
38+
extend: [
39+
// This package has clientDir: '../../apps/main-app/app/graphql'
40+
resolve(relativeClientDirFixture, 'packages/shared-graphql'),
41+
],
42+
}),
43+
],
44+
})
45+
46+
await prepare(nitro)
47+
await build(nitro)
48+
49+
// Generate types
50+
const { generateServerTypes, generateClientTypes } = await import('../../src/nitro/codegen')
51+
await generateServerTypes(nitro)
52+
await generateClientTypes(nitro)
53+
}, 60000)
54+
55+
afterAll(async () => {
56+
await nitro?.close()
57+
})
58+
59+
describe('relative clientDir path resolution', () => {
60+
it('should scan schemas from extend package', () => {
61+
const schemas = nitro.scanSchemas || []
62+
63+
// Should include schema from shared-graphql package
64+
const hasSharedSchema = schemas.some((s: string) =>
65+
s.includes('shared-graphql') && s.includes('schema.graphql'),
66+
)
67+
68+
expect(hasSharedSchema).toBe(true)
69+
})
70+
71+
it('should scan client documents from relative clientDir path', () => {
72+
const docs = nitro.scanDocuments || []
73+
74+
console.log('Scanned documents:', docs)
75+
76+
// Should include products.graphql from apps/main-app/app/graphql
77+
// (resolved from clientDir: '../../apps/main-app/app/graphql')
78+
const hasProductsDoc = docs.some((d: string) =>
79+
d.includes('main-app') && d.includes('products.graphql'),
80+
)
81+
82+
expect(hasProductsDoc).toBe(true)
83+
})
84+
85+
it('should load client documents correctly', async () => {
86+
const { loadGraphQLDocuments } = await import('../../src/core/codegen/document-loader')
87+
88+
const docs = await loadGraphQLDocuments(nitro.scanDocuments)
89+
90+
// Should have loaded documents
91+
expect(docs.length).toBeGreaterThan(0)
92+
93+
// Check that GetAllProducts query is in the loaded documents
94+
const hasGetAllProductsQuery = docs.some(doc =>
95+
doc.document?.definitions.some(def =>
96+
def.kind === 'OperationDefinition' && 'name' in def && def.name?.value === 'GetAllProducts',
97+
),
98+
)
99+
expect(hasGetAllProductsQuery).toBe(true)
100+
})
101+
102+
it('should generate client types with queries from relative clientDir', () => {
103+
const graphqlBuildDir = nitro.graphql.buildDir
104+
const clientTypesPath = join(graphqlBuildDir, 'nitro-graphql-client.d.ts')
105+
106+
// First check if client types were generated
107+
if (existsSync(clientTypesPath)) {
108+
const content = readFileSync(clientTypesPath, 'utf-8')
109+
110+
// Should include GetAllProducts and GetProductById query types
111+
expect(content).toContain('GetAllProducts')
112+
expect(content).toContain('GetProductById')
113+
}
114+
else {
115+
// If no client types, at least verify documents were scanned
116+
const docs = nitro.scanDocuments || []
117+
expect(docs.length).toBeGreaterThan(0)
118+
}
119+
})
120+
})
121+
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
query GetAllProducts {
2+
products {
3+
id
4+
name
5+
price
6+
}
7+
}
8+
9+
query GetProductById($id: ID!) {
10+
product(id: $id) {
11+
id
12+
name
13+
price
14+
}
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// THIS FILE IS GENERATED, DO NOT EDIT!
2+
/* eslint-disable eslint-comments/no-unlimited-disable */
3+
/* tslint:disable */
4+
/* eslint-disable */
5+
/* prettier-ignore */
6+
import type * as Types from '#graphql/client';
7+
8+
import type { ExecutionResult } from 'graphql';
9+
10+
export const GetAllProductsDocument = /*#__PURE__*/ `
11+
query GetAllProducts {
12+
products {
13+
id
14+
name
15+
price
16+
}
17+
}
18+
`;
19+
export const GetProductByIdDocument = /*#__PURE__*/ `
20+
query GetProductById($id: ID!) {
21+
product(id: $id) {
22+
id
23+
name
24+
price
25+
}
26+
}
27+
`;
28+
export type Requester<C = {}, E = unknown> = <R, V>(doc: string, vars?: V, options?: C) => Promise<ExecutionResult<R, E>> | AsyncIterable<ExecutionResult<R, E>>
29+
export function getSdk<C, E>(requester: Requester<C, E>) {
30+
return {
31+
GetAllProducts(variables?: Types.GetAllProductsQueryVariables, options?: C): Promise<ExecutionResult<Types.GetAllProductsQuery, E>> {
32+
return requester<Types.GetAllProductsQuery, Types.GetAllProductsQueryVariables>(GetAllProductsDocument, variables, options) as Promise<ExecutionResult<Types.GetAllProductsQuery, E>>;
33+
},
34+
GetProductById(variables: Types.GetProductByIdQueryVariables, options?: C): Promise<ExecutionResult<Types.GetProductByIdQuery, E>> {
35+
return requester<Types.GetProductByIdQuery, Types.GetProductByIdQueryVariables>(GetProductByIdDocument, variables, options) as Promise<ExecutionResult<Types.GetProductByIdQuery, E>>;
36+
}
37+
};
38+
}
39+
export type Sdk = ReturnType<typeof getSdk>;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type Query {
2+
hello: String!
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Extend package config with relative clientDir pointing to another directory
2+
export default {
3+
serverDir: 'server/graphql',
4+
clientDir: '../../apps/main-app/app/graphql',
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type Query {
2+
products: [Product!]!
3+
product(id: ID!): Product
4+
}
5+
6+
type Product {
7+
id: ID!
8+
name: String!
9+
price: Float!
10+
}

0 commit comments

Comments
 (0)