Skip to content

Commit

Permalink
Merge pull request #24007 from storybookjs/norbert/enhance-updateStatus
Browse files Browse the repository at this point in the history
Addon API: Improve the updateStatus API
  • Loading branch information
ndelangen authored Aug 31, 2023
2 parents 7b268e1 + c31c498 commit 115d439
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 4 deletions.
23 changes: 20 additions & 3 deletions code/lib/manager-api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,10 @@ export interface SubAPI {
* @param {StatusUpdate} update - An object containing the updated status information.
* @returns {Promise<void>} A promise that resolves when the status has been updated.
*/
experimental_updateStatus: (addonId: string, update: API_StatusUpdate) => Promise<void>;
experimental_updateStatus: (
addonId: string,
update: API_StatusUpdate | ((state: API_StatusState) => API_StatusUpdate)
) => Promise<void>;
/**
* Updates the filtering of the index.
*
Expand Down Expand Up @@ -581,13 +584,27 @@ export const init: ModuleFn<SubAPI, SubState> = ({
},

/* EXPERIMENTAL APIs */
experimental_updateStatus: async (id, update) => {
experimental_updateStatus: async (id, input) => {
const { status, internal_index: index } = store.getState();
const newStatus = { ...status };

const update = typeof input === 'function' ? input(status) : input;

if (Object.keys(update).length === 0) {
return;
}

Object.entries(update).forEach(([storyId, value]) => {
newStatus[storyId] = { ...(newStatus[storyId] || {}) };
newStatus[storyId][id] = value;
if (value === null) {
delete newStatus[storyId][id];
} else {
newStatus[storyId][id] = value;
}

if (Object.keys(newStatus[storyId]).length === 0) {
delete newStatus[storyId];
}
});

await store.setState({ status: newStatus }, { persistence: 'session' });
Expand Down
84 changes: 84 additions & 0 deletions code/lib/manager-api/src/tests/stories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,90 @@ describe('stories API', () => {
}
`);
});
it('delete when value is null', async () => {
const moduleArgs = createMockModuleArgs({});
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
const { store } = moduleArgs;

await api.setIndex({ v: 4, entries: mockEntries });

await expect(
api.experimental_updateStatus('a-addon-id', {
'a-story-id': {
status: 'pending',
title: 'an addon title',
description: 'an addon description',
},
'another-story-id': { status: 'success', title: 'a addon title', description: '' },
})
).resolves.not.toThrow();

// do a second update, this time with null
await expect(
api.experimental_updateStatus('a-addon-id', {
'a-story-id': null,
'another-story-id': { status: 'success', title: 'a addon title', description: '' },
})
).resolves.not.toThrow();

expect(store.getState().status).toMatchInlineSnapshot(`
Object {
"another-story-id": Object {
"a-addon-id": Object {
"description": "",
"status": "success",
"title": "a addon title",
},
},
}
`);
});
it('updates with a function', async () => {
const moduleArgs = createMockModuleArgs({});
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
const { store } = moduleArgs;

await api.setIndex({ v: 4, entries: mockEntries });

// setup initial state
await expect(
api.experimental_updateStatus('a-addon-id', () => ({
'a-story-id': {
status: 'pending',
title: 'an addon title',
description: 'an addon description',
},
'another-story-id': { status: 'success', title: 'a addon title', description: '' },
}))
).resolves.not.toThrow();

// use existing state in function
await expect(
api.experimental_updateStatus('a-addon-id', (current) => {
return Object.fromEntries(
Object.entries(current).map(([k, v]) => [k, { ...v['a-addon-id'], status: 'success' }])
);
})
).resolves.not.toThrow();
expect(store.getState().status).toMatchInlineSnapshot(`
Object {
"a-story-id": Object {
"a-addon-id": Object {
"description": "an addon description",
"status": "success",
"title": "an addon title",
},
},
"another-story-id": Object {
"a-addon-id": Object {
"description": "",
"status": "success",
"title": "a addon title",
},
},
}
`);
});
});
describe('experimental_setFilter', () => {
it('is included in the initial state', async () => {
Expand Down
2 changes: 1 addition & 1 deletion code/lib/types/src/modules/api-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,5 @@ export type API_StatusState = Record<StoryId, Record<string, API_StatusObject>>;
export type API_StatusUpdate = Record<StoryId, API_StatusObject>;

export type API_FilterFunction = (
item: API_PreparedIndexEntry & { status: Record<string, API_StatusObject> }
item: API_PreparedIndexEntry & { status: Record<string, API_StatusObject | null> }
) => boolean;

0 comments on commit 115d439

Please sign in to comment.