Skip to content

Commit cde9827

Browse files
authored
Merge pull request #3167 from SeedCompany/edgedb/tests
2 parents b394e58 + 020717f commit cde9827

File tree

6 files changed

+108
-14
lines changed

6 files changed

+108
-14
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
run: yarn test --reporters=github-actions
2323

2424
E2E:
25-
name: E2E Tests (${{ matrix.shard }}/6)
25+
name: E2E Tests (${{ matrix.database }} ${{ matrix.shard }}/6)
2626
runs-on: ubuntu-latest
2727

2828
services:
@@ -47,6 +47,7 @@ jobs:
4747
strategy:
4848
matrix:
4949
shard: [1, 2, 3, 4, 5, 6]
50+
database: [neo4j, edgedb]
5051
fail-fast: false
5152
steps:
5253
- uses: actions/checkout@v4
@@ -60,3 +61,5 @@ jobs:
6061
run: yarn test:e2e --shard=${{ matrix.shard }}/6 --reporters=github-actions
6162
env:
6263
NEO4J_VERSION: ${{ matrix.neo4j-version }}
64+
DATABASE: ${{ matrix.database }}
65+
continue-on-error: ${{ matrix.database == 'edgedb' }}

src/common/and-call.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { FnLike } from '@seedcompany/common';
2+
import { isPromise } from 'node:util/types';
3+
import { ConditionalKeys } from 'type-fest';
4+
5+
export const andCall = <
6+
T,
7+
K extends ConditionalKeys<T, FnLike>,
8+
X extends T[K] & FnLike,
9+
>(
10+
thing: T,
11+
methodName: K,
12+
add: X,
13+
) => {
14+
const orig = (thing[methodName] as FnLike).bind(thing);
15+
(thing[methodName] as FnLike) = () => {
16+
const res = orig();
17+
return isPromise(res) ? res.then((x) => add(x)) : add(res);
18+
};
19+
};

src/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { Many, many, maybeMany, JsonSet, ArrayItem } from '@seedcompany/common';
22

3+
export * from './and-call';
34
export * from './temporal';
45
export * from './calculated.decorator';
56
export * from './context.type';

src/core/edgedb/edgedb.module.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Module, OnModuleDestroy } from '@nestjs/common';
22
import { APP_INTERCEPTOR } from '@nestjs/core';
3-
import { createClient, Duration } from 'edgedb';
3+
import { ConnectOptions, createClient, Duration } from 'edgedb';
44
import { IdResolver } from '~/common/validators/short-id.validator';
55
import type { ConfigService } from '~/core';
66
import { splitDb } from '../database/split-db.provider';
@@ -30,13 +30,22 @@ import { TransactionContext } from './transaction.context';
3030
}),
3131
},
3232
OptionsContext,
33+
{
34+
provide: 'EDGEDB_CONNECT',
35+
useValue: {} satisfies ConnectOptions,
36+
},
3337
{
3438
provide: Client,
35-
inject: [OptionsContext, 'CONFIG'],
36-
useFactory: async (options: OptionsContext, config: ConfigService) => {
39+
inject: [OptionsContext, 'EDGEDB_CONNECT', 'CONFIG'],
40+
useFactory: async (
41+
options: OptionsContext,
42+
connectConfig: ConnectOptions,
43+
config: ConfigService,
44+
) => {
3745
const client = createClient({
3846
// Only for connection retry warnings. Skip.
3947
logging: false,
48+
...connectConfig,
4049
});
4150

4251
Object.assign(client, { options: options.currentAsLazyRef });

test/utility/create-app.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { faker } from '@faker-js/faker';
22
import { INestApplication } from '@nestjs/common';
33
import { Test } from '@nestjs/testing';
4+
import { andCall } from '~/common';
45
import { AppModule } from '../../src/app.module';
56
import { LogLevel } from '../../src/core/logger';
67
import { LevelMatcher } from '../../src/core/logger/level-matcher';
78
import {
89
createGraphqlClient,
910
GraphQLTestClient,
1011
} from './create-graphql-client';
12+
import { ephemeralEdgeDB } from './edgedb-setup';
1113

1214
// Patch faker email to be more unique
1315
const origEmail = faker.internet.email.bind(faker.internet);
@@ -19,16 +21,29 @@ export interface TestApp extends INestApplication {
1921
}
2022

2123
export const createTestApp = async () => {
22-
const moduleFixture = await Test.createTestingModule({
23-
imports: [AppModule],
24-
})
25-
.overrideProvider(LevelMatcher)
26-
.useValue(new LevelMatcher([], LogLevel.ERROR))
27-
.compile();
24+
const db = await ephemeralEdgeDB();
2825

29-
const app = moduleFixture.createNestApplication<TestApp>();
30-
await app.init();
31-
app.graphql = await createGraphqlClient(app);
26+
try {
27+
const moduleFixture = await Test.createTestingModule({
28+
imports: [AppModule],
29+
})
30+
.overrideProvider(LevelMatcher)
31+
.useValue(new LevelMatcher([], LogLevel.ERROR))
32+
.overrideProvider('EDGEDB_CONNECT')
33+
.useValue(db?.options)
34+
.compile();
3235

33-
return app;
36+
const app = moduleFixture.createNestApplication<TestApp>();
37+
await app.init();
38+
app.graphql = await createGraphqlClient(app);
39+
40+
andCall(app, 'close', async () => {
41+
await db?.cleanup();
42+
});
43+
44+
return app;
45+
} catch (e) {
46+
await db?.cleanup();
47+
throw e;
48+
}
3449
};

test/utility/edgedb-setup.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Client, ConnectOptions, createClient } from 'edgedb';
2+
import { DateTime } from 'luxon';
3+
4+
export const ephemeralEdgeDB = async () => {
5+
if (process.env.DATABASE !== 'edgedb') {
6+
return undefined;
7+
}
8+
9+
const db = createClient();
10+
11+
await dropStale(db);
12+
13+
const branch = `test_${Date.now()}`;
14+
15+
await db.execute(`create schema branch ${branch} from main`);
16+
17+
const cleanup = async () => {
18+
await db.execute(`drop branch ${branch}`);
19+
await db.close();
20+
};
21+
22+
const options: ConnectOptions = { branch };
23+
24+
return { options, cleanup };
25+
};
26+
27+
async function dropStale(db: Client) {
28+
const branches = await db.query<string>('select sys::Database.name');
29+
30+
const stale = branches.flatMap((name) => {
31+
if (!name.startsWith('test_')) {
32+
return [];
33+
}
34+
const ts = Number(name.slice(5));
35+
if (isNaN(ts)) {
36+
return [];
37+
}
38+
const createdAt = DateTime.fromMillis(ts);
39+
return createdAt.diffNow().as('hours') > 4 ? name : [];
40+
});
41+
if (stale.length === 0) {
42+
return;
43+
}
44+
await db.execute('drop branch array_unpack(<array<string>>$branches)', {
45+
branches: stale,
46+
});
47+
}

0 commit comments

Comments
 (0)