Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/silly-doors-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools/sync-actions': patch
---

Fix `types` sync actions to generate `removeEnumValues`/`removeLocalizedEnumValues` update actions when values are removed from an `Enum`/`LocalizedEnum` field definition. Previously, removed enum values were silently dropped and no update action was produced.
28 changes: 27 additions & 1 deletion packages/sync-actions/src/types/types-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import isEqual from 'lodash.isequal';
import createBuildArrayActions, {
ADD_ACTIONS,
CHANGE_ACTIONS,
REMOVE_ACTIONS,
} from '../utils/create-build-array-actions';
import { buildBaseAttributesActions } from '../utils/common-actions';
import * as diffPatcher from '../utils/diffpatcher';
Expand Down Expand Up @@ -68,12 +69,22 @@ function actionsMapEnums<S extends CustomFieldEnumType>(
? 'changeEnumValueOrder'
: 'changeLocalizedEnumValueOrder';

const removeEnumActionName =
attributeType === 'Enum'
? 'removeEnumValues'
: 'removeLocalizedEnumValues';

const buildArrayActions = createBuildArrayActions('values', {
[ADD_ACTIONS]: (newEnum: CustomFieldEnumType) => ({
fieldName,
action: addEnumActionName,
value: newEnum,
}),
[REMOVE_ACTIONS]: (oldEnum: CustomFieldEnumValue) => ({
fieldName,
action: removeEnumActionName,
key: oldEnum.key,
}),
[CHANGE_ACTIONS]: (
oldEnum: CustomFieldEnumValue,
newEnum: CustomFieldEnumValue
Expand Down Expand Up @@ -126,18 +137,33 @@ function actionsMapEnums<S extends CustomFieldEnumType>(

const actions = [];
// following lists are necessary to ensure that when we change the
// order of enumValues, we generate one updateAction instead of one at a time.
// order of enumValues, or remove enumValues, we generate one updateAction
// instead of one at a time.
let newEnumValuesOrder = [];
const removedEnumValueKeys = [];

buildArrayActions(attributeDiff, previous, next)
.flat()
.forEach((updateAction) => {
if (updateAction.action === changeEnumOrderActionName) {
newEnumValuesOrder = next.values.map((enumValue) => enumValue.key);
} else if (updateAction.action === removeEnumActionName) {
removedEnumValueKeys.push(updateAction.key);
} else actions.push(updateAction);
});

return [
// Make sure to execute the removal of enum values before adding/changing
// any, in case a removed key is reused by a newly added value.
...(removedEnumValueKeys.length > 0
? [
{
fieldName,
action: removeEnumActionName,
keys: removedEnumValueKeys,
},
]
: []),
...actions,
...(newEnumValuesOrder.length > 0
? [
Expand Down
93 changes: 92 additions & 1 deletion packages/sync-actions/test/types-sync-enums.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,49 @@ describe('Actions', () => {
});
});

describe('with enum value removed', () => {
beforeEach(() => {
before = createTestType({
fieldDefinitions: [
{
name: 'enum',
type: {
name: 'Enum',
values: [
{ key: 'enum_1', label: 'enum-1' },
{ key: 'enum_2', label: 'enum-2' },
{ key: 'enum_3', label: 'enum-3' },
],
},
},
],
});

now = createTestType({
fieldDefinitions: [
{
name: 'enum',
type: {
name: 'Enum',
values: [{ key: 'enum_1', label: 'enum-1' }],
},
},
],
});
updateActions = typesSync.buildActions(now, before);
});

test('should return `removeEnumValues` updateAction with all removed keys', () => {
expect(updateActions).toEqual([
{
action: 'removeEnumValues',
fieldName: 'enum',
keys: ['enum_2', 'enum_3'],
},
]);
});
});

describe('with enum reordered', () => {
beforeEach(() => {
before = createTestType({
Expand Down Expand Up @@ -259,8 +302,13 @@ describe('Actions', () => {
updateActions = typesSync.buildActions(now, before);
});

test('should return `addLocalizedEnumValue` updateAction', () => {
test('should return `removeLocalizedEnumValues` and `addLocalizedEnumValue` updateActions', () => {
expect(updateActions).toEqual([
{
fieldName: 'lenum',
action: 'removeLocalizedEnumValues',
keys: ['enum_4'],
},
{
fieldName: 'lenum',
action: 'addLocalizedEnumValue',
Expand All @@ -273,6 +321,49 @@ describe('Actions', () => {
});
});

describe('with lenum value removed', () => {
beforeEach(() => {
before = createTestType({
fieldDefinitions: [
{
name: 'lenum',
type: {
name: 'lenum',
values: [
{ key: 'enum_1', label: { en: 'enum-1' } },
{ key: 'enum_2', label: { en: 'enum-2' } },
{ key: 'enum_3', label: { en: 'enum-3' } },
],
},
},
],
});

now = createTestType({
fieldDefinitions: [
{
name: 'lenum',
type: {
name: 'lenum',
values: [{ key: 'enum_1', label: { en: 'enum-1' } }],
},
},
],
});
updateActions = typesSync.buildActions(now, before);
});

test('should return `removeLocalizedEnumValues` updateAction with all removed keys', () => {
expect(updateActions).toEqual([
{
action: 'removeLocalizedEnumValues',
fieldName: 'lenum',
keys: ['enum_2', 'enum_3'],
},
]);
});
});

describe('with lenum reordered', () => {
beforeEach(() => {
before = createTestType({
Expand Down
Loading