-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sync actions for attribute group (#1876)
* feat: add sync actions for attribute group * chore: add changeset
- Loading branch information
1 parent
470456f
commit 27f0d2b
Showing
5 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@commercetools/sync-actions': minor | ||
--- | ||
|
||
Add support for attribute groups `changeName`, `setKey`, `setDescription`, `addAttribute` and `removeAttribute` actions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { buildBaseAttributesActions } from './utils/common-actions' | ||
import createBuildArrayActions, { | ||
ADD_ACTIONS, | ||
REMOVE_ACTIONS, | ||
CHANGE_ACTIONS, | ||
} from './utils/create-build-array-actions' | ||
|
||
const hasAttribute = (attributes, newValue) => | ||
attributes.some((attribute) => attribute.key === newValue.key) | ||
|
||
export const baseActionsList = [ | ||
{ action: 'changeName', key: 'name' }, | ||
{ action: 'setKey', key: 'key' }, | ||
{ action: 'setDescription', key: 'description' }, | ||
] | ||
|
||
export function actionsMapBase(diff, oldObj, newObj, config = {}) { | ||
return buildBaseAttributesActions({ | ||
actions: baseActionsList, | ||
diff, | ||
oldObj, | ||
newObj, | ||
shouldOmitEmptyString: config.shouldOmitEmptyString, | ||
}) | ||
} | ||
|
||
export function actionsMapAttributes(diff, oldObj, newObj) { | ||
const handler = createBuildArrayActions('attributes', { | ||
[ADD_ACTIONS]: (newAttribute) => ({ | ||
action: 'addAttribute', | ||
attribute: newAttribute, | ||
}), | ||
[REMOVE_ACTIONS]: (oldAttribute) => { | ||
// We only add the action if the attribute is not included in the new object. | ||
return !hasAttribute(newObj.attributes, oldAttribute) | ||
? { | ||
action: 'removeAttribute', | ||
attribute: oldAttribute, | ||
} | ||
: null | ||
}, | ||
[CHANGE_ACTIONS]: (oldAttribute, newAttribute) => { | ||
const result = [] | ||
// We only remove the attribute in case that the oldAttribute is not | ||
// included in the new object | ||
if (!hasAttribute(newObj.attributes, oldAttribute)) | ||
result.push({ | ||
action: 'removeAttribute', | ||
attribute: oldAttribute, | ||
}) | ||
|
||
// We only add the attribute in case that the newAttribute was not | ||
// included in the old object | ||
if (!hasAttribute(oldObj.attributes, newAttribute)) | ||
result.push({ | ||
action: 'addAttribute', | ||
attribute: newAttribute, | ||
}) | ||
|
||
return result | ||
}, | ||
}) | ||
|
||
return handler(diff, oldObj, newObj) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* @flow */ | ||
import flatten from 'lodash.flatten' | ||
import type { | ||
SyncAction, | ||
ActionGroup, | ||
UpdateAction, | ||
SyncActionConfig, | ||
} from 'types/sdk' | ||
import * as attributeGroupsActions from './attribute-groups-actions' | ||
import createBuildActions from './utils/create-build-actions' | ||
import createMapActionGroup from './utils/create-map-action-group' | ||
import * as diffpatcher from './utils/diffpatcher' | ||
|
||
function createAttributeGroupsMapActions( | ||
mapActionGroup: ( | ||
type: string, | ||
fn: () => Array<UpdateAction> | ||
) => Array<UpdateAction>, | ||
syncActionConfig: SyncActionConfig | ||
): (diff: Object, newObj: Object, oldObj: Object) => Array<UpdateAction> { | ||
return function doMapActions( | ||
diff: Object, | ||
newObj: Object, | ||
oldObj: Object | ||
): Array<UpdateAction> { | ||
const allActions = [] | ||
allActions.push( | ||
mapActionGroup('base', (): Array<UpdateAction> => | ||
attributeGroupsActions.actionsMapBase( | ||
diff, | ||
oldObj, | ||
newObj, | ||
syncActionConfig | ||
) | ||
) | ||
) | ||
allActions.push( | ||
flatten( | ||
mapActionGroup('attributes', (): Array<UpdateAction> => | ||
attributeGroupsActions.actionsMapAttributes(diff, oldObj, newObj) | ||
) | ||
) | ||
) | ||
return flatten(allActions) | ||
} | ||
} | ||
|
||
export default ( | ||
actionGroupList: Array<ActionGroup>, | ||
syncActionConfig: SyncActionConfig | ||
): SyncAction => { | ||
const mapActionGroup = createMapActionGroup(actionGroupList) | ||
const doMapActions = createAttributeGroupsMapActions( | ||
mapActionGroup, | ||
syncActionConfig | ||
) | ||
const buildActions = createBuildActions(diffpatcher.diff, doMapActions) | ||
return { buildActions } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
205 changes: 205 additions & 0 deletions
205
packages/sync-actions/test/attribute-groups-sync.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
import attributeGroupSyncFn from '../src/attribute-groups' | ||
import { baseActionsList } from '../src/attribute-groups-actions' | ||
|
||
describe('Exports', () => { | ||
test('correctly define base actions list', () => { | ||
expect(baseActionsList).toEqual([ | ||
{ action: 'changeName', key: 'name' }, | ||
{ action: 'setKey', key: 'key' }, | ||
{ action: 'setDescription', key: 'description' }, | ||
]) | ||
}) | ||
}) | ||
|
||
describe('Actions', () => { | ||
let attributeGroupSync | ||
beforeEach(() => { | ||
attributeGroupSync = attributeGroupSyncFn() | ||
}) | ||
|
||
test('should build `changeName` action', () => { | ||
const before = { | ||
name: 'John', | ||
} | ||
const now = { | ||
name: 'Robert', | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [{ action: 'changeName', name: now.name }] | ||
expect(actual).toEqual(expected) | ||
}) | ||
|
||
test('should build `setDescription` action', () => { | ||
const before = { | ||
description: 'some description', | ||
} | ||
const now = { | ||
description: 'some updated description', | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ | ||
action: 'setDescription', | ||
description: now.description, | ||
}, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
|
||
test('should build `setKey` action', () => { | ||
const before = { | ||
key: 'some-key', | ||
} | ||
const now = { | ||
key: 'new-key', | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ | ||
action: 'setKey', | ||
key: now.key, | ||
}, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
|
||
describe('`addAttribute`', () => { | ||
test('should build `addAttribute` action with one attribute', () => { | ||
const before = { | ||
attributes: [], | ||
} | ||
const now = { attributes: [{ key: 'Size' }] } | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'addAttribute', attribute: now.attributes[0] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
test('should build `addAttribute` action with two attributes', () => { | ||
const before = { attributes: [] } | ||
const now = { attributes: [{ key: 'Size' }, { key: 'Brand' }] } | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'addAttribute', attribute: now.attributes[0] }, | ||
{ action: 'addAttribute', attribute: now.attributes[1] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('`removeAttribute`', () => { | ||
test('should build `removeAttribute` action removing one attribute', () => { | ||
const before = { | ||
attributes: [{ key: 'Size' }, { key: 'Brand' }], | ||
} | ||
const now = { attributes: [{ key: 'Size' }] } | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[1] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
test('should build `removeAttribute` action removing two attributes', () => { | ||
const before = { | ||
attributes: [{ key: 'Size' }, { key: 'Brand' }], | ||
} | ||
const now = { attributes: [] } | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[0] }, | ||
{ action: 'removeAttribute', attribute: before.attributes[1] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('Swap attributes (create one + delete one)', () => { | ||
test('should build `removeAttribute` and `addAttribute`', () => { | ||
const before = { attributes: [{ key: 'Size' }] } | ||
const now = { attributes: [{ key: 'Brand' }] } | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[0] }, | ||
{ action: 'addAttribute', attribute: now.attributes[0] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('Multiple actions', () => { | ||
test('should build multiple actions for required changes', () => { | ||
const before = { | ||
attributes: [{ key: 'Size' }, { key: 'Brand' }], | ||
} | ||
const now = { | ||
attributes: [{ key: 'Quality' }, { key: 'Brand' }, { key: 'color' }], | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[0] }, | ||
{ action: 'addAttribute', attribute: now.attributes[0] }, | ||
{ action: 'addAttribute', attribute: now.attributes[2] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('Delete first attributes', () => { | ||
test('should build multiple actions for required changes', () => { | ||
const before = { | ||
attributes: [{ key: 'Size' }, { key: 'Brand' }, { key: 'Color' }], | ||
} | ||
const now = { | ||
attributes: [{ key: 'Color' }], | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[0] }, | ||
{ action: 'removeAttribute', attribute: before.attributes[1] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('Delete multiple attributes', () => { | ||
test('should build multiple actions for required changes', () => { | ||
const before = { | ||
attributes: [ | ||
{ key: 'Size' }, | ||
{ key: 'Brand' }, | ||
{ key: 'Quality' }, | ||
{ key: 'Color' }, | ||
{ key: 'Model' }, | ||
{ key: 'attr-1' }, | ||
], | ||
} | ||
const now = { | ||
attributes: [ | ||
{ key: 'Brand' }, | ||
{ key: 'Quality' }, | ||
{ key: 'Model' }, | ||
{ key: 'attr-2' }, | ||
], | ||
} | ||
|
||
const actual = attributeGroupSync.buildActions(now, before) | ||
const expected = [ | ||
{ action: 'removeAttribute', attribute: before.attributes[0] }, | ||
{ action: 'removeAttribute', attribute: before.attributes[3] }, | ||
{ action: 'addAttribute', attribute: now.attributes[3] }, | ||
{ action: 'removeAttribute', attribute: before.attributes[5] }, | ||
] | ||
expect(actual).toEqual(expected) | ||
}) | ||
}) | ||
}) |