@webitel/api-services 0.1.69 → 0.1.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/package.json +3 -1
  2. package/src/api/clients/_shared/types.ts +25 -0
  3. package/src/api/clients/index.ts +8 -0
  4. package/src/api/clients/queues/__tests__/fieldsToSend.spec.ts +135 -0
  5. package/src/api/clients/queues/__tests__/queueLogs.spec.ts +132 -0
  6. package/src/api/clients/queues/__tests__/queueMembers.spec.ts +175 -0
  7. package/src/api/clients/queues/__tests__/queues.spec.ts +130 -0
  8. package/src/api/clients/queues/defaults/__tests__/queueTypeDefaults.spec.ts +143 -0
  9. package/src/api/clients/queues/defaults/amd.ts +17 -0
  10. package/src/api/clients/queues/defaults/defaultQueue.ts +9 -0
  11. package/src/api/clients/queues/defaults/processing.ts +8 -4
  12. package/src/api/clients/queues/defaults/queueTypeDefaults.ts +305 -0
  13. package/src/api/clients/queues/queueAgents.ts +48 -0
  14. package/src/api/clients/queues/queueBuckets.ts +187 -0
  15. package/src/api/clients/queues/queueHooks.ts +184 -0
  16. package/src/api/clients/queues/queueLogs.ts +80 -0
  17. package/src/api/clients/queues/queueMembers.ts +426 -0
  18. package/src/api/clients/queues/queueResGroups.ts +176 -0
  19. package/src/api/clients/queues/queueSkills.ts +183 -0
  20. package/src/api/clients/queues/queueState.ts +97 -0
  21. package/src/api/clients/queues/queues.ts +124 -94
  22. package/src/api/clients/queues/scripts/__tests__/mapResetMembersFilters.spec.ts +132 -0
  23. package/src/api/clients/queues/scripts/mapResetMembersFilters.ts +52 -0
  24. package/src/enums/CallReportingStatus/CallReportingStatus.ts +13 -0
  25. package/src/enums/MemberStopCause/MemberStopCause.ts +13 -0
  26. package/src/enums/QueueStrategy/QueueStrategy.ts +27 -0
  27. package/src/enums/QueueType/QueueType.ts +31 -0
  28. package/src/enums/TimeBaseScore/TimeBaseScore.ts +6 -0
  29. package/src/enums/TypesResourceStrategy/TypesResourceStrategy.ts +7 -0
  30. package/src/enums/index.ts +21 -1
  31. package/src/scripts/index.ts +19 -1
  32. package/src/scripts/normalizeDatetime/normalizeDatetime.ts +132 -0
  33. package/src/validations/_shared/isFilled.ts +15 -0
  34. package/src/validations/_shared/lookup.validations.ts +28 -0
  35. package/src/validations/_shared/variablePair.validations.ts +18 -0
  36. package/src/validations/index.ts +12 -0
  37. package/src/validations/queue/__tests__/queue.validations.spec.ts +159 -0
  38. package/src/validations/queue/queue.rules.ts +166 -0
  39. package/src/validations/queue/queue.validations.ts +105 -0
  40. package/src/validations/queue/queueAmd.validations.ts +22 -0
  41. package/src/validations/queue/queuePayload.validations.ts +71 -0
  42. package/src/validations/queue/taskProcessing.validations.ts +21 -0
  43. package/src/validations/queueBucket/queueBucket.validations.ts +10 -0
  44. package/src/validations/queueHook/queueHook.validations.ts +10 -0
  45. package/src/validations/queueMember/memberCommunication.validations.ts +25 -0
  46. package/src/validations/queueMember/queueMember.validations.ts +38 -0
  47. package/src/validations/queueResGroup/queueResGroup.validations.ts +15 -0
  48. package/src/validations/queueSkill/queueSkill.validations.ts +42 -0
  49. package/types/.tsbuildinfo +1 -1
  50. package/types/api/clients/_shared/types.d.ts +20 -0
  51. package/types/api/clients/index.d.ts +8 -0
  52. package/types/api/clients/queues/defaults/amd.d.ts +17 -0
  53. package/types/api/clients/queues/defaults/defaultQueue.d.ts +9 -0
  54. package/types/api/clients/queues/defaults/processing.d.ts +7 -2
  55. package/types/api/clients/queues/defaults/queueTypeDefaults.d.ts +31 -0
  56. package/types/api/clients/queues/queueAgents.d.ts +7 -0
  57. package/types/api/clients/queues/queueBuckets.d.ts +12 -0
  58. package/types/api/clients/queues/queueHooks.d.ts +12 -0
  59. package/types/api/clients/queues/queueLogs.d.ts +7 -0
  60. package/types/api/clients/queues/queueMembers.d.ts +30 -0
  61. package/types/api/clients/queues/queueResGroups.d.ts +15 -0
  62. package/types/api/clients/queues/queueSkills.d.ts +12 -0
  63. package/types/api/clients/queues/queueState.d.ts +8 -0
  64. package/types/api/clients/queues/queues.d.ts +9 -1
  65. package/types/api/clients/queues/scripts/mapResetMembersFilters.d.ts +30 -0
  66. package/types/enums/CallReportingStatus/CallReportingStatus.d.ts +11 -0
  67. package/types/enums/MemberStopCause/MemberStopCause.d.ts +11 -0
  68. package/types/enums/QueueStrategy/QueueStrategy.d.ts +21 -0
  69. package/types/enums/QueueType/QueueType.d.ts +28 -0
  70. package/types/enums/TimeBaseScore/TimeBaseScore.d.ts +5 -0
  71. package/types/enums/TypesResourceStrategy/TypesResourceStrategy.d.ts +5 -0
  72. package/types/enums/index.d.ts +7 -1
  73. package/types/scripts/index.d.ts +3 -1
  74. package/types/scripts/normalizeDatetime/normalizeDatetime.d.ts +14 -0
  75. package/types/validations/_shared/isFilled.d.ts +9 -0
  76. package/types/validations/_shared/lookup.validations.d.ts +18 -0
  77. package/types/validations/_shared/variablePair.validations.d.ts +16 -0
  78. package/types/validations/index.d.ts +12 -0
  79. package/types/validations/queue/queue.rules.d.ts +21 -0
  80. package/types/validations/queue/queue.validations.d.ts +285 -0
  81. package/types/validations/queue/queueAmd.validations.d.ts +22 -0
  82. package/types/validations/queue/queuePayload.validations.d.ts +75 -0
  83. package/types/validations/queue/taskProcessing.validations.d.ts +22 -0
  84. package/types/validations/queueBucket/queueBucket.validations.d.ts +9 -0
  85. package/types/validations/queueHook/queueHook.validations.d.ts +10 -0
  86. package/types/validations/queueMember/memberCommunication.validations.d.ts +16 -0
  87. package/types/validations/queueMember/queueMember.validations.d.ts +48 -0
  88. package/types/validations/queueResGroup/queueResGroup.validations.d.ts +11 -0
  89. package/types/validations/queueSkill/queueSkill.validations.d.ts +34 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webitel/api-services",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,6 +39,7 @@
39
39
  "CHANGELOG.md"
40
40
  ],
41
41
  "peerDependencies": {
42
+ "date-fns": "^4.1.0",
42
43
  "deep-copy": "^1.4.2",
43
44
  "deep-equal": "^2.2.3",
44
45
  "deepmerge": "^4.3.1",
@@ -51,6 +52,7 @@
51
52
  "@types/node": "^22.13.10",
52
53
  "axios": "^1.15.2",
53
54
  "change-case": "^5.4.4",
55
+ "date-fns": "^4.1.0",
54
56
  "globby": "^14.1.0",
55
57
  "husky": "^9.1.7",
56
58
  "is-json": "^2.0.1",
@@ -32,3 +32,28 @@ export interface PatchItemParams {
32
32
  export interface DeleteItemParams {
33
33
  id: ApiId;
34
34
  }
35
+
36
+ /**
37
+ * Params for entities that only exist under a parent — queue hooks, skills,
38
+ * buckets, resource groups, members. ui-datalist threads `parentId` through
39
+ * every call a nested table or its card popup makes.
40
+ */
41
+ export interface NestedGetItemParams extends GetItemParams {
42
+ parentId: ApiId;
43
+ }
44
+
45
+ export interface NestedAddItemParams extends AddItemParams {
46
+ parentId: ApiId;
47
+ }
48
+
49
+ export interface NestedUpdateItemParams extends UpdateItemParams {
50
+ parentId: ApiId;
51
+ }
52
+
53
+ export interface NestedPatchItemParams extends PatchItemParams {
54
+ parentId: ApiId;
55
+ }
56
+
57
+ export interface NestedDeleteItemParams extends DeleteItemParams {
58
+ parentId: ApiId;
59
+ }
@@ -37,6 +37,14 @@ export * from './object/object';
37
37
  export * from './onlineSkills/onlineSkills';
38
38
  export * from './pdfServices/pdfServices';
39
39
  export * from './phones/phones';
40
+ export * from './queues/queueAgents';
41
+ export * from './queues/queueBuckets';
42
+ export * from './queues/queueHooks';
43
+ export * from './queues/queueLogs';
44
+ export * from './queues/queueMembers';
45
+ export * from './queues/queueResGroups';
46
+ export * from './queues/queueSkills';
47
+ export * from './queues/queueState';
40
48
  export * from './queues/queues';
41
49
  export * from './quickReplies/quickReplies';
42
50
  export * from './regions/regions';
@@ -0,0 +1,135 @@
1
+ import { getShallowFieldsToSendFromZodSchema } from '@webitel/api-services/gen/utils';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ import {
5
+ queueBucketSchema,
6
+ queueHookSchema,
7
+ queueMemberSchema,
8
+ queueResGroupSchema,
9
+ queueSchema,
10
+ queueSkillSchema,
11
+ } from '../../../../validations';
12
+
13
+ /**
14
+ * The queue api modules derive their `sanitize()` whitelists from these
15
+ * schemas, so the form and the request cannot drift apart. That only holds
16
+ * while `getShallowFieldsToSendFromZodSchema` can still read the keys — and
17
+ * `queueSchema` and `queueSkillSchema` are `superRefine`-wrapped, which would
18
+ * hide them if zod ever moved refinements back outside the object.
19
+ */
20
+ const fieldsOf = (
21
+ schema: Parameters<typeof getShallowFieldsToSendFromZodSchema>[0],
22
+ ) =>
23
+ [
24
+ ...getShallowFieldsToSendFromZodSchema(schema),
25
+ ].sort();
26
+
27
+ describe('fields derived from the queue schemas', () => {
28
+ it('sends every editable queue field', () => {
29
+ expect(fieldsOf(queueSchema)).toEqual([
30
+ 'afterSchema',
31
+ 'calendar',
32
+ 'description',
33
+ 'dncList',
34
+ 'doSchema',
35
+ 'enabled',
36
+ 'formSchema',
37
+ 'grantee',
38
+ 'name',
39
+ 'payload',
40
+ 'priority',
41
+ 'ringtone',
42
+ 'schema',
43
+ 'stickyAgent',
44
+ 'strategy',
45
+ 'tags',
46
+ 'taskProcessing',
47
+ 'team',
48
+ 'type',
49
+ 'variables',
50
+ ]);
51
+ });
52
+
53
+ it('reads through the queue superRefine', () => {
54
+ // the rules wrapper must not hide the shape from the whitelist
55
+ expect(fieldsOf(queueSchema)).toContain('payload');
56
+ expect(fieldsOf(queueSkillSchema)).toContain('skill');
57
+ });
58
+
59
+ it.each([
60
+ [
61
+ 'hook',
62
+ queueHookSchema,
63
+ [
64
+ 'enabled',
65
+ 'event',
66
+ 'properties',
67
+ 'schema',
68
+ ],
69
+ ],
70
+ [
71
+ 'bucket',
72
+ queueBucketSchema,
73
+ [
74
+ 'bucket',
75
+ 'disabled',
76
+ 'priority',
77
+ ],
78
+ ],
79
+ [
80
+ 'resource group',
81
+ queueResGroupSchema,
82
+ [
83
+ 'communication',
84
+ 'resourceGroup',
85
+ ],
86
+ ],
87
+ [
88
+ 'skill',
89
+ queueSkillSchema,
90
+ [
91
+ 'buckets',
92
+ 'enabled',
93
+ 'lvl',
94
+ 'maxCapacity',
95
+ 'minCapacity',
96
+ 'skill',
97
+ ],
98
+ ],
99
+ [
100
+ 'member',
101
+ queueMemberSchema,
102
+ [
103
+ 'agent',
104
+ 'bucket',
105
+ 'communications',
106
+ 'expireAt',
107
+ 'minOfferingAt',
108
+ 'name',
109
+ 'priority',
110
+ 'stopCause',
111
+ 'timezone',
112
+ 'variables',
113
+ ],
114
+ ],
115
+ ])('sends every editable %s field', (_entity, schema, expected) => {
116
+ expect(fieldsOf(schema)).toEqual(expected);
117
+ });
118
+
119
+ /**
120
+ * `queueId` is put on nested bodies by each module's `preRequestHandler`; it
121
+ * belongs to the url, not the form, so it is appended to the derived list
122
+ * rather than added to the schema.
123
+ */
124
+ it('leaves queueId out of the nested schemas', () => {
125
+ for (const schema of [
126
+ queueHookSchema,
127
+ queueBucketSchema,
128
+ queueResGroupSchema,
129
+ queueSkillSchema,
130
+ queueMemberSchema,
131
+ ]) {
132
+ expect(fieldsOf(schema)).not.toContain('queueId');
133
+ }
134
+ });
135
+ });
@@ -0,0 +1,132 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const searchAttemptsHistory = vi.fn();
4
+
5
+ vi.mock('@webitel/api-services/gen', () => ({
6
+ getMemberService: () => ({
7
+ searchAttemptsHistory,
8
+ }),
9
+ }));
10
+
11
+ const { QueueLogsAPI } = await import('../queueLogs');
12
+
13
+ const paramsSent = () => searchAttemptsHistory.mock.calls[0][0];
14
+
15
+ describe('QueueLogsAPI.getList', () => {
16
+ beforeEach(() => {
17
+ searchAttemptsHistory.mockReset().mockResolvedValue({
18
+ data: {
19
+ items: [],
20
+ next: false,
21
+ },
22
+ });
23
+ });
24
+
25
+ /**
26
+ * The range filters are protobuf nested messages, so they only bind as
27
+ * `joined_at.from`. The generated params type calls them `joinedAtFrom`,
28
+ * which the backend would ignore — the request would succeed and quietly
29
+ * return unfiltered rows. That is how the duration filter was broken before
30
+ * this migration, so it is worth pinning.
31
+ *
32
+ * Verified live: `joined_at`, `leaving_at` and `offering_at` all filter with
33
+ * this shape. `duration` does not — the backend accepts and ignores it (see
34
+ * the note in `queueLogs.ts`), so this pins the wire format only, not that
35
+ * the duration filter actually works.
36
+ */
37
+ it('sends range bounds as dotted keys', async () => {
38
+ await QueueLogsAPI.getList({
39
+ parentId: '7',
40
+ joinedAt: {
41
+ from: 100,
42
+ to: 200,
43
+ },
44
+ duration: {
45
+ from: 5,
46
+ to: 30,
47
+ },
48
+ });
49
+
50
+ expect(paramsSent()).toMatchObject({
51
+ 'joined_at.from': 100,
52
+ 'joined_at.to': 200,
53
+ 'duration.from': 5,
54
+ 'duration.to': 30,
55
+ });
56
+ });
57
+
58
+ it('does not send the flattened names the generated type declares', async () => {
59
+ await QueueLogsAPI.getList({
60
+ parentId: '7',
61
+ joinedAt: {
62
+ from: 100,
63
+ to: 200,
64
+ },
65
+ });
66
+
67
+ expect(paramsSent()).not.toHaveProperty('joinedAtFrom');
68
+ expect(paramsSent()).not.toHaveProperty('joinedAtTo');
69
+ });
70
+
71
+ it('maps the filter names onto the service params', async () => {
72
+ await QueueLogsAPI.getList({
73
+ parentId: '7',
74
+ bucket: [
75
+ 1,
76
+ ],
77
+ agent: [
78
+ 2,
79
+ ],
80
+ leavingAt: {
81
+ from: 10,
82
+ to: 20,
83
+ },
84
+ offeringAt: {
85
+ from: 30,
86
+ to: 40,
87
+ },
88
+ });
89
+
90
+ expect(paramsSent()).toMatchObject({
91
+ bucketId: [
92
+ 1,
93
+ ],
94
+ agentId: [
95
+ 2,
96
+ ],
97
+ 'leaving_at.from': 10,
98
+ 'leaving_at.to': 20,
99
+ 'offering_at.from': 30,
100
+ 'offering_at.to': 40,
101
+ });
102
+ });
103
+
104
+ it('scopes the query to its queue and maps search onto q', async () => {
105
+ await QueueLogsAPI.getList({
106
+ parentId: '7',
107
+ search: 'joe',
108
+ });
109
+
110
+ // `starToSearch` makes it a prefix search, as everywhere else
111
+ expect(paramsSent()).toMatchObject({
112
+ queueId: [
113
+ '7',
114
+ ],
115
+ q: 'joe*',
116
+ });
117
+ });
118
+
119
+ it('sorts by join time unless told otherwise', async () => {
120
+ await QueueLogsAPI.getList({
121
+ parentId: '7',
122
+ });
123
+ expect(paramsSent().sort).toBe('+joined_at');
124
+
125
+ searchAttemptsHistory.mockClear();
126
+ await QueueLogsAPI.getList({
127
+ parentId: '7',
128
+ sort: '-duration',
129
+ });
130
+ expect(paramsSent().sort).toBe('-duration');
131
+ });
132
+ });
@@ -0,0 +1,175 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const searchMemberInQueue = vi.fn();
4
+ const resetMembersCount = vi.fn();
5
+ const resetMembers = vi.fn();
6
+
7
+ vi.mock('@webitel/api-services/gen', () => ({
8
+ getMemberService: () => ({
9
+ searchMemberInQueue,
10
+ resetMembersCount,
11
+ resetMembers,
12
+ }),
13
+ }));
14
+
15
+ const { QueueMembersAPI } = await import('../queueMembers');
16
+
17
+ describe('QueueMembersAPI.getList', () => {
18
+ beforeEach(() => {
19
+ searchMemberInQueue.mockReset().mockResolvedValue({
20
+ data: {
21
+ items: [],
22
+ next: false,
23
+ },
24
+ });
25
+ });
26
+
27
+ const paramsSent = () => searchMemberInQueue.mock.calls[0][1];
28
+
29
+ /**
30
+ * `created_at` and `priority` are protobuf nested messages, so they only
31
+ * bind as dotted keys. The generated params type calls them `createdAtFrom`
32
+ * and `priorityFrom`, which the backend ignores — the request succeeds and
33
+ * returns unfiltered rows.
34
+ */
35
+ it('sends range bounds as dotted keys', async () => {
36
+ await QueueMembersAPI.getList({
37
+ parentId: '7',
38
+ createdAt: {
39
+ from: 100,
40
+ to: 200,
41
+ },
42
+ memberPriority: {
43
+ from: 1,
44
+ to: 9,
45
+ },
46
+ });
47
+
48
+ expect(paramsSent()).toMatchObject({
49
+ 'created_at.from': 100,
50
+ 'created_at.to': 200,
51
+ 'priority.from': 1,
52
+ 'priority.to': 9,
53
+ });
54
+ expect(paramsSent()).not.toHaveProperty('createdAtFrom');
55
+ expect(paramsSent()).not.toHaveProperty('priorityFrom');
56
+ });
57
+
58
+ it('passes the queue id positionally, as a number', async () => {
59
+ await QueueMembersAPI.getList({
60
+ parentId: '7',
61
+ });
62
+
63
+ expect(searchMemberInQueue.mock.calls[0][0]).toBe(7);
64
+ });
65
+
66
+ /** the datalist names differ from the service's, so the mapping is explicit */
67
+ it('maps the filter names onto the service params', async () => {
68
+ await QueueMembersAPI.getList({
69
+ parentId: '7',
70
+ search: 'joe',
71
+ bucket: [
72
+ 1,
73
+ ],
74
+ agent: [
75
+ 2,
76
+ ],
77
+ stopCause: [
78
+ 'cancel',
79
+ ],
80
+ offeringAt: {
81
+ from: 300,
82
+ to: 400,
83
+ },
84
+ attempts: {
85
+ from: 2,
86
+ to: 5,
87
+ },
88
+ name: 'alice',
89
+ destination: '380',
90
+ });
91
+
92
+ expect(paramsSent()).toMatchObject({
93
+ q: 'joe*',
94
+ bucketId: [
95
+ 1,
96
+ ],
97
+ agentId: [
98
+ 2,
99
+ ],
100
+ stopCause: [
101
+ 'cancel',
102
+ ],
103
+ 'offering_at.from': 300,
104
+ 'offering_at.to': 400,
105
+ 'attempts.from': 2,
106
+ 'attempts.to': 5,
107
+ name: 'alice',
108
+ destination: '380',
109
+ });
110
+ });
111
+
112
+ /** the pre-migration spellings still work, so both can coexist */
113
+ it('still accepts the legacy filter names', async () => {
114
+ await QueueMembersAPI.getList({
115
+ parentId: '7',
116
+ from: 100,
117
+ to: 200,
118
+ cause: [
119
+ 'cancel',
120
+ ],
121
+ });
122
+
123
+ expect(paramsSent()).toMatchObject({
124
+ 'created_at.from': 100,
125
+ 'created_at.to': 200,
126
+ stopCause: [
127
+ 'cancel',
128
+ ],
129
+ });
130
+ });
131
+ });
132
+
133
+ describe('QueueMembersAPI.getQuantity', () => {
134
+ beforeEach(() => {
135
+ resetMembersCount.mockReset().mockResolvedValue({
136
+ data: {
137
+ count: 12,
138
+ },
139
+ });
140
+ });
141
+
142
+ /** was a hand-built url; the generated call must keep the dotted keys */
143
+ it('counts through the service with dotted range keys', async () => {
144
+ const count = await QueueMembersAPI.getQuantity({
145
+ parentId: '7',
146
+ filters: {
147
+ createdAt: {
148
+ from: 100,
149
+ to: 200,
150
+ },
151
+ },
152
+ });
153
+
154
+ expect(count).toBe(12);
155
+ expect(resetMembersCount).toHaveBeenCalledWith(
156
+ '7',
157
+ expect.objectContaining({
158
+ 'created_at.from': 100,
159
+ 'created_at.to': 200,
160
+ }),
161
+ );
162
+ });
163
+
164
+ it('reports zero when the service returns no count', async () => {
165
+ resetMembersCount.mockResolvedValue({
166
+ data: {},
167
+ });
168
+
169
+ await expect(
170
+ QueueMembersAPI.getQuantity({
171
+ parentId: '7',
172
+ }),
173
+ ).resolves.toBe(0);
174
+ });
175
+ });
@@ -0,0 +1,130 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ import { QueueType } from '../../../../enums';
4
+
5
+ const readQueue = vi.fn();
6
+ const searchQueue = vi.fn();
7
+
8
+ vi.mock('@webitel/api-services/gen', () => ({
9
+ getQueueService: () => ({
10
+ readQueue,
11
+ searchQueue,
12
+ }),
13
+ }));
14
+
15
+ const { QueuesAPI } = await import('../queues');
16
+
17
+ /**
18
+ * proto3 omits zero values, so an OFFLINE_QUEUE (type `0`) arrives with no
19
+ * `type` key at all. Legacy restored it with a `defaultObject`; these tests
20
+ * pin that the restore survived the migration.
21
+ *
22
+ * The failure mode is silent and severe: without `type`, `getQueueDefaults`
23
+ * falls back to the type-agnostic base, the Params tab renders none of the
24
+ * offline-specific controls, and `queueSchema`'s `superRefine` skips the
25
+ * per-type branch — the form just quietly loses half its behaviour.
26
+ */
27
+ describe('QueuesAPI.get, on a type-less (offline) response', () => {
28
+ beforeEach(() => {
29
+ readQueue.mockReset();
30
+ });
31
+
32
+ it('restores type 0 and seeds the offline defaults', async () => {
33
+ readQueue.mockResolvedValue({
34
+ data: {
35
+ id: 239,
36
+ name: 'offline',
37
+ payload: {},
38
+ },
39
+ });
40
+
41
+ const item = await QueuesAPI.get({
42
+ itemId: 239,
43
+ });
44
+
45
+ expect(item.type).toBe(QueueType.OFFLINE_QUEUE);
46
+ // seeded from offlineQueue(), not from the base defaults
47
+ expect(item.payload).toMatchObject({
48
+ maxAttempts: 3,
49
+ originateTimeout: 60,
50
+ minOnlineAgents: 0,
51
+ });
52
+ expect(item.taskProcessing).toBeDefined();
53
+ });
54
+
55
+ it('never overwrites a type the backend did send', async () => {
56
+ readQueue.mockResolvedValue({
57
+ data: {
58
+ id: 15,
59
+ type: QueueType.CHAT_INBOUND_QUEUE,
60
+ payload: {},
61
+ },
62
+ });
63
+
64
+ const item = await QueuesAPI.get({
65
+ itemId: 15,
66
+ });
67
+
68
+ expect(item.type).toBe(QueueType.CHAT_INBOUND_QUEUE);
69
+ });
70
+ });
71
+
72
+ describe('QueuesAPI.getList, on type-less rows', () => {
73
+ beforeEach(() => {
74
+ searchQueue.mockReset();
75
+ });
76
+
77
+ /**
78
+ * The table renders `type`, `active` and `waiting` straight into cells, so
79
+ * an omitted zero shows up as a blank column rather than "Offline queue"/0.
80
+ */
81
+ it('restores the zero values the table renders', async () => {
82
+ searchQueue.mockResolvedValue({
83
+ data: {
84
+ items: [
85
+ {
86
+ id: 239,
87
+ name: 'offline',
88
+ },
89
+ ],
90
+ next: false,
91
+ },
92
+ });
93
+
94
+ const { items } = await QueuesAPI.getList({});
95
+
96
+ expect(items[0]).toMatchObject({
97
+ type: QueueType.OFFLINE_QUEUE,
98
+ enabled: false,
99
+ active: 0,
100
+ waiting: 0,
101
+ });
102
+ });
103
+
104
+ it('leaves non-zero values alone', async () => {
105
+ searchQueue.mockResolvedValue({
106
+ data: {
107
+ items: [
108
+ {
109
+ id: 15,
110
+ type: QueueType.CHAT_INBOUND_QUEUE,
111
+ enabled: true,
112
+ active: 4,
113
+ priority: 1000,
114
+ },
115
+ ],
116
+ next: false,
117
+ },
118
+ });
119
+
120
+ const { items } = await QueuesAPI.getList({});
121
+
122
+ expect(items[0]).toMatchObject({
123
+ type: QueueType.CHAT_INBOUND_QUEUE,
124
+ enabled: true,
125
+ active: 4,
126
+ priority: 1000,
127
+ waiting: 0,
128
+ });
129
+ });
130
+ });