|
@@ -6,6 +6,10 @@ import {DataSource} from '@modal-sh/yasumi/dist/types/backend'; |
|
|
|
|
|
|
|
|
vi.mock('fs/promises'); |
|
|
vi.mock('fs/promises'); |
|
|
|
|
|
|
|
|
|
|
|
const toJsonl = (dummyItems: unknown[]) => dummyItems.map((i) => JSON.stringify(i)).join('\n'); |
|
|
|
|
|
|
|
|
|
|
|
const ID_ATTR = 'id' as const; |
|
|
|
|
|
|
|
|
describe('prepareResource', () => { |
|
|
describe('prepareResource', () => { |
|
|
beforeAll(() => { |
|
|
beforeAll(() => { |
|
|
const mockWriteFile = writeFile as Mock; |
|
|
const mockWriteFile = writeFile as Mock; |
|
@@ -20,8 +24,6 @@ describe('prepareResource', () => { |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const toJsonl = (dummyItems: unknown[]) => dummyItems.map((i) => JSON.stringify(i)).join('\n') |
|
|
|
|
|
|
|
|
|
|
|
describe('methods', () => { |
|
|
describe('methods', () => { |
|
|
const dummyItems = [ |
|
|
const dummyItems = [ |
|
|
{ |
|
|
{ |
|
@@ -45,7 +47,7 @@ describe('methods', () => { |
|
|
beforeEach(() => { |
|
|
beforeEach(() => { |
|
|
mockGenerationStrategy = vi.fn(); |
|
|
mockGenerationStrategy = vi.fn(); |
|
|
const r = resource(schema) |
|
|
const r = resource(schema) |
|
|
.id('id', { |
|
|
|
|
|
|
|
|
.id(ID_ATTR, { |
|
|
generationStrategy: mockGenerationStrategy, |
|
|
generationStrategy: mockGenerationStrategy, |
|
|
schema: v.any(), |
|
|
schema: v.any(), |
|
|
serialize: (id) => id.toString(), |
|
|
serialize: (id) => id.toString(), |
|
@@ -100,8 +102,9 @@ describe('methods', () => { |
|
|
|
|
|
|
|
|
describe('getById', () => { |
|
|
describe('getById', () => { |
|
|
it('works', async () => { |
|
|
it('works', async () => { |
|
|
const item = await ds.getById('2'); // ID is always a string because it originates from URLs |
|
|
|
|
|
const expected = dummyItems.find((i) => i.id === 2); |
|
|
|
|
|
|
|
|
const id = 2; |
|
|
|
|
|
const item = await ds.getById(id.toString()); // ID is always a string because it originates from URLs |
|
|
|
|
|
const expected = dummyItems.find((i) => i[ID_ATTR] === id); |
|
|
expect(item).toEqual(expected); |
|
|
expect(item).toEqual(expected); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
@@ -142,15 +145,15 @@ describe('methods', () => { |
|
|
await ds.delete('1'); |
|
|
await ds.delete('1'); |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect.any(String), |
|
|
expect.any(String), |
|
|
toJsonl(dummyItems.filter((d) => d.id !== 1)), |
|
|
|
|
|
|
|
|
toJsonl(dummyItems.filter((d) => d[ID_ATTR] !== 1)), |
|
|
); |
|
|
); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
describe('emplace', () => { |
|
|
describe('emplace', () => { |
|
|
it('works', async () => { |
|
|
|
|
|
|
|
|
it('replaces existing data', async () => { |
|
|
const data = { |
|
|
const data = { |
|
|
id: 2, |
|
|
|
|
|
|
|
|
[ID_ATTR]: 2, |
|
|
name: 'foo', |
|
|
name: 'foo', |
|
|
}; |
|
|
}; |
|
|
const { id, ...etcData } = data; |
|
|
const { id, ...etcData } = data; |
|
@@ -162,20 +165,41 @@ describe('methods', () => { |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect.any(String), |
|
|
expect.any(String), |
|
|
toJsonl(dummyItems.map((d) => |
|
|
toJsonl(dummyItems.map((d) => |
|
|
d.id === 2 |
|
|
|
|
|
// ID will be defined last, since we are just writing to file, we need strict ordering |
|
|
|
|
|
? { ...etcData, id } |
|
|
|
|
|
|
|
|
d[ID_ATTR] === data[ID_ATTR] |
|
|
|
|
|
// ID will be defined first, since we are just writing to file, we need strict ordering |
|
|
|
|
|
? { [ID_ATTR]: id, ...etcData } |
|
|
: d |
|
|
: d |
|
|
)), |
|
|
)), |
|
|
); |
|
|
); |
|
|
expect(newItem).toEqual([data, false]); |
|
|
expect(newItem).toEqual([data, false]); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it('creates new data', async () => { |
|
|
|
|
|
const data = { |
|
|
|
|
|
[ID_ATTR]: 4, |
|
|
|
|
|
name: 'quux', |
|
|
|
|
|
}; |
|
|
|
|
|
const { [ID_ATTR]: id, ...etcData } = data; |
|
|
|
|
|
const newItem = await ds.emplace( |
|
|
|
|
|
id.toString(), |
|
|
|
|
|
etcData, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
|
|
|
expect.any(String), |
|
|
|
|
|
toJsonl([ |
|
|
|
|
|
...dummyItems, |
|
|
|
|
|
data |
|
|
|
|
|
]), |
|
|
|
|
|
); |
|
|
|
|
|
expect(newItem).toEqual([data, true]); |
|
|
|
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
describe('patch', () => { |
|
|
describe('patch', () => { |
|
|
it('works', async () => { |
|
|
it('works', async () => { |
|
|
const data = { |
|
|
const data = { |
|
|
id: 2, |
|
|
|
|
|
|
|
|
[ID_ATTR]: 2, |
|
|
name: 'foo', |
|
|
name: 'foo', |
|
|
}; |
|
|
}; |
|
|
const { id, ...etcData } = data; |
|
|
const { id, ...etcData } = data; |
|
@@ -187,8 +211,9 @@ describe('methods', () => { |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect(mockWriteFile).toBeCalledWith( |
|
|
expect.any(String), |
|
|
expect.any(String), |
|
|
toJsonl(dummyItems.map((d) => |
|
|
toJsonl(dummyItems.map((d) => |
|
|
d.id === 2 |
|
|
|
|
|
? { ...etcData, id } |
|
|
|
|
|
|
|
|
d[ID_ATTR] === data[ID_ATTR] |
|
|
|
|
|
// ID will be defined first, since we are just writing to file, we need strict ordering |
|
|
|
|
|
? { [ID_ATTR]: id, ...etcData } |
|
|
: d |
|
|
: d |
|
|
)), |
|
|
)), |
|
|
); |
|
|
); |
|
@@ -198,7 +223,7 @@ describe('methods', () => { |
|
|
|
|
|
|
|
|
describe('newId', () => { |
|
|
describe('newId', () => { |
|
|
it('works', async () => { |
|
|
it('works', async () => { |
|
|
const v = 'newId'; |
|
|
|
|
|
|
|
|
const v = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); |
|
|
mockGenerationStrategy.mockResolvedValueOnce(v); |
|
|
mockGenerationStrategy.mockResolvedValueOnce(v); |
|
|
const id = await ds.newId(); |
|
|
const id = await ds.newId(); |
|
|
expect(id).toBe(v); |
|
|
expect(id).toBe(v); |
|
|