Skip to content

Commit b506767

Browse files
committed
Fix server tests for V5
1 parent 3d1ae67 commit b506767

File tree

2 files changed

+94
-94
lines changed

2 files changed

+94
-94
lines changed

@app/server/__tests__/helpers.ts

Lines changed: 90 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
import { Request, Response } from "express";
2-
import { ExecutionResult, graphql, GraphQLSchema } from "graphql";
3-
import { Pool, PoolClient } from "pg";
1+
import { makeWithPgClientViaPgClientAlreadyInTransaction } from "@dataplan/pg/adaptors/pg";
2+
import { execute,hookArgs } from "grafast";
43
import {
5-
createPostGraphileSchema,
6-
PostGraphileOptions,
7-
withPostGraphileContext,
8-
} from "postgraphile";
4+
ExecutionArgs,
5+
ExecutionResult,
6+
GraphQLSchema,
7+
parse,
8+
validate,
9+
} from "graphql";
10+
import { Pool, PoolClient } from "pg";
11+
import { postgraphile,PostGraphileInstance } from "postgraphile";
912

1013
import {
1114
createSession,
1215
createUsers,
1316
poolFromUrl,
1417
} from "../../__tests__/helpers";
15-
import { getPostGraphileOptions } from "../src/graphile.config";
18+
import { getPreset } from "../src/graphile.config";
1619

1720
export * from "../../__tests__/helpers";
1821

@@ -96,7 +99,7 @@ export function sanitize(json: any): any {
9699
// Contains the PostGraphile schema and rootPgPool
97100
interface ICtx {
98101
rootPgPool: Pool;
99-
options: PostGraphileOptions<Request, Response>;
102+
pgl: PostGraphileInstance;
100103
schema: GraphQLSchema;
101104
}
102105
let ctx: ICtx | null = null;
@@ -106,17 +109,14 @@ export const setup = async () => {
106109
connectionString: process.env.TEST_DATABASE_URL,
107110
});
108111

109-
const options = getPostGraphileOptions({ rootPgPool });
110-
const schema = await createPostGraphileSchema(
111-
rootPgPool,
112-
"app_public",
113-
options
114-
);
112+
const preset = getPreset({ rootPgPool, authPgPool: rootPgPool });
113+
const pgl = postgraphile(preset);
114+
const schema = await pgl.getSchema();
115115

116116
// Store the context
117117
ctx = {
118118
rootPgPool,
119-
options,
119+
pgl,
120120
schema,
121121
};
122122
};
@@ -146,9 +146,10 @@ export const runGraphQLQuery = async function runGraphQLQuery(
146146
) => void | ExecutionResult | Promise<void | ExecutionResult> = () => {} // Place test assertions in this function
147147
) {
148148
if (!ctx) throw new Error("No ctx!");
149-
const { schema, rootPgPool, options } = ctx;
149+
const { schema, rootPgPool, pgl } = ctx;
150+
const resolvedPreset = pgl.getResolvedPreset();
150151
const req = new MockReq({
151-
url: options.graphqlRoute || "/graphql",
152+
url: resolvedPreset.grafserv?.graphqlPath || "/graphql",
152153
method: "POST",
153154
headers: {
154155
Accept: "application/json",
@@ -159,92 +160,87 @@ export const runGraphQLQuery = async function runGraphQLQuery(
159160
const res: any = { req };
160161
req.res = res;
161162

162-
const {
163-
pgSettings: pgSettingsGenerator,
164-
additionalGraphQLContextFromRequest,
165-
} = options;
166-
const pgSettings =
167-
(typeof pgSettingsGenerator === "function"
168-
? await pgSettingsGenerator(req)
169-
: pgSettingsGenerator) || {};
163+
let checkResult: ExecutionResult | void;
164+
const document = parse(query);
165+
const errors = validate(schema, document);
166+
if (errors.length > 0) {
167+
throw errors[0];
168+
}
169+
const args: ExecutionArgs = {
170+
schema,
171+
document,
172+
contextValue: {
173+
__TESTING: true,
174+
},
175+
variableValues: variables,
176+
};
177+
await hookArgs(args, { node: { req, res } }, resolvedPreset);
170178

171179
// Because we're connected as the database owner, we should manually switch to
172180
// the authenticator role
173-
if (!pgSettings.role) {
174-
pgSettings.role = process.env.DATABASE_AUTHENTICATOR;
181+
const context = args.contextValue as Grafast.Context;
182+
if (!context.pgSettings?.role) {
183+
context.pgSettings = context.pgSettings ?? {};
184+
context.pgSettings.role = process.env.DATABASE_AUTHENTICATOR as string;
175185
}
176186

177-
await withPostGraphileContext(
178-
{
179-
...options,
180-
pgPool: rootPgPool,
181-
pgSettings,
182-
pgForceTransaction: true,
183-
},
184-
async (context) => {
185-
let checkResult;
186-
const { pgClient } = context;
187-
try {
188-
// This runs our GraphQL query, passing the replacement client
189-
const additionalContext = additionalGraphQLContextFromRequest
190-
? await additionalGraphQLContextFromRequest(req, res)
191-
: null;
192-
const result = await graphql(
193-
schema,
194-
query,
195-
null,
196-
{
197-
...context,
198-
...additionalContext,
199-
__TESTING: true,
200-
},
201-
variables
202-
);
203-
// Expand errors
204-
if (result.errors) {
205-
if (options.handleErrors) {
206-
result.errors = options.handleErrors(result.errors);
207-
} else {
208-
// This does a similar transform that PostGraphile does to errors.
209-
// It's not the same. Sorry.
210-
result.errors = result.errors.map((rawErr) => {
211-
const e = Object.create(rawErr);
212-
Object.defineProperty(e, "originalError", {
213-
value: rawErr.originalError,
214-
enumerable: false,
215-
});
216-
217-
if (e.originalError) {
218-
Object.keys(e.originalError).forEach((k) => {
219-
try {
220-
e[k] = e.originalError[k];
221-
} catch (err) {
222-
// Meh.
223-
}
224-
});
187+
const pgClient = await rootPgPool.connect();
188+
try {
189+
await pgClient.query("begin");
190+
191+
// Override withPgClient with a transactional version for the tests
192+
const withPgClient = makeWithPgClientViaPgClientAlreadyInTransaction(
193+
pgClient,
194+
true
195+
);
196+
context.withPgClient = withPgClient;
197+
198+
const result = (await execute(args, resolvedPreset)) as ExecutionResult;
199+
// Expand errors
200+
if (result.errors) {
201+
if (resolvedPreset.grafserv?.maskError) {
202+
result.errors = result.errors.map(resolvedPreset.grafserv.maskError);
203+
} else {
204+
// This does a similar transform that PostGraphile does to errors.
205+
// It's not the same. Sorry.
206+
result.errors = result.errors.map((rawErr) => {
207+
const e = Object.create(rawErr);
208+
Object.defineProperty(e, "originalError", {
209+
value: rawErr.originalError,
210+
enumerable: false,
211+
});
212+
213+
if (e.originalError) {
214+
Object.keys(e.originalError).forEach((k) => {
215+
try {
216+
e[k] = e.originalError[k];
217+
} catch (err) {
218+
// Meh.
225219
}
226-
return e;
227220
});
228221
}
229-
}
230-
231-
// This is were we call the `checker` so you can do your assertions.
232-
// Also note that we pass the `replacementPgClient` so that you can
233-
// query the data in the database from within the transaction before it
234-
// gets rolled back.
235-
checkResult = await checker(result, {
236-
pgClient,
222+
return e;
237223
});
224+
}
225+
}
238226

239-
// You don't have to keep this, I just like knowing when things change!
240-
expect(sanitize(result)).toMatchSnapshot();
227+
// This is were we call the `checker` so you can do your assertions.
228+
// Also note that we pass the `replacementPgClient` so that you can
229+
// query the data in the database from within the transaction before it
230+
// gets rolled back.
231+
checkResult = await checker(result, {
232+
pgClient,
233+
});
241234

242-
return checkResult == null ? result : checkResult;
243-
} finally {
244-
// Rollback the transaction so no changes are written to the DB - this
245-
// makes our tests fairly deterministic.
246-
await pgClient.query("rollback");
247-
}
235+
// You don't have to keep this, I just like knowing when things change!
236+
expect(sanitize(result)).toMatchSnapshot();
237+
238+
return checkResult == null ? result : checkResult;
239+
} finally {
240+
try {
241+
await pgClient.query("rollback");
242+
} finally {
243+
pgClient.release();
248244
}
249-
);
245+
}
250246
};

@app/server/__tests__/tsconfig.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"include": ["."]
4+
}

0 commit comments

Comments
 (0)