-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest.ts
More file actions
133 lines (111 loc) · 3.34 KB
/
Copy pathtest.ts
File metadata and controls
133 lines (111 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import bunTest from 'bun:test'
import pino, { type BaseLogger } from 'pino'
import {
Ydb,
type YdbModelsObjectType,
type YdbOptionType,
type YdbRegistryFromModels,
type YdbType,
} from './index.js'
type YdbTestOptions<TModels extends YdbModelsObjectType = YdbModelsObjectType> =
Pick<YdbOptionType<TModels>, 'models'> & { sync?: boolean }
export type TestOptions<
TModels extends YdbModelsObjectType = YdbModelsObjectType,
> = bunTest.TestOptions & YdbTestOptions<TModels>
export type TestCtx<TModels extends YdbModelsObjectType = YdbModelsObjectType> =
{
db: YdbType<YdbRegistryFromModels<TModels>>
logger: BaseLogger
}
export type TestBase = {
expect: typeof bunTest.expect
setSystemTime: typeof bunTest.setSystemTime
mock: typeof bunTest.mock
spyOn: typeof bunTest.spyOn
init: typeof bunTest.beforeAll
teardown: typeof bunTest.afterAll
}
export type TestCallback<
TModels extends YdbModelsObjectType = YdbModelsObjectType,
> = (t: TestBase, ctx: TestCtx<TModels>) => void | Promise<void>
async function prepare<
TModels extends YdbModelsObjectType = YdbModelsObjectType,
>(options?: YdbTestOptions<TModels>) {
const logger = pino({
transport: {
target: 'pino-pretty',
},
level: 'debug',
})
const db = Ydb.init({
endpoint: process.env.YDB_ENDPOINT || '',
database: process.env.YDB_DATABASE || '',
token: process.env.YDB_TOKEN || '',
connectionString: process.env.YDB_CONNECTION_STRING || '',
models: (options?.models || {}) as TModels,
timeout: Number(process.env.YDB_TEST_TIMEOUT || 10000),
logger,
debug: process.env.YDB_DEBUG === '1' || process.env.YDB_DEBUG === 'true',
})
bunTest.afterAll(async () => {
await db.close()
})
const timeout = Number(process.env.YDB_TEST_WAIT_TIMEOUT || 30000)
await db.wait(timeout)
if (options?.sync === true) {
await db.sync()
}
const ctx = {
db,
logger,
} as TestCtx<TModels>
const test: TestBase = {
expect: bunTest.expect,
setSystemTime: bunTest.setSystemTime,
mock: bunTest.mock,
spyOn: bunTest.spyOn,
init: bunTest.beforeAll,
teardown: bunTest.afterAll,
}
return {
test,
ctx,
}
}
type BunTest = (
label: string,
fn: () => undefined | Promise<unknown>,
options?: TestOptions,
) => void
const createTest = (testFunc: BunTest) =>
function testWithCtx<
TModels extends YdbModelsObjectType = YdbModelsObjectType,
>(
name: string,
optionsOrCallback: TestOptions<TModels> | TestCallback<TModels>,
callback?: TestCallback<TModels>,
) {
const options =
typeof optionsOrCallback === 'function' ? undefined : optionsOrCallback
const testCallback =
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback
if (!testCallback) {
throw new Error('test callback is required')
}
return testFunc(
name,
async () => {
const { test, ctx } = await prepare(options)
await testCallback(test, ctx)
},
options,
)
}
export const test = Object.assign(createTest(bunTest.test), {
skip: createTest(bunTest.test.skip),
todo: createTest(bunTest.test.todo),
if: (cond: boolean) => createTest(bunTest.test.if(cond)),
skipIf: (cond: boolean) => createTest(bunTest.test.skipIf(cond)),
...(process.env.CI ? {} : { only: createTest(bunTest.test.only) }),
})
export const it = test