Skip to content

Commit

Permalink
fix(@aws-amplify/datastore): consecutive saves 2 (#8038)
Browse files Browse the repository at this point in the history
  • Loading branch information
iartemiev committed Apr 15, 2021
1 parent c1ce5ac commit a15b8f0
Show file tree
Hide file tree
Showing 12 changed files with 425 additions and 204 deletions.
37 changes: 31 additions & 6 deletions packages/datastore/__tests__/DataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,13 @@ describe('DataStore tests', () => {
const result = await DataStore.save(model);

const [settingsSave, modelCall] = <any>save.mock.calls;
const [_model, _condition, _mutator] = modelCall;
const [_model, _condition, _mutator, patches] = modelCall;

expect(result).toMatchObject(model);
expect(patches).toBeUndefined();
});

test('Save returns the updated model', async () => {
test('Save returns the updated model and patches', async () => {
let model: Model;
const save = jest.fn(() => [model]);
const query = jest.fn(() => [model]);
Expand Down Expand Up @@ -437,12 +438,17 @@ describe('DataStore tests', () => {
const result = await DataStore.save(model);

const [settingsSave, modelSave, modelUpdate] = <any>save.mock.calls;
const [_model, _condition, _mutator] = modelUpdate;
const [_model, _condition, _mutator, [patches]] = modelUpdate;

const expectedPatches = [
{ op: 'replace', path: ['field1'], value: 'edited' },
];

expect(result).toMatchObject(model);
expect(patches).toMatchObject(expectedPatches);
});

test('Save returns the updated model - list field', async () => {
test('Save returns the updated model and patches - list field', async () => {
let model: Model;
const save = jest.fn(() => [model]);
const query = jest.fn(() => [model]);
Expand Down Expand Up @@ -499,8 +505,27 @@ describe('DataStore tests', () => {
save.mock.calls
);

const [_model, _condition, _mutator] = modelUpdate;
const [_model2, _condition2, _mutator2] = modelUpdate2;
const [_model, _condition, _mutator, [patches]] = modelUpdate;
const [_model2, _condition2, _mutator2, [patches2]] = modelUpdate2;

const expectedPatches = [
{
op: 'replace',
path: ['emails'],
value: ['john@doe.com', 'jane@doe.com', 'joe@doe.com'],
},
];

const expectedPatches2 = [
{
op: 'add',
path: ['emails', 3],
value: 'joe@doe.com',
},
];

expect(patches).toMatchObject(expectedPatches);
expect(patches2).toMatchObject(expectedPatches2);
});

test('Instantiation validations', async () => {
Expand Down
5 changes: 2 additions & 3 deletions packages/datastore/__tests__/outbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,9 @@ async function instantiateOutbox(): Promise<void> {

outbox = new MutationEventOutbox(
schema,
userClasses,
MutationEvent,
ownSymbol,
getModelDefinition
modelInstanceCreator,
ownSymbol
);
merger = new ModelMerger(outbox, ownSymbol);
}
Expand Down
123 changes: 116 additions & 7 deletions packages/datastore/__tests__/storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,62 @@ describe('Storage tests', () => {
expect(modelUpdate.element.field1).toEqual('edited');
});

test('scalar - unchanged', async () => {
const classes = initSchema(testSchema());

const { Model } = classes as {
Model: PersistentModelConstructor<Model>;
};

const dateCreated = new Date().toISOString();

const model = await DataStore.save(
new Model({
field1: 'Some value',
dateCreated,
})
);

await DataStore.save(
Model.copyOf(model, draft => {
draft.field1 = 'Some value';
})
);

const [[_modelSave], modelUpdate] = zenNext.mock.calls;

expect(modelUpdate).toBeUndefined();
expect(modelUpdate).toBeUndefined();

expect(true).toBeTruthy();
});

test('update by nulling previous value', async () => {
const classes = initSchema(testSchema());

const { Model } = classes as {
Model: PersistentModelConstructor<Model>;
};

const model = await DataStore.save(
new Model({
field1: 'Some value',
optionalField1: 'Some optional value',
dateCreated: new Date().toISOString(),
})
);

await DataStore.save(
Model.copyOf(model, draft => {
draft.optionalField1 = null;
})
);

const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

expect(modelUpdate.element.optionalField1).toBeNull();
});

test('list (destructured)', async () => {
const classes = initSchema(testSchema());

Expand All @@ -86,7 +142,7 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

const expectedValueEmails = [
'john@doe.com',
Expand Down Expand Up @@ -120,7 +176,7 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

const expectedValueEmails = [
'john@doe.com',
Expand All @@ -133,7 +189,7 @@ describe('Storage tests', () => {
expect(modelUpdate.element.emails).toMatchObject(expectedValueEmails);
});

test('list unchanged', async () => {
test('update with changed field and list unchanged', async () => {
const classes = initSchema(testSchema());

const { Model } = classes as {
Expand All @@ -156,13 +212,66 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

expect(modelUpdate.element.dateCreated).toBeUndefined();
expect(modelUpdate.element.field1).toEqual('Updated value');
expect(modelUpdate.element.emails).toBeUndefined();
});

test('update with list unchanged', async () => {
const classes = initSchema(testSchema());

const { Model } = classes as {
Model: PersistentModelConstructor<Model>;
};

const model = await DataStore.save(
new Model({
field1: 'Some value',
dateCreated: new Date().toISOString(),
emails: ['john@doe.com', 'jane@doe.com'],
})
);

await DataStore.save(
Model.copyOf(model, draft => {
// same as above. should not result in mutation event
draft.emails = ['john@doe.com', 'jane@doe.com'];
})
);

const [[_modelSave], modelUpdate] = zenNext.mock.calls;

expect(modelUpdate).toBeUndefined();
});

test('update by nulling list', async () => {
const classes = initSchema(testSchema());

const { Model } = classes as {
Model: PersistentModelConstructor<Model>;
};

const model = await DataStore.save(
new Model({
field1: 'Some value',
dateCreated: new Date().toISOString(),
emails: ['john@doe.com', 'jane@doe.com'],
})
);

await DataStore.save(
Model.copyOf(model, draft => {
draft.emails = null;
})
);

const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

expect(modelUpdate.element.emails).toBeNull();
});

test('custom type (destructured)', async () => {
const classes = initSchema(testSchema());

Expand Down Expand Up @@ -191,7 +300,7 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

const expectedValueMetadata = {
author: 'some author',
Expand Down Expand Up @@ -231,7 +340,7 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

const expectedValueMetadata = {
author: 'some author',
Expand Down Expand Up @@ -276,7 +385,7 @@ describe('Storage tests', () => {
})
);

const [[modelSave], [modelUpdate]] = zenNext.mock.calls;
const [[_modelSave], [modelUpdate]] = zenNext.mock.calls;

expect(modelUpdate.element.dateCreated).toBeUndefined();
expect(modelUpdate.element.field1).toEqual('Updated value');
Expand Down
Loading

0 comments on commit a15b8f0

Please sign in to comment.