graphile-test 0.1.1 → 2.0.1

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 Dan Lynch <pyramation@gmail.com>
3
+ Copyright (c) 2024 Dan Lynch <pyramation@gmail.com>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,51 +1,53 @@
1
- # graphile-test [![Build Status](https://travis-ci.org/pyramation/graphile-test.svg?branch=master)](https://travis-ci.org/pyramation/graphile-test)
1
+ # graphile-test
2
+
3
+ <p align="center" width="100%">
4
+ <img height="250" src="https://github.com/user-attachments/assets/d0456af5-b6e9-422e-a45d-2574d5be490f" />
5
+ </p>
6
+
7
+ <p align="center" width="100%">
8
+ <a href="https://github.com/launchql/launchql-2.0/actions/workflows/run-tests.yaml">
9
+ <img height="20" src="https://github.com/launchql/launchql-2.0/actions/workflows/run-tests.yaml/badge.svg" />
10
+ </a>
11
+ <a href="https://github.com/launchql/launchql-2.0/blob/main/LICENSE-MIT">
12
+ <img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/>
13
+ </a>
14
+ <a href="https://www.npmjs.com/package/graphile-test">
15
+ <img height="20" src="https://img.shields.io/github/package-json/v/launchql/launchql-2.0?filename=packages%2Fgraphile-test%2Fpackage.json"/>
16
+ </a>
17
+ </p>
18
+
19
+ ## Install
2
20
 
3
21
  ```sh
4
- npm install graphile-test
22
+ npm install graphile-test
5
23
  ```
6
24
 
7
- # how to use
25
+ ---
8
26
 
9
- ## environment vars
27
+ ## How to Use
10
28
 
11
- make sure env vars are set:
12
-
13
- ```
14
- PGUSER
15
- PGPASSWORD
16
- PGHOST
17
- PGPORT
18
- PGDATABASE
19
- SCHEMA
20
- ```
21
-
22
- ## postgres users
29
+ ### 1. Create Required Postgres Role
23
30
 
24
31
  ```sql
25
32
  CREATE ROLE authenticated;
26
33
  ```
27
34
 
28
- ## write test
29
-
30
- Then in a test:
35
+ ---
31
36
 
32
- ```js
33
- import { GraphQLTest, env, snapshot } from 'graphile-test';
34
- import { MyGraphQuery } from '../utils/queries';
37
+ ### 2. Write a Test
35
38
 
36
- const { SCHEMA } = env;
39
+ ```ts
40
+ import { GraphQLTest, snapshot } from 'graphile-test';
41
+ import { MyGraphQLQuery } from '../src/queries';
37
42
 
38
- const getDbString = () =>
39
- `postgres://${env.PGUSER}:${env.PGPASSWORD}@${env.PGHOST}:${env.PGPORT}/${env.PGDATABASE}`;
43
+ const dbname = 'graphile_test_db';
44
+ const schemas = ['app_public'];
40
45
 
41
- const { setup, teardown, graphQL } = GraphQLTest(
42
- {
43
- appendPlugins: [],
44
- schema: SCHEMA,
45
- graphqlRoute: '/graphql'
46
- },
47
- getDbString()
48
- );
46
+ const { setup, teardown, graphQL } = GraphQLTest({
47
+ dbname,
48
+ schemas,
49
+ authRole: 'postgres',
50
+ });
49
51
 
50
52
  beforeAll(async () => {
51
53
  await setup();
@@ -54,18 +56,43 @@ afterAll(async () => {
54
56
  await teardown();
55
57
  });
56
58
 
57
- it('it works!', async () => {
59
+ it('query', async () => {
58
60
  await graphQL(async query => {
59
- const data = await query(MyGraphQuery);
61
+ const data = await query(MyGraphQLQuery);
60
62
  expect(snapshot(data)).toMatchSnapshot();
61
63
  });
62
64
  });
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Testing Setup
70
+
71
+ Before running tests, prepare your database:
63
72
 
73
+ ```sh
74
+ createdb graphile_test_db
75
+ psql -f sql/test.sql graphile_test_db
64
76
  ```
65
77
 
66
- ## testing
78
+ ---
79
+
80
+ ## Environment Variables
81
+
82
+ You can override the default Postgres connection settings by setting the following environment variables:
67
83
 
68
84
  ```sh
69
- createdb test_database
70
- psql test_database < sql/test.sql
71
- ```
85
+ export PGUSER=your_pg_user
86
+ export PGHOST=your_pg_host
87
+ export PGPORT=your_pg_port
88
+ ```
89
+
90
+ Once set, these will be automatically picked up by `graphile-test` when establishing connections.
91
+
92
+ ---
93
+
94
+ ## Disclaimer
95
+
96
+ AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
97
+
98
+ No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
package/clean.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ type AnyObject = Record<string, any>;
2
+ export declare const pruneDates: (row: AnyObject) => AnyObject;
3
+ export declare const pruneIds: (row: AnyObject) => AnyObject;
4
+ export declare const pruneIdArrays: (row: AnyObject) => AnyObject;
5
+ export declare const pruneUUIDs: (row: AnyObject) => AnyObject;
6
+ export declare const pruneHashes: (row: AnyObject) => AnyObject;
7
+ export declare const prune: (obj: AnyObject) => AnyObject;
8
+ export declare const snapshot: (obj: unknown) => unknown;
9
+ export {};
package/clean.js ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.snapshot = exports.prune = exports.pruneHashes = exports.pruneUUIDs = exports.pruneIdArrays = exports.pruneIds = exports.pruneDates = void 0;
4
+ const uuidRegexp = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5
+ const idReplacement = (v) => (!v ? v : '[ID]');
6
+ function mapValues(obj, fn) {
7
+ return Object.entries(obj).reduce((acc, [key, value]) => {
8
+ acc[key] = fn(value, key);
9
+ return acc;
10
+ }, {});
11
+ }
12
+ const pruneDates = (row) => mapValues(row, (v, k) => {
13
+ if (!v) {
14
+ return v;
15
+ }
16
+ if (v instanceof Date) {
17
+ return '[DATE]';
18
+ }
19
+ else if (typeof v === 'string' &&
20
+ /(_at|At)$/.test(k) &&
21
+ /^20[0-9]{2}-[0-9]{2}-[0-9]{2}/.test(v)) {
22
+ return '[DATE]';
23
+ }
24
+ return v;
25
+ });
26
+ exports.pruneDates = pruneDates;
27
+ const pruneIds = (row) => mapValues(row, (v, k) => (k === 'id' || (typeof k === 'string' && k.endsWith('_id'))) &&
28
+ (typeof v === 'string' || typeof v === 'number')
29
+ ? idReplacement(v)
30
+ : v);
31
+ exports.pruneIds = pruneIds;
32
+ const pruneIdArrays = (row) => mapValues(row, (v, k) => typeof k === 'string' && k.endsWith('_ids') && Array.isArray(v)
33
+ ? `[UUIDs-${v.length}]`
34
+ : v);
35
+ exports.pruneIdArrays = pruneIdArrays;
36
+ const pruneUUIDs = (row) => mapValues(row, (v, k) => {
37
+ if (typeof v !== 'string') {
38
+ return v;
39
+ }
40
+ if (['uuid', 'queue_name'].includes(k) && uuidRegexp.test(v)) {
41
+ return '[UUID]';
42
+ }
43
+ if (k === 'gravatar' && /^[0-9a-f]{32}$/i.test(v)) {
44
+ return '[gUUID]';
45
+ }
46
+ return v;
47
+ });
48
+ exports.pruneUUIDs = pruneUUIDs;
49
+ const pruneHashes = (row) => mapValues(row, (v, k) => typeof k === 'string' &&
50
+ k.endsWith('_hash') &&
51
+ typeof v === 'string' &&
52
+ v.startsWith('$')
53
+ ? '[hash]'
54
+ : v);
55
+ exports.pruneHashes = pruneHashes;
56
+ const prune = (obj) => (0, exports.pruneHashes)((0, exports.pruneUUIDs)((0, exports.pruneIds)((0, exports.pruneIdArrays)((0, exports.pruneDates)(obj)))));
57
+ exports.prune = prune;
58
+ const snapshot = (obj) => {
59
+ if (Array.isArray(obj)) {
60
+ return obj.map(exports.snapshot);
61
+ }
62
+ else if (obj && typeof obj === 'object') {
63
+ return mapValues((0, exports.prune)(obj), exports.snapshot);
64
+ }
65
+ return obj;
66
+ };
67
+ exports.snapshot = snapshot;
package/esm/clean.js ADDED
@@ -0,0 +1,57 @@
1
+ const uuidRegexp = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2
+ const idReplacement = (v) => (!v ? v : '[ID]');
3
+ function mapValues(obj, fn) {
4
+ return Object.entries(obj).reduce((acc, [key, value]) => {
5
+ acc[key] = fn(value, key);
6
+ return acc;
7
+ }, {});
8
+ }
9
+ export const pruneDates = (row) => mapValues(row, (v, k) => {
10
+ if (!v) {
11
+ return v;
12
+ }
13
+ if (v instanceof Date) {
14
+ return '[DATE]';
15
+ }
16
+ else if (typeof v === 'string' &&
17
+ /(_at|At)$/.test(k) &&
18
+ /^20[0-9]{2}-[0-9]{2}-[0-9]{2}/.test(v)) {
19
+ return '[DATE]';
20
+ }
21
+ return v;
22
+ });
23
+ export const pruneIds = (row) => mapValues(row, (v, k) => (k === 'id' || (typeof k === 'string' && k.endsWith('_id'))) &&
24
+ (typeof v === 'string' || typeof v === 'number')
25
+ ? idReplacement(v)
26
+ : v);
27
+ export const pruneIdArrays = (row) => mapValues(row, (v, k) => typeof k === 'string' && k.endsWith('_ids') && Array.isArray(v)
28
+ ? `[UUIDs-${v.length}]`
29
+ : v);
30
+ export const pruneUUIDs = (row) => mapValues(row, (v, k) => {
31
+ if (typeof v !== 'string') {
32
+ return v;
33
+ }
34
+ if (['uuid', 'queue_name'].includes(k) && uuidRegexp.test(v)) {
35
+ return '[UUID]';
36
+ }
37
+ if (k === 'gravatar' && /^[0-9a-f]{32}$/i.test(v)) {
38
+ return '[gUUID]';
39
+ }
40
+ return v;
41
+ });
42
+ export const pruneHashes = (row) => mapValues(row, (v, k) => typeof k === 'string' &&
43
+ k.endsWith('_hash') &&
44
+ typeof v === 'string' &&
45
+ v.startsWith('$')
46
+ ? '[hash]'
47
+ : v);
48
+ export const prune = (obj) => pruneHashes(pruneUUIDs(pruneIds(pruneIdArrays(pruneDates(obj)))));
49
+ export const snapshot = (obj) => {
50
+ if (Array.isArray(obj)) {
51
+ return obj.map(snapshot);
52
+ }
53
+ else if (obj && typeof obj === 'object') {
54
+ return mapValues(prune(obj), snapshot);
55
+ }
56
+ return obj;
57
+ };
@@ -0,0 +1,172 @@
1
+ import { getGraphileSettings } from '@launchql/graphile-settings';
2
+ import pg from 'pg';
3
+ import { createPostGraphileSchema, withPostGraphileContext } from 'postgraphile';
4
+ import { graphql } from 'graphql';
5
+ // @ts-ignore
6
+ import MockReq from 'mock-req';
7
+ import { print } from 'graphql/language/printer';
8
+ import { getEnvOptions } from '@launchql/types';
9
+ const opt = getEnvOptions();
10
+ export const GraphQLTest = ({ dbname, schemas, authRole = 'authenticated' }) => {
11
+ const getDbString = (db) => `postgres://${opt.pg.user}:${opt.pg.password}@${opt.pg.host}:${opt.pg.port}/${db}`;
12
+ const options = {
13
+ ...getGraphileSettings({
14
+ graphile: {
15
+ schema: schemas
16
+ }
17
+ }),
18
+ graphqlRoute: '/graphql',
19
+ graphiqlRoute: '/graphiql'
20
+ };
21
+ pg.defaults.poolSize = 1;
22
+ const POSTGRAPHILE_AUTHENTICATOR_ROLE = authRole;
23
+ let ctx = null;
24
+ const setup = async () => {
25
+ const rootPgPool = new pg.Pool({
26
+ connectionString: getDbString(dbname)
27
+ });
28
+ const schema = await createPostGraphileSchema(rootPgPool, schemas, options);
29
+ ctx = { rootPgPool, options, schema };
30
+ };
31
+ const teardown = async () => {
32
+ try {
33
+ if (!ctx)
34
+ return;
35
+ const { rootPgPool } = ctx;
36
+ ctx = null;
37
+ await rootPgPool.end();
38
+ }
39
+ catch (e) {
40
+ console.error(e);
41
+ }
42
+ };
43
+ const graphQL = async (...args) => {
44
+ if (!ctx)
45
+ throw new Error('Context is not initialized. Did you run setup()?');
46
+ let reqOptions = {};
47
+ let checker;
48
+ if (args.length === 1) {
49
+ checker = args[0];
50
+ }
51
+ else if (args.length === 2) {
52
+ reqOptions = args[0];
53
+ checker = args[1];
54
+ }
55
+ else {
56
+ throw new Error('Invalid arguments supplied to graphQL');
57
+ }
58
+ const { schema, rootPgPool, options } = ctx;
59
+ const req = new MockReq({
60
+ url: options.graphqlRoute || '/graphql',
61
+ method: 'POST',
62
+ headers: {
63
+ Accept: 'application/json',
64
+ 'Content-Type': 'application/json'
65
+ },
66
+ ...reqOptions
67
+ });
68
+ const pgSettingsGenerator = options.pgSettings;
69
+ // @ts-ignore
70
+ const pgSettings = typeof pgSettingsGenerator === 'function' ? await pgSettingsGenerator(req) : pgSettingsGenerator || {};
71
+ return await withPostGraphileContext({ ...options, pgPool: rootPgPool, pgSettings }, async (context) => {
72
+ const replacementPgClient = await rootPgPool.connect();
73
+ await replacementPgClient.query('begin');
74
+ await replacementPgClient.query("select set_config('role', $1, true)", [POSTGRAPHILE_AUTHENTICATOR_ROLE]);
75
+ for (const [key, value] of Object.entries(pgSettings)) {
76
+ await replacementPgClient.query("select set_config($1, $2, true)", [key, String(value)]);
77
+ }
78
+ try {
79
+ const query = async (q, variables) => {
80
+ if (typeof q !== 'string')
81
+ q = print(q);
82
+ return await graphql(schema, q, null, { ...context, pgClient: replacementPgClient }, variables);
83
+ };
84
+ return await checker(query, replacementPgClient);
85
+ }
86
+ finally {
87
+ await replacementPgClient.query('rollback');
88
+ replacementPgClient.release();
89
+ }
90
+ });
91
+ };
92
+ const graphQLQuery = async (...args) => {
93
+ if (!ctx)
94
+ throw new Error('Context is not initialized. Did you run setup()?');
95
+ let reqOptions = {};
96
+ let Query;
97
+ let vars;
98
+ let commit = false;
99
+ if (args.length === 1) {
100
+ Query = args[0];
101
+ }
102
+ else if (args.length === 2) {
103
+ if (typeof args[1] === 'boolean') {
104
+ Query = args[0];
105
+ commit = args[1];
106
+ }
107
+ else {
108
+ Query = args[0];
109
+ vars = args[1];
110
+ }
111
+ }
112
+ else if (args.length === 3) {
113
+ if (typeof args[2] === 'boolean') {
114
+ Query = args[0];
115
+ vars = args[1];
116
+ commit = args[2];
117
+ }
118
+ else {
119
+ reqOptions = args[0];
120
+ Query = args[1];
121
+ vars = args[2];
122
+ }
123
+ }
124
+ else if (args.length === 4) {
125
+ reqOptions = args[0];
126
+ Query = args[1];
127
+ vars = args[2];
128
+ commit = args[3];
129
+ }
130
+ else {
131
+ throw new Error('Invalid arguments supplied to graphQLQuery');
132
+ }
133
+ const { schema, rootPgPool, options } = ctx;
134
+ const req = new MockReq({
135
+ url: options.graphqlRoute || '/graphql',
136
+ method: 'POST',
137
+ headers: {
138
+ Accept: 'application/json',
139
+ 'Content-Type': 'application/json'
140
+ },
141
+ ...reqOptions
142
+ });
143
+ const pgSettingsGenerator = options.pgSettings;
144
+ // @ts-ignore
145
+ const pgSettings = typeof pgSettingsGenerator === 'function' ? await pgSettingsGenerator(req) : pgSettingsGenerator || {};
146
+ return await withPostGraphileContext({ ...options, pgPool: rootPgPool, pgSettings }, async (context) => {
147
+ const replacementPgClient = await rootPgPool.connect();
148
+ await replacementPgClient.query('begin');
149
+ await replacementPgClient.query("select set_config('role', $1, true)", [POSTGRAPHILE_AUTHENTICATOR_ROLE]);
150
+ for (const [key, value] of Object.entries(pgSettings)) {
151
+ await replacementPgClient.query("select set_config($1, $2, true)", [key, String(value)]);
152
+ }
153
+ try {
154
+ if (typeof Query !== 'string')
155
+ Query = print(Query);
156
+ return await graphql(schema, Query, null, { ...context, pgClient: replacementPgClient }, vars);
157
+ }
158
+ finally {
159
+ await replacementPgClient.query(commit ? 'commit' : 'rollback');
160
+ replacementPgClient.release();
161
+ }
162
+ });
163
+ };
164
+ return {
165
+ setup,
166
+ teardown,
167
+ graphQL,
168
+ graphQLQuery,
169
+ // @ts-ignore
170
+ withContext: (cb) => cb(ctx)
171
+ };
172
+ };
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './clean';
2
+ export * from './graphile-test';
@@ -0,0 +1,12 @@
1
+ export interface GraphQLTestOptions {
2
+ dbname: string;
3
+ schemas: string[];
4
+ authRole?: string;
5
+ }
6
+ export declare const GraphQLTest: ({ dbname, schemas, authRole }: GraphQLTestOptions) => {
7
+ setup: () => Promise<void>;
8
+ teardown: () => Promise<void>;
9
+ graphQL: (...args: any[]) => Promise<any>;
10
+ graphQLQuery: (...args: any[]) => Promise<any>;
11
+ withContext: <T>(cb: (ctx: typeof ctx) => T) => T;
12
+ };
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GraphQLTest = void 0;
7
+ const graphile_settings_1 = require("@launchql/graphile-settings");
8
+ const pg_1 = __importDefault(require("pg"));
9
+ const postgraphile_1 = require("postgraphile");
10
+ const graphql_1 = require("graphql");
11
+ // @ts-ignore
12
+ const mock_req_1 = __importDefault(require("mock-req"));
13
+ const printer_1 = require("graphql/language/printer");
14
+ const types_1 = require("@launchql/types");
15
+ const opt = (0, types_1.getEnvOptions)();
16
+ const GraphQLTest = ({ dbname, schemas, authRole = 'authenticated' }) => {
17
+ const getDbString = (db) => `postgres://${opt.pg.user}:${opt.pg.password}@${opt.pg.host}:${opt.pg.port}/${db}`;
18
+ const options = {
19
+ ...(0, graphile_settings_1.getGraphileSettings)({
20
+ graphile: {
21
+ schema: schemas
22
+ }
23
+ }),
24
+ graphqlRoute: '/graphql',
25
+ graphiqlRoute: '/graphiql'
26
+ };
27
+ pg_1.default.defaults.poolSize = 1;
28
+ const POSTGRAPHILE_AUTHENTICATOR_ROLE = authRole;
29
+ let ctx = null;
30
+ const setup = async () => {
31
+ const rootPgPool = new pg_1.default.Pool({
32
+ connectionString: getDbString(dbname)
33
+ });
34
+ const schema = await (0, postgraphile_1.createPostGraphileSchema)(rootPgPool, schemas, options);
35
+ ctx = { rootPgPool, options, schema };
36
+ };
37
+ const teardown = async () => {
38
+ try {
39
+ if (!ctx)
40
+ return;
41
+ const { rootPgPool } = ctx;
42
+ ctx = null;
43
+ await rootPgPool.end();
44
+ }
45
+ catch (e) {
46
+ console.error(e);
47
+ }
48
+ };
49
+ const graphQL = async (...args) => {
50
+ if (!ctx)
51
+ throw new Error('Context is not initialized. Did you run setup()?');
52
+ let reqOptions = {};
53
+ let checker;
54
+ if (args.length === 1) {
55
+ checker = args[0];
56
+ }
57
+ else if (args.length === 2) {
58
+ reqOptions = args[0];
59
+ checker = args[1];
60
+ }
61
+ else {
62
+ throw new Error('Invalid arguments supplied to graphQL');
63
+ }
64
+ const { schema, rootPgPool, options } = ctx;
65
+ const req = new mock_req_1.default({
66
+ url: options.graphqlRoute || '/graphql',
67
+ method: 'POST',
68
+ headers: {
69
+ Accept: 'application/json',
70
+ 'Content-Type': 'application/json'
71
+ },
72
+ ...reqOptions
73
+ });
74
+ const pgSettingsGenerator = options.pgSettings;
75
+ // @ts-ignore
76
+ const pgSettings = typeof pgSettingsGenerator === 'function' ? await pgSettingsGenerator(req) : pgSettingsGenerator || {};
77
+ return await (0, postgraphile_1.withPostGraphileContext)({ ...options, pgPool: rootPgPool, pgSettings }, async (context) => {
78
+ const replacementPgClient = await rootPgPool.connect();
79
+ await replacementPgClient.query('begin');
80
+ await replacementPgClient.query("select set_config('role', $1, true)", [POSTGRAPHILE_AUTHENTICATOR_ROLE]);
81
+ for (const [key, value] of Object.entries(pgSettings)) {
82
+ await replacementPgClient.query("select set_config($1, $2, true)", [key, String(value)]);
83
+ }
84
+ try {
85
+ const query = async (q, variables) => {
86
+ if (typeof q !== 'string')
87
+ q = (0, printer_1.print)(q);
88
+ return await (0, graphql_1.graphql)(schema, q, null, { ...context, pgClient: replacementPgClient }, variables);
89
+ };
90
+ return await checker(query, replacementPgClient);
91
+ }
92
+ finally {
93
+ await replacementPgClient.query('rollback');
94
+ replacementPgClient.release();
95
+ }
96
+ });
97
+ };
98
+ const graphQLQuery = async (...args) => {
99
+ if (!ctx)
100
+ throw new Error('Context is not initialized. Did you run setup()?');
101
+ let reqOptions = {};
102
+ let Query;
103
+ let vars;
104
+ let commit = false;
105
+ if (args.length === 1) {
106
+ Query = args[0];
107
+ }
108
+ else if (args.length === 2) {
109
+ if (typeof args[1] === 'boolean') {
110
+ Query = args[0];
111
+ commit = args[1];
112
+ }
113
+ else {
114
+ Query = args[0];
115
+ vars = args[1];
116
+ }
117
+ }
118
+ else if (args.length === 3) {
119
+ if (typeof args[2] === 'boolean') {
120
+ Query = args[0];
121
+ vars = args[1];
122
+ commit = args[2];
123
+ }
124
+ else {
125
+ reqOptions = args[0];
126
+ Query = args[1];
127
+ vars = args[2];
128
+ }
129
+ }
130
+ else if (args.length === 4) {
131
+ reqOptions = args[0];
132
+ Query = args[1];
133
+ vars = args[2];
134
+ commit = args[3];
135
+ }
136
+ else {
137
+ throw new Error('Invalid arguments supplied to graphQLQuery');
138
+ }
139
+ const { schema, rootPgPool, options } = ctx;
140
+ const req = new mock_req_1.default({
141
+ url: options.graphqlRoute || '/graphql',
142
+ method: 'POST',
143
+ headers: {
144
+ Accept: 'application/json',
145
+ 'Content-Type': 'application/json'
146
+ },
147
+ ...reqOptions
148
+ });
149
+ const pgSettingsGenerator = options.pgSettings;
150
+ // @ts-ignore
151
+ const pgSettings = typeof pgSettingsGenerator === 'function' ? await pgSettingsGenerator(req) : pgSettingsGenerator || {};
152
+ return await (0, postgraphile_1.withPostGraphileContext)({ ...options, pgPool: rootPgPool, pgSettings }, async (context) => {
153
+ const replacementPgClient = await rootPgPool.connect();
154
+ await replacementPgClient.query('begin');
155
+ await replacementPgClient.query("select set_config('role', $1, true)", [POSTGRAPHILE_AUTHENTICATOR_ROLE]);
156
+ for (const [key, value] of Object.entries(pgSettings)) {
157
+ await replacementPgClient.query("select set_config($1, $2, true)", [key, String(value)]);
158
+ }
159
+ try {
160
+ if (typeof Query !== 'string')
161
+ Query = (0, printer_1.print)(Query);
162
+ return await (0, graphql_1.graphql)(schema, Query, null, { ...context, pgClient: replacementPgClient }, vars);
163
+ }
164
+ finally {
165
+ await replacementPgClient.query(commit ? 'commit' : 'rollback');
166
+ replacementPgClient.release();
167
+ }
168
+ });
169
+ };
170
+ return {
171
+ setup,
172
+ teardown,
173
+ graphQL,
174
+ graphQLQuery,
175
+ // @ts-ignore
176
+ withContext: (cb) => cb(ctx)
177
+ };
178
+ };
179
+ exports.GraphQLTest = GraphQLTest;
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './clean';
2
+ export * from './graphile-test';
package/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./clean"), exports);
18
+ __exportStar(require("./graphile-test"), exports);