Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1import fc from 'fast-check';
2import { uid } from 'uid';
3
4import getBottle from '../../../iocContainer/index.js';
5import createActions from '../../../test/fixtureHelpers/createActions.js';
6import createContentItemTypes from '../../../test/fixtureHelpers/createContentItemTypes.js';
7import createMrtQueue from '../../../test/fixtureHelpers/createMrtQueue.js';
8import createOrg from '../../../test/fixtureHelpers/createOrg.js';
9import createUser from '../../../test/fixtureHelpers/createUser.js';
10import { makeTestWithFixture } from '../../../test/utils.js';
11import {
12 bullJobIdtoExternalJobId,
13 itemIdToBullJobId,
14 parseExternalId,
15} from './QueueOperations.js';
16
17describe('QueueOperations', () => {
18 it('External ID functions should be inverses of one another', () => {
19 fc.assert(
20 fc.property(
21 fc.string({ minLength: 1 }),
22 fc.string({ minLength: 1 }),
23 fc.string({ minLength: 1 }),
24 (itemTypeId, itemId, guid) => {
25 const bullId = itemIdToBullJobId({ typeId: itemTypeId, id: itemId });
26 const externalId = bullJobIdtoExternalJobId(bullId, guid);
27 const inverse = parseExternalId(externalId);
28 expect(inverse).toEqual({ bullId, guid });
29 },
30 ),
31 );
32 });
33
34 const testWithQueueAndActions = () =>
35 makeTestWithFixture(async () => {
36 const container = (await getBottle()).container;
37
38 const { org, cleanup: orgCleanup } = await createOrg(
39 { Org: container.Sequelize.Org },
40 container.ModerationConfigService,
41 container.ApiKeyService,
42 uid(),
43 );
44
45 const { user, cleanup: userCleanup } = await createUser(
46 container.Sequelize,
47 org.id,
48 );
49 const { itemTypes, cleanup: itemTypesCleanup } =
50 await createContentItemTypes({
51 moderationConfigService: container.ModerationConfigService,
52 orgId: org.id,
53 extra: {
54 fields: [
55 {
56 name: 'someField',
57 type: 'NUMBER',
58 required: false,
59 container: null,
60 },
61 ],
62 },
63 });
64
65 const { actions, cleanup: actionsCleanup } = await createActions({
66 actionAPI: container.ActionAPIDataSource,
67 itemTypeIds: itemTypes.map((it) => it.id),
68 orgId: org.id,
69 numActions: 3,
70 });
71
72 const { queue, cleanup: queuesCleanup } = await createMrtQueue({
73 orgId: org.id,
74 mrtService: container.ManualReviewToolService,
75 userId: user.id,
76 });
77
78 return {
79 org,
80 actions,
81 queue,
82 mrtService: container.ManualReviewToolService,
83 cleanup: async () => {
84 await queuesCleanup();
85 await actionsCleanup();
86 await itemTypesCleanup();
87 await userCleanup();
88 await orgCleanup();
89 await container.KyselyPg.destroy();
90 await container.KyselyPgReadReplica.destroy();
91 },
92 };
93 });
94
95 testWithQueueAndActions()(
96 'Queues should default to having no actions hidden',
97 async ({ org, queue, mrtService }) => {
98 const hiddenActions = await mrtService.getHiddenActionsForQueue({
99 orgId: org.id,
100 queueId: queue.id,
101 });
102 expect(hiddenActions.length).toEqual(0);
103 },
104 );
105
106 testWithQueueAndActions()(
107 'Test hiding an action',
108 async ({ org, queue, mrtService, actions }) => {
109 const actionToHide = actions[Math.floor(Math.random() * actions.length)];
110 await mrtService.updateHiddenActionsForQueue({
111 queueId: queue.id,
112 orgId: org.id,
113 actionIdsToHide: [actionToHide.id],
114 actionIdsToUnhide: [],
115 });
116
117 const hiddenActions = await mrtService.getHiddenActionsForQueue({
118 orgId: org.id,
119 queueId: queue.id,
120 });
121
122 expect(hiddenActions.length).toEqual(1);
123 expect(hiddenActions[0]).toEqual(actionToHide.id);
124 },
125 );
126
127 testWithQueueAndActions()(
128 'Test unhiding an action',
129 async ({ org, queue, mrtService, actions }) => {
130 await mrtService.updateHiddenActionsForQueue({
131 queueId: queue.id,
132 orgId: org.id,
133 actionIdsToHide: actions.map((it) => it.id),
134 actionIdsToUnhide: [],
135 });
136
137 const actionToUnhide =
138 actions[Math.floor(Math.random() * actions.length)];
139 await mrtService.updateHiddenActionsForQueue({
140 queueId: queue.id,
141 orgId: org.id,
142 actionIdsToHide: [],
143 actionIdsToUnhide: [actionToUnhide.id],
144 });
145
146 const hiddenActions = await mrtService.getHiddenActionsForQueue({
147 orgId: org.id,
148 queueId: queue.id,
149 });
150
151 expect(hiddenActions.length).toEqual(actions.length - 1);
152 expect(hiddenActions).not.toContain(actionToUnhide.id);
153 },
154 );
155
156 testWithQueueAndActions()(
157 'Test hiding some actions and unhiding some others',
158 async ({ org, queue, mrtService, actions }) => {
159 const actionsToHide = actions.slice(0, 2);
160 const actionsToToggle = actions.slice(2, 3);
161
162 // First hide the actions we're going to unhide later
163 await mrtService.updateHiddenActionsForQueue({
164 queueId: queue.id,
165 orgId: org.id,
166 actionIdsToHide: actionsToToggle.map((it) => it.id),
167 actionIdsToUnhide: [],
168 });
169 const initiallyHiddenActions = await mrtService.getHiddenActionsForQueue({
170 orgId: org.id,
171 queueId: queue.id,
172 });
173 expect(initiallyHiddenActions.length).toEqual(1);
174 expect(initiallyHiddenActions[0]).toEqual(actionsToToggle[0].id);
175
176 // Then unhide the currently hidden actions while hiding others
177 await mrtService.updateHiddenActionsForQueue({
178 queueId: queue.id,
179 orgId: org.id,
180 actionIdsToHide: actionsToHide.map((it) => it.id),
181 actionIdsToUnhide: actionsToToggle.map((it) => it.id),
182 });
183
184 const hiddenActions = await mrtService.getHiddenActionsForQueue({
185 orgId: org.id,
186 queueId: queue.id,
187 });
188
189 expect(hiddenActions.length).toEqual(2);
190 expect(
191 hiddenActions.every((it) =>
192 actionsToHide.map((it) => it.id).includes(it),
193 ),
194 ).toEqual(true);
195 expect(
196 hiddenActions.some((it) =>
197 actionsToToggle.map((it) => it.id).includes(it),
198 ),
199 ).toEqual(false);
200 },
201 );
202});