diff --git a/packages/@sanity/mutator/src/document/Mutation.ts b/packages/@sanity/mutator/src/document/Mutation.ts index 0d04d187750..ad145532652 100644 --- a/packages/@sanity/mutator/src/document/Mutation.ts +++ b/packages/@sanity/mutator/src/document/Mutation.ts @@ -106,17 +106,21 @@ export class Mutation { compile(): void { const operations: ((doc: Doc | null) => Doc | null)[] = [] + // creation requires a _createdAt + const getGuaranteedCreatedAt = (doc: Doc): string => + doc?._createdAt || this.params.timestamp || new Date().toISOString() + this.mutations.forEach((mutation) => { if (mutation.create) { // TODO: Fail entire patch if document did exist - const create = mutation.create || {} + const create = (mutation.create || {}) as Doc operations.push((doc): Doc => { if (doc) { return doc } - return Object.assign(create as Doc, { - _createdAt: create._createdAt || this.params.timestamp, + return Object.assign(create, { + _createdAt: getGuaranteedCreatedAt(create), }) }) return @@ -127,7 +131,7 @@ export class Mutation { operations.push((doc) => doc === null ? Object.assign(createIfNotExists, { - _createdAt: createIfNotExists._createdAt || this.params.timestamp, + _createdAt: getGuaranteedCreatedAt(createIfNotExists), }) : doc, ) @@ -138,7 +142,7 @@ export class Mutation { const createOrReplace = mutation.createOrReplace || {} operations.push(() => Object.assign(createOrReplace, { - _createdAt: createOrReplace._createdAt || this.params.timestamp, + _createdAt: getGuaranteedCreatedAt(createOrReplace), }), ) return diff --git a/packages/@sanity/mutator/src/document/types.ts b/packages/@sanity/mutator/src/document/types.ts index acd147e4b7d..215cf2c67d2 100644 --- a/packages/@sanity/mutator/src/document/types.ts +++ b/packages/@sanity/mutator/src/document/types.ts @@ -16,6 +16,7 @@ export interface Doc { _type: string _rev?: string _updatedAt?: string + _createdAt?: string [attribute: string]: unknown } diff --git a/packages/@sanity/mutator/test/SquashingBuffer.test.ts b/packages/@sanity/mutator/test/SquashingBuffer.test.ts index ab5ee308a59..6544bddf769 100644 --- a/packages/@sanity/mutator/test/SquashingBuffer.test.ts +++ b/packages/@sanity/mutator/test/SquashingBuffer.test.ts @@ -1,4 +1,4 @@ -import {expect, test} from '@jest/globals' +import {expect, jest, test} from '@jest/globals' import {type PatchMutationOperation} from '@sanity/types' import {Mutation} from '../src/document/Mutation' @@ -109,7 +109,39 @@ test('de-duplicate createIfNotExists', () => { expect(tx2 && tx2.mutations.length).toBe(1) }) +test.each(['create', 'createIfNotExists', 'createOrReplace'])( + '%s defaults to current created at time', + (createFnc) => { + const globalMockDate = new Date('2020-01-01T12:34:55.000Z') + const globalDateSpy = jest.spyOn(global, 'Date').mockReturnValue(globalMockDate) + + const sb = new SquashingBuffer(null) + + add(sb, {[createFnc]: {_id: '1', _type: 'test', a: 'A string value'}}) + + const tx = sb.purge('txn_id') + if (!tx) { + throw new Error('buffer purge did not result in a mutation') + } + + const final = tx.apply(null) + + expect(final).toEqual({ + _id: '1', + _rev: 'txn_id', + _createdAt: '2020-01-01T12:34:55.000Z', + _type: 'test', + a: 'A string value', + }) + + globalDateSpy.mockRestore() + }, +) + test('de-duplicate create respects deletes', () => { + const globalMockDate = new Date('2020-01-01T12:34:55.000Z') + const globalDateSpy = jest.spyOn(global, 'Date').mockReturnValue(globalMockDate) + const initial = {_id: '1', _type: 'test', a: 'A string value', c: 'Some value'} const sb = new SquashingBuffer(initial) add(sb, {createIfNotExists: {_id: '1', _type: 'test', a: 'A string value', c: 'Some value'}}) @@ -124,7 +156,7 @@ test('de-duplicate create respects deletes', () => { if (!tx) { throw new Error('buffer purge did not result in a mutation') } - tx.params.timestamp = '2021-01-01T12:34:55Z' + tx.params.timestamp = '2021-01-01T12:34:55.000Z' const creates = tx.mutations.filter((mut) => !!mut.createIfNotExists) expect(creates.length).toBe(2) // Only a single create mutation expected (note: bn - is this correct?) @@ -134,14 +166,16 @@ test('de-duplicate create respects deletes', () => { expect(final).toEqual({ _id: '1', _type: 'test', - _createdAt: '2021-01-01T12:34:55Z', - _updatedAt: '2021-01-01T12:34:55Z', + _createdAt: '2020-01-01T12:34:55.000Z', + _updatedAt: '2021-01-01T12:34:55.000Z', _rev: 'txn_id', a: { b: 'A wrapped value', }, c: 'Changed', }) + + globalDateSpy.mockRestore() }) test('de-duplicate create respects rebasing', () => {