Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

feat(core): delete support in persistCascade for 1-to-1 relations #42 #88

Merged
merged 2 commits into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ describe('The cascaded persist of a resource', () => {

const productResource = Resource.create(1, 'product', { price: 2300 });
const image = Resource.create(null, 'image', { src: 'some/image.png' });
const thumb = Resource.create('2', 'image', { src: 'some/image2.png' });
const author = Resource.create(2, 'person', { name: 'A great author' });

const coverStory = Resource.create(null, 'text', {
text: 'A tale of mystery and wonder.',
Expand All @@ -41,6 +43,8 @@ describe('The cascaded persist of a resource', () => {
const book = Resource.create(1, 'book', {
title: 'A great book',
product: productResource,
thumb,
author,
}, {
product: {
resource: 'product',
Expand All @@ -52,6 +56,16 @@ describe('The cascaded persist of a resource', () => {
cardinality: 'one-to-one',
many: false,
},
thumb: {
cardinality: 'one-to-one',
many: false,
resource: 'image',
},
author: {
cardinality: 'many-to-one',
many: false,
resource: 'person',
},
});

book.data = {
Expand All @@ -66,11 +80,11 @@ describe('The cascaded persist of a resource', () => {

set.persistCascadeResource(book);

expect(set.tasks).toHaveLength(6);
expect(set.tasks).toHaveLength(9);

expect(set.tasks[0].payload).toBe(book);
expect(set.tasks[0].type).toEqual('update');
expect(set.tasks[0].related).toHaveLength(1);
expect(set.tasks[0].related).toHaveLength(3);
expect(set.tasks[0].dependencies).toHaveLength(1);
expect(set.tasks[0].dependencies[0].type).toEqual('create');
expect(set.tasks[0].dependencies[0].payload).toEqual(coverStory);
Expand All @@ -85,33 +99,52 @@ describe('The cascaded persist of a resource', () => {
expect(set.tasks[1].dependencies[0].type).toEqual('create');
expect(set.tasks[1].dependencies[0].payload).toEqual(coverStory);

expect(set.tasks[2].payload).toBe(productResource);
expect(set.tasks[2].type).toEqual('update');
expect(set.tasks[2].related).toHaveLength(0);
expect(set.tasks[2].context).toBe(book);
expect(set.tasks[2].type).toEqual('relation');
expect(set.tasks[2].dependencies).toHaveLength(0);
expect(set.tasks[2].related).toHaveLength(0);
expect(set.tasks[2].payload.relation).toEqual('thumb');
expect(set.tasks[2].payload.resources).toHaveLength(0);

expect(set.tasks[3].context).toBe(book);
expect(set.tasks[3].type).toEqual('relation');
expect(set.tasks[3].dependencies).toHaveLength(0);
expect(set.tasks[3].related).toHaveLength(0);
expect(set.tasks[3].payload.relation).toEqual('author');
expect(set.tasks[3].payload.resources).toHaveLength(0);

expect(set.tasks[3].payload).toBe(coverStory);
expect(set.tasks[3].type).toEqual('create');
expect(set.tasks[3].related).toHaveLength(1);
expect(set.tasks[3].related[0].type).toEqual('relation');
expect(set.tasks[3].related[0].payload.relation).toEqual('image');
expect(set.tasks[3].related[0].payload.resources[0]).toBe(image);
expect(set.tasks[3].dependencies).toHaveLength(1);
expect(set.tasks[3].dependencies[0].type).toEqual('create');
expect(set.tasks[3].dependencies[0].payload).toEqual(image);

expect(set.tasks[4].context).toBe(coverStory);
expect(set.tasks[4].type).toEqual('relation');
expect(set.tasks[4].dependencies).toHaveLength(2);
expect(set.tasks[4].dependencies[0].type).toEqual('create');
expect(set.tasks[4].dependencies[0].payload).toEqual(coverStory);
expect(set.tasks[4].dependencies[1].type).toEqual('create');
expect(set.tasks[4].dependencies[1].payload).toEqual(image);
expect(set.tasks[4].payload).toBe(productResource);
expect(set.tasks[4].type).toEqual('update');
expect(set.tasks[4].related).toHaveLength(0);
expect(set.tasks[4].dependencies).toHaveLength(0);

expect(set.tasks[5].payload).toBe(image);
expect(set.tasks[5].payload).toBe(coverStory);
expect(set.tasks[5].type).toEqual('create');
expect(set.tasks[5].related).toHaveLength(0);
expect(set.tasks[5].dependencies).toHaveLength(0);
expect(set.tasks[5].related).toHaveLength(1);
expect(set.tasks[5].related[0].type).toEqual('relation');
expect(set.tasks[5].related[0].payload.relation).toEqual('image');
expect(set.tasks[5].related[0].payload.resources[0]).toBe(image);
expect(set.tasks[5].dependencies).toHaveLength(1);
expect(set.tasks[5].dependencies[0].type).toEqual('create');
expect(set.tasks[5].dependencies[0].payload).toEqual(image);

expect(set.tasks[6].context).toBe(coverStory);
expect(set.tasks[6].type).toEqual('relation');
expect(set.tasks[6].dependencies).toHaveLength(2);
expect(set.tasks[6].dependencies[0].type).toEqual('create');
expect(set.tasks[6].dependencies[0].payload).toEqual(coverStory);
expect(set.tasks[6].dependencies[1].type).toEqual('create');
expect(set.tasks[6].dependencies[1].payload).toEqual(image);
expect(set.tasks[6].related).toHaveLength(0);

expect(set.tasks[7].payload).toBe(image);
expect(set.tasks[7].type).toEqual('create');
expect(set.tasks[7].related).toHaveLength(0);
expect(set.tasks[7].dependencies).toHaveLength(0);

expect(set.tasks[8].payload).toBe(thumb);
expect(set.tasks[8].type).toEqual('delete');
expect(set.tasks[8].related).toHaveLength(0);
expect(set.tasks[8].dependencies).toHaveLength(0);
});
});
36 changes: 34 additions & 2 deletions packages/core/__tests__/Resource/Change/Relation.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Resource from '../../../src/Resource/Resource';
import {
getChangedResourceRelations,
getAllRelatedResources,
getAllRelatedResources, getDeletedOneToOneRelatedResources,
} from '../../../src/Resource/Change/Relation/Relation';
import { resourceHasChanged } from '../../../src/Resource/Change/Inspection';

Expand Down Expand Up @@ -94,10 +94,42 @@ describe('Relation tests', () => {
});

author.data = {
name: 'An even greated author',
name: 'An even greater author',
};

const changedRelations = getChangedResourceRelations(resource);
expect(changedRelations).toHaveLength(0);
});

test('that a correct list of deleted one-to-one resources is returned', () => {
const author = Resource.create(2, 'author', { name: 'A great author' });
const thumb = Resource.create('2', 'image', { src: 'some/image2.png' });
const resource = Resource.create(1, 'book', {
title: 'A great book',
author,
thumb,
}, {
author: {
resource: 'author',
cardinality: 'many-to-one',
},
thumb: {
resource: 'image',
cardinality: 'one-to-one',
},
coverStory: {
resource: 'cover-story',
cardinality: 'one-to-one',
},
});

resource.data = {
title: 'A great book',
};

const deletedResources = getDeletedOneToOneRelatedResources(resource);

expect(deletedResources).toHaveLength(1);
expect(deletedResources[0]).toBe(thumb);
});
});
37 changes: 32 additions & 5 deletions packages/core/src/Resource/Change/Relation/Relation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import flatten from 'lodash/flatten';
import isEmpty from 'lodash/isEmpty';
import isEqual from 'lodash/isEqual';
import { previousState } from '../../../State/State';
import { resourceIsNew } from '../Inspection';
import { resourceHasChanged, resourceIsNew } from '../Inspection';

/**
* @param {HyralResource} resource
Expand Down Expand Up @@ -47,12 +47,12 @@ export function getChangedResourceRelations(resource) {
return [];
}

if (!resourceIsNew(resource) && previousState(resource.stateStack) === null) {
return [];
if (resourceIsNew(resource)) {
return Object.keys(resource.relationships);
}

if (resourceIsNew(resource) && previousState(resource.stateStack) === null) {
return Object.keys(resource.relationships);
if (!resourceHasChanged(resource)) {
return [];
}

return Object.keys(resource.relationships).filter(relation => !isEqual(
Expand All @@ -64,3 +64,30 @@ export function getChangedResourceRelations(resource) {
),
));
}

/**
* @param {HyralResource} resource
*
* @returns {HyralResource[]}
*/
export function getDeletedOneToOneRelatedResources(resource) {
if (!resource.relationships) {
return [];
}

if (resourceIsNew(resource)) {
return [];
}

if (!resourceHasChanged(resource)) {
return [];
}

return Object.keys(resource.relationships)
.filter(relation => resource.relationships[relation].cardinality === 'one-to-one')
mnugter marked this conversation as resolved.
Show resolved Hide resolved
.filter(relation => getRelatedResources(resource, relation).length === 0)
.filter(
relation => getRelatedResources(previousState(resource.stateStack), relation).length !== 0,
)
.map(relation => getRelatedResources(previousState(resource.stateStack), relation)[0]);
}
3 changes: 3 additions & 0 deletions packages/core/src/Resource/Change/Task/TaskGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Task from './Task';
import {
getAllRelatedResources,
getChangedResourceRelations,
getDeletedOneToOneRelatedResources,
getRelatedResources,
} from '../Relation/Relation';
import setTaskDependencies from './Helpers/setTaskDependencies';
Expand Down Expand Up @@ -59,6 +60,8 @@ export default function TaskGenerator(tasks, repositoryManager) {
relatedResource => this.persistCascadeResource(relatedResource),
);

getDeletedOneToOneRelatedResources(resource).map(this.deleteResource);

setTaskDependencies(tasks);
},
/**
Expand Down