1
import type { Knex } from 'knex';
2
import knex from 'knex';
3
import { createTracker, MockClient, Tracker } from 'knex-mock-client';
4
import type { MockedFunction } from 'vitest';
5
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
import { snapshotApplyTestSchema } from '../__utils__/schemas.js';
8
snapshotBeforeCreateCollection,
9
snapshotBeforeDeleteCollection,
10
snapshotCreateCollection,
11
snapshotCreateCollectionNotNested,
12
} from '../__utils__/snapshots.js';
13
import { CollectionsService, FieldsService } from '../services/index.js';
14
import type { Snapshot, SnapshotField } from '../types/index.js';
15
import { applySnapshot } from './apply-snapshot.js';
16
import * as getSchema from './get-schema.js';
18
class Client_PG extends MockClient {}
20
describe('applySnapshot', () => {
21
let db: MockedFunction<Knex>;
24
const mutationOptions = {
25
autoPurgeSystemCache: false,
26
bypassEmitAction: expect.any(Function),
31
db = vi.mocked(knex.default({ client: Client_PG }));
32
tracker = createTracker(db);
40
describe('Creating new collection(s)', () => {
41
it('Creates new top-level collection(s)', async () => {
43
collection: 'test_table_2',
45
accountability: 'all',
46
collection: 'test_table_2',
49
icon: 'import_export',
50
item_duplication_fields: null,
56
schema: { name: 'test_table_2' },
59
collection: 'test_table_2',
62
collection: 'test_table_2',
65
display_options: null,
78
validation_message: null,
84
foreign_key_column: null,
85
foreign_key_table: null,
86
generation_expression: null,
87
has_auto_increment: false,
94
numeric_precision: null,
96
table: 'test_table_2',
104
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
106
const createOneCollectionSpy = vi.spyOn(CollectionsService.prototype, 'createOne').mockResolvedValue('test');
107
const createFieldSpy = vi.spyOn(FieldsService.prototype, 'createField').mockResolvedValue();
109
await applySnapshot(snapshotCreateCollectionNotNested, {
111
current: snapshotBeforeCreateCollection,
112
schema: snapshotApplyTestSchema,
115
expect(createOneCollectionSpy).toHaveBeenCalledTimes(1);
116
expect(createOneCollectionSpy).toHaveBeenCalledWith(expected, mutationOptions);
120
expect(createFieldSpy).toHaveBeenCalledTimes(0);
123
it('Creates the highest-level nested collection(s) with existing parents and any children', async () => {
125
collection: 'test_table_2',
127
accountability: 'all',
128
collection: 'test_table_2',
131
icon: 'import_export',
132
item_duplication_fields: null,
138
schema: { name: 'test_table_2' },
141
collection: 'test_table_2',
144
collection: 'test_table_2',
147
display_options: null,
160
validation_message: null,
166
foreign_key_column: null,
167
foreign_key_table: null,
168
generation_expression: null,
169
has_auto_increment: false,
172
is_primary_key: true,
176
numeric_precision: null,
178
table: 'test_table_2',
186
collection: 'test_table_3',
189
collection: 'test_table_3',
192
collection: 'test_table_3',
195
display_options: null,
208
validation_message: null,
214
foreign_key_column: null,
215
foreign_key_table: null,
216
generation_expression: null,
217
has_auto_increment: false,
220
is_primary_key: true,
224
numeric_precision: null,
226
table: 'test_table_3',
232
accountability: 'all',
233
collection: 'test_table_3',
234
group: 'test_table_2',
236
icon: 'import_export',
237
item_duplication_fields: null,
243
schema: { name: 'test_table_3' },
247
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
249
const createOneCollectionSpy = vi.spyOn(CollectionsService.prototype, 'createOne').mockResolvedValue('test');
250
const createFieldSpy = vi.spyOn(FieldsService.prototype, 'createField').mockResolvedValue();
252
await applySnapshot(snapshotCreateCollection, {
254
current: snapshotBeforeCreateCollection,
255
schema: snapshotApplyTestSchema,
258
expect(createOneCollectionSpy).toHaveBeenCalledTimes(2);
259
expect(createOneCollectionSpy).toHaveBeenCalledWith(expected, mutationOptions);
260
expect(createOneCollectionSpy).toHaveBeenCalledWith(expected2, mutationOptions);
264
expect(createFieldSpy).toHaveBeenCalledTimes(0);
268
describe('Creating new collection with UUID primary key field', () => {
269
const fieldSchemaMaxLength = 36;
271
it.each(['char', 'varchar'])(
272
'casts non-postgres schema snapshots of UUID fields as %s(36) to UUID type',
273
async (fieldSchemaDataType) => {
274
const snapshotToApply: Snapshot = {
279
collection: 'test_uuid_table',
281
accountability: 'all',
282
collection: 'test_uuid_table',
286
item_duplication_fields: null,
291
schema: { name: 'test_uuid_table' },
296
collection: 'test_uuid_table',
299
collection: 'test_uuid_table',
302
display_options: null,
315
validation_message: null,
320
data_type: fieldSchemaDataType,
322
foreign_key_column: null,
323
foreign_key_schema: null,
324
foreign_key_table: null,
325
generation_expression: null,
326
has_auto_increment: false,
329
is_primary_key: true,
331
max_length: fieldSchemaMaxLength,
333
numeric_precision: null,
335
table: 'test_uuid_table',
344
collection: 'test_uuid_table',
346
accountability: 'all',
347
collection: 'test_uuid_table',
351
item_duplication_fields: null,
356
schema: { name: 'test_uuid_table' },
359
collection: 'test_uuid_table',
362
collection: 'test_uuid_table',
365
display_options: null,
378
validation_message: null,
384
foreign_key_column: null,
385
foreign_key_table: null,
386
generation_expression: null,
387
has_auto_increment: false,
390
is_primary_key: true,
394
numeric_precision: null,
396
table: 'test_uuid_table',
404
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
406
const createOneCollectionSpy = vi.spyOn(CollectionsService.prototype, 'createOne').mockResolvedValue('test');
407
vi.spyOn(FieldsService.prototype, 'createField').mockResolvedValue();
409
await applySnapshot(snapshotToApply, {
418
schema: snapshotApplyTestSchema,
421
expect(createOneCollectionSpy).toHaveBeenCalledOnce();
422
expect(createOneCollectionSpy).toHaveBeenCalledWith(expected, mutationOptions);
427
describe('Delete collections', () => {
428
it('Deletes interrelated collections', async () => {
429
const snapshotToApply: Snapshot = {
438
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
440
const deleteOneCollectionSpy = vi.spyOn(CollectionsService.prototype, 'deleteOne').mockResolvedValue('test');
442
await applySnapshot(snapshotToApply, {
444
current: snapshotBeforeDeleteCollection,
445
schema: snapshotApplyTestSchema,
448
expect(deleteOneCollectionSpy).toHaveBeenCalledTimes(3);