Skip to content

Commit a7fc3a4

Browse files
feat: release status in references [TOL-3103] (#1876)
* feat: release status in references * fix: path to type * refactor: rename buildEntryDraft to buildEntry * fix: set type import * refactor: wrap in useMemo * feat: parseReleaseParams util fn
1 parent 5228c3b commit a7fc3a4

16 files changed

+674
-52
lines changed

packages/_shared/src/ReleaseEntityStatusBadge/ReleaseEntityStatusBadge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22

33
import { Badge, BadgeVariant } from '@contentful/f36-components';
44

5-
import type { ReleaseAction } from './types';
5+
import type { ReleaseAction } from '../types';
66

77
type ReleaseEntityActionBadgeProps = {
88
action: ReleaseAction;

packages/_shared/src/ReleaseEntityStatusBadge/ReleaseEntityStatusLocalesList.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { MenuSectionTitle } from '@contentful/f36-components';
44
import type { LocaleProps } from 'contentful-management';
55
import { sortBy } from 'lodash';
66

7+
import { ReleaseLocalesStatus, ReleaseLocalesStatusMap } from '../types';
78
import { Banner } from './Banner';
89
import { ReleaseEntityStatusLocale } from './ReleaseEntityStatusLocale';
9-
import { ReleaseLocalesStatus, ReleaseLocalesStatusMap } from './types';
1010

1111
function groupAndSortLocales(
1212
entries: [string, ReleaseLocalesStatus][],
13-
activeLocales?: Pick<LocaleProps, 'code'>[]
13+
activeLocales?: Pick<LocaleProps, 'code'>[],
1414
) {
1515
// Group into selected locales (for editing) and non selected
1616
const { selected, nonSelected } = entries.reduce(
@@ -25,7 +25,7 @@ function groupAndSortLocales(
2525
nonSelected: [...prev.nonSelected, localeStatusType],
2626
};
2727
},
28-
{ selected: [] as ReleaseLocalesStatus[], nonSelected: [] as ReleaseLocalesStatus[] }
28+
{ selected: [] as ReleaseLocalesStatus[], nonSelected: [] as ReleaseLocalesStatus[] },
2929
);
3030

3131
return {
@@ -65,7 +65,7 @@ export function ReleaseEntityStatusLocalesList({
6565
willPublish: prev.willPublish + (status === 'willPublish' ? 1 : 0),
6666
remainsDraft: prev.remainsDraft + (status === 'remainsDraft' ? 1 : 0),
6767
}),
68-
{ willPublish: 0, becomesDraft: 0, remainsDraft: 0 }
68+
{ willPublish: 0, becomesDraft: 0, remainsDraft: 0 },
6969
);
7070

7171
const { selected, nonSelected } = groupAndSortLocales(entries, activeLocales);

packages/_shared/src/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import tokens from '@contentful/f36-tokens';
55
import type { LocaleProps } from 'contentful-management';
66
import { cx, css } from 'emotion';
77

8+
import type { ReleaseLocalesStatusMap, ReleaseEntityStatus } from '../types';
89
import { RELEASE_BADGES } from './constants';
910
import { ReleaseEntityStatusLocalesList } from './ReleaseEntityStatusLocalesList';
10-
import type { ReleaseLocalesStatusMap, ReleaseEntityStatus } from './types';
1111

1212
type BadgeSVGType = {
1313
isHover: boolean;
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export * from './ReleaseEntityStatusPopover';
22
export * from './ReleaseEntityStatusBadge';
3-
export * from './types';

packages/_shared/src/ReleaseEntityStatusBadge/types.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
import { renderHook } from '@testing-library/react';
2+
import type { CollectionProp, EntryProps, LocaleProps } from 'contentful-management';
3+
4+
import type { ReleaseV2Entity, ReleaseV2EntityWithLocales, ReleaseV2Props } from '../types';
5+
import { getPreviousReleaseEntryVersion } from '../utils/getPreviousReleaseEntryVersion';
6+
import { useActiveReleaseLocalesStatuses } from './useActiveReleaseLocalesStatuses';
7+
8+
const buildEntry = (status: 'draft' | 'published' | 'changed') =>
9+
({
10+
sys: {
11+
fieldStatus: {
12+
'*': { 'en-US': status },
13+
},
14+
},
15+
}) as unknown as EntryProps;
16+
17+
const createEntryBasedReleaseEntity = ({
18+
entryId = 'entry-1',
19+
action = 'publish',
20+
}: {
21+
entryId?: string;
22+
action?: 'publish' | 'unpublish';
23+
}) =>
24+
({
25+
entity: {
26+
sys: { type: 'Link', linkType: 'Entry', id: entryId },
27+
},
28+
action,
29+
}) as ReleaseV2Entity;
30+
31+
const createEntryBasedRelease = ({
32+
entryId,
33+
action,
34+
}: { entryId?: string; action?: 'publish' | 'unpublish' } = {}) =>
35+
({
36+
title: 'Release 1',
37+
sys: { id: 'release-1', type: 'Release', schemaVersion: 'Release.v2' },
38+
entities: { items: [createEntryBasedReleaseEntity({ entryId, action })] },
39+
}) as ReleaseV2Props;
40+
41+
const createLocaleBasedReleaseEntity = ({
42+
entryId = 'entry-1',
43+
verb = 'add',
44+
}: {
45+
entryId?: string;
46+
verb?: 'add' | 'remove';
47+
}) =>
48+
({
49+
entity: {
50+
sys: { type: 'Link', linkType: 'Entry', id: entryId },
51+
},
52+
[verb]: {
53+
fields: { '*': ['en-US'] },
54+
},
55+
}) as ReleaseV2EntityWithLocales;
56+
57+
const createLocaleBasedRelease = ({
58+
entryId,
59+
verb,
60+
}: { entryId?: string; verb?: 'add' | 'remove' } = {}) =>
61+
({
62+
title: 'Release 1',
63+
sys: { id: 'release-1', type: 'Release', schemaVersion: 'Release.v2' },
64+
entities: { items: [createLocaleBasedReleaseEntity({ entryId, verb })] },
65+
}) as ReleaseV2Props;
66+
67+
jest.mock('../utils/getPreviousReleaseEntryVersion', () => ({
68+
getPreviousReleaseEntryVersion: jest.fn(),
69+
}));
70+
71+
const baseParams = {
72+
entryId: 'entry-1',
73+
locales: [{ code: 'en-US' } as LocaleProps],
74+
isActiveReleaseLoading: false,
75+
releaseVersionMap: new Map(),
76+
releases: { items: [] } as unknown as CollectionProp<ReleaseV2Props>,
77+
};
78+
79+
describe('useActiveReleaseLocalesStatuses', () => {
80+
beforeEach(() => {
81+
jest.clearAllMocks();
82+
});
83+
84+
describe('with entry based publishing', () => {
85+
it('returns Will publish status when active release has publish action', () => {
86+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
87+
previousReleaseEntity: createEntryBasedReleaseEntity({
88+
entryId: 'entry-1',
89+
action: 'unpublish',
90+
}),
91+
previousEntryVersion: {
92+
sys: {
93+
fieldStatus: { '*': { 'en-US': 'draft' } },
94+
},
95+
},
96+
});
97+
98+
const { result } = renderHook(() =>
99+
useActiveReleaseLocalesStatuses({
100+
...baseParams,
101+
activeRelease: createEntryBasedRelease(),
102+
currentEntryDraft: buildEntry('draft'),
103+
}),
104+
);
105+
106+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
107+
variant: 'positive',
108+
status: 'willPublish',
109+
label: 'Will publish',
110+
locale: { code: 'en-US' },
111+
});
112+
});
113+
114+
it('returns Becomes draft status when previous version has published locales and active version has unpublish action', () => {
115+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
116+
previousReleaseEntity: createEntryBasedReleaseEntity({
117+
entryId: 'entry-1',
118+
action: 'publish',
119+
}),
120+
previousEntryVersion: {
121+
sys: {
122+
fieldStatus: { '*': { 'en-US': 'published' } },
123+
},
124+
},
125+
});
126+
127+
const { result } = renderHook(() =>
128+
useActiveReleaseLocalesStatuses({
129+
...baseParams,
130+
activeRelease: createEntryBasedRelease({ action: 'unpublish' }),
131+
currentEntryDraft: buildEntry('published'),
132+
}),
133+
);
134+
135+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
136+
variant: 'warning',
137+
status: 'becomesDraft',
138+
label: 'Becomes draft',
139+
locale: { code: 'en-US' },
140+
});
141+
});
142+
143+
it('returns Remains draft status when previous version has draft locales and active version has unpublish action', () => {
144+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
145+
previousReleaseEntity: createEntryBasedReleaseEntity({ action: 'unpublish' }),
146+
previousEntryVersion: {
147+
sys: {
148+
fieldStatus: { '*': { 'en-US': 'draft' } },
149+
},
150+
},
151+
});
152+
153+
const { result } = renderHook(() =>
154+
useActiveReleaseLocalesStatuses({
155+
...baseParams,
156+
activeRelease: createEntryBasedRelease({ action: 'unpublish' }),
157+
currentEntryDraft: buildEntry('draft'),
158+
}),
159+
);
160+
161+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
162+
variant: 'secondary',
163+
status: 'remainsDraft',
164+
label: 'Remains draft',
165+
locale: { code: 'en-US' },
166+
});
167+
});
168+
169+
it('returns Not in release status when entry is not in the release', () => {
170+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
171+
previousReleaseEntity: undefined,
172+
previousEntryVersion: undefined,
173+
});
174+
175+
const { result } = renderHook(() =>
176+
useActiveReleaseLocalesStatuses({
177+
...baseParams,
178+
activeRelease: createEntryBasedRelease({
179+
entryId: 'entry-2',
180+
action: 'publish',
181+
}),
182+
currentEntryDraft: buildEntry('draft'),
183+
}),
184+
);
185+
186+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
187+
variant: 'secondary',
188+
status: 'notInRelease',
189+
label: 'Not in release',
190+
locale: { code: 'en-US' },
191+
});
192+
});
193+
});
194+
195+
describe('with locale based publishing', () => {
196+
it('returns Will publish status when active release has publish action', () => {
197+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
198+
previousReleaseEntity: createLocaleBasedReleaseEntity({
199+
entryId: 'entry-1',
200+
verb: 'remove',
201+
}),
202+
previousEntryVersion: {
203+
sys: {
204+
fieldStatus: { '*': { 'en-US': 'draft' } },
205+
},
206+
},
207+
});
208+
209+
const { result } = renderHook(() =>
210+
useActiveReleaseLocalesStatuses({
211+
...baseParams,
212+
activeRelease: createLocaleBasedRelease(),
213+
currentEntryDraft: buildEntry('draft'),
214+
}),
215+
);
216+
217+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
218+
variant: 'positive',
219+
status: 'willPublish',
220+
label: 'Will publish',
221+
locale: { code: 'en-US' },
222+
});
223+
});
224+
225+
it('returns Becomes draft status when previous version has published locales and active version has unpublish action', () => {
226+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
227+
previousReleaseEntity: createLocaleBasedReleaseEntity({
228+
entryId: 'entry-1',
229+
verb: 'add',
230+
}),
231+
previousEntryVersion: {
232+
sys: {
233+
fieldStatus: { '*': { 'en-US': 'published' } },
234+
},
235+
},
236+
});
237+
238+
const { result } = renderHook(() =>
239+
useActiveReleaseLocalesStatuses({
240+
...baseParams,
241+
activeRelease: createLocaleBasedRelease({ verb: 'remove' }),
242+
currentEntryDraft: buildEntry('published'),
243+
}),
244+
);
245+
246+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
247+
variant: 'warning',
248+
status: 'becomesDraft',
249+
label: 'Becomes draft',
250+
locale: { code: 'en-US' },
251+
});
252+
});
253+
254+
it('returns Remains draft status when previous version has draft locales and active version has unpublish action', () => {
255+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
256+
previousReleaseEntity: createLocaleBasedReleaseEntity({ verb: 'remove' }),
257+
previousEntryVersion: {
258+
sys: {
259+
fieldStatus: { '*': { 'en-US': 'draft' } },
260+
},
261+
},
262+
});
263+
264+
const { result } = renderHook(() =>
265+
useActiveReleaseLocalesStatuses({
266+
...baseParams,
267+
activeRelease: createLocaleBasedRelease({ verb: 'remove' }),
268+
currentEntryDraft: buildEntry('draft'),
269+
}),
270+
);
271+
272+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
273+
variant: 'secondary',
274+
status: 'remainsDraft',
275+
label: 'Remains draft',
276+
locale: { code: 'en-US' },
277+
});
278+
});
279+
280+
it('returns Not in release status when entry is not in the release', () => {
281+
(getPreviousReleaseEntryVersion as jest.Mock).mockReturnValue({
282+
previousReleaseEntity: undefined,
283+
previousEntryVersion: undefined,
284+
});
285+
286+
const { result } = renderHook(() =>
287+
useActiveReleaseLocalesStatuses({
288+
...baseParams,
289+
activeRelease: createLocaleBasedRelease({
290+
entryId: 'entry-2',
291+
verb: 'add',
292+
}),
293+
currentEntryDraft: buildEntry('draft'),
294+
}),
295+
);
296+
297+
expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
298+
variant: 'secondary',
299+
status: 'notInRelease',
300+
label: 'Not in release',
301+
locale: { code: 'en-US' },
302+
});
303+
});
304+
});
305+
});

0 commit comments

Comments
 (0)