@qoretechnologies/reqraft 0.10.13-pr.74.gccefa54 → 0.10.13
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.
- package/.claude/CLAUDE.md +8 -11
- package/dist/components/form/engine/FormEngine.d.ts +1 -1
- package/dist/helpers/common.d.ts +0 -5
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +1 -20
- package/dist/helpers/common.js.map +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -7
- package/dist/index.js.map +1 -1
- package/dist/providers/StorageProvider.d.ts +13 -0
- package/dist/providers/StorageProvider.d.ts.map +1 -1
- package/dist/providers/StorageProvider.js +29 -5
- package/dist/providers/StorageProvider.js.map +1 -1
- package/package.json +3 -3
- package/src/helpers/common.ts +0 -19
- package/src/hooks/useStorage/useStorage.stories.tsx +52 -0
- package/src/index.tsx +0 -5
- package/src/providers/StorageProvider.tsx +30 -4
- package/dist/components/composer/Composer.d.ts +0 -108
- package/dist/components/composer/Composer.d.ts.map +0 -1
- package/dist/components/composer/Composer.js +0 -238
- package/dist/components/composer/Composer.js.map +0 -1
- package/dist/components/composer/helpers.d.ts +0 -21
- package/dist/components/composer/helpers.d.ts.map +0 -1
- package/dist/components/composer/helpers.js +0 -75
- package/dist/components/composer/helpers.js.map +0 -1
- package/dist/components/composer/index.d.ts +0 -3
- package/dist/components/composer/index.d.ts.map +0 -1
- package/dist/components/composer/index.js +0 -19
- package/dist/components/composer/index.js.map +0 -1
- package/dist/components/imageLightbox/ImageLightbox.d.ts +0 -17
- package/dist/components/imageLightbox/ImageLightbox.d.ts.map +0 -1
- package/dist/components/imageLightbox/ImageLightbox.js +0 -129
- package/dist/components/imageLightbox/ImageLightbox.js.map +0 -1
- package/dist/components/imageLightbox/index.d.ts +0 -2
- package/dist/components/imageLightbox/index.d.ts.map +0 -1
- package/dist/components/imageLightbox/index.js +0 -18
- package/dist/components/imageLightbox/index.js.map +0 -1
- package/dist/components/supportTicket/AttachmentChips.d.ts +0 -10
- package/dist/components/supportTicket/AttachmentChips.d.ts.map +0 -1
- package/dist/components/supportTicket/AttachmentChips.js +0 -119
- package/dist/components/supportTicket/AttachmentChips.js.map +0 -1
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts +0 -35
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts.map +0 -1
- package/dist/components/supportTicket/InterfaceReferenceTags.js +0 -31
- package/dist/components/supportTicket/InterfaceReferenceTags.js.map +0 -1
- package/dist/components/supportTicket/ReferencePicker.d.ts +0 -41
- package/dist/components/supportTicket/ReferencePicker.d.ts.map +0 -1
- package/dist/components/supportTicket/ReferencePicker.js +0 -86
- package/dist/components/supportTicket/ReferencePicker.js.map +0 -1
- package/dist/components/supportTicket/TicketHeader.d.ts +0 -86
- package/dist/components/supportTicket/TicketHeader.d.ts.map +0 -1
- package/dist/components/supportTicket/TicketHeader.js +0 -149
- package/dist/components/supportTicket/TicketHeader.js.map +0 -1
- package/dist/components/supportTicket/TicketMetaTags.d.ts +0 -32
- package/dist/components/supportTicket/TicketMetaTags.d.ts.map +0 -1
- package/dist/components/supportTicket/TicketMetaTags.js +0 -21
- package/dist/components/supportTicket/TicketMetaTags.js.map +0 -1
- package/dist/components/supportTicket/TicketReplyBox.d.ts +0 -63
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +0 -1
- package/dist/components/supportTicket/TicketReplyBox.js +0 -115
- package/dist/components/supportTicket/TicketReplyBox.js.map +0 -1
- package/dist/components/supportTicket/fileToAttachment.d.ts +0 -9
- package/dist/components/supportTicket/fileToAttachment.d.ts.map +0 -1
- package/dist/components/supportTicket/fileToAttachment.js +0 -28
- package/dist/components/supportTicket/fileToAttachment.js.map +0 -1
- package/dist/components/supportTicket/index.d.ts +0 -9
- package/dist/components/supportTicket/index.d.ts.map +0 -1
- package/dist/components/supportTicket/index.js +0 -25
- package/dist/components/supportTicket/index.js.map +0 -1
- package/dist/components/supportTicket/meta.d.ts +0 -63
- package/dist/components/supportTicket/meta.d.ts.map +0 -1
- package/dist/components/supportTicket/meta.js +0 -79
- package/dist/components/supportTicket/meta.js.map +0 -1
- package/dist/components/ticketReferences/TicketReferences.d.ts +0 -52
- package/dist/components/ticketReferences/TicketReferences.d.ts.map +0 -1
- package/dist/components/ticketReferences/TicketReferences.js +0 -453
- package/dist/components/ticketReferences/TicketReferences.js.map +0 -1
- package/dist/components/ticketReferences/index.d.ts +0 -3
- package/dist/components/ticketReferences/index.d.ts.map +0 -1
- package/dist/components/ticketReferences/index.js +0 -6
- package/dist/components/ticketReferences/index.js.map +0 -1
- package/dist/components/ticketThread/TicketThread.d.ts +0 -52
- package/dist/components/ticketThread/TicketThread.d.ts.map +0 -1
- package/dist/components/ticketThread/TicketThread.js +0 -248
- package/dist/components/ticketThread/TicketThread.js.map +0 -1
- package/dist/components/ticketThread/index.d.ts +0 -3
- package/dist/components/ticketThread/index.d.ts.map +0 -1
- package/dist/components/ticketThread/index.js +0 -7
- package/dist/components/ticketThread/index.js.map +0 -1
- package/dist/helpers/scrollbar.d.ts +0 -2
- package/dist/helpers/scrollbar.d.ts.map +0 -1
- package/dist/helpers/scrollbar.js +0 -25
- package/dist/helpers/scrollbar.js.map +0 -1
- package/src/components/composer/Composer.stories.tsx +0 -238
- package/src/components/composer/Composer.tsx +0 -545
- package/src/components/composer/helpers.ts +0 -74
- package/src/components/composer/index.ts +0 -2
- package/src/components/imageLightbox/ImageLightbox.stories.tsx +0 -156
- package/src/components/imageLightbox/ImageLightbox.tsx +0 -169
- package/src/components/imageLightbox/index.ts +0 -1
- package/src/components/supportTicket/AttachmentChips.stories.tsx +0 -122
- package/src/components/supportTicket/AttachmentChips.tsx +0 -142
- package/src/components/supportTicket/InterfaceReferenceTags.stories.tsx +0 -134
- package/src/components/supportTicket/InterfaceReferenceTags.tsx +0 -85
- package/src/components/supportTicket/ReferencePicker.stories.tsx +0 -296
- package/src/components/supportTicket/ReferencePicker.tsx +0 -237
- package/src/components/supportTicket/TicketConversation.stories.tsx +0 -122
- package/src/components/supportTicket/TicketHeader.stories.tsx +0 -183
- package/src/components/supportTicket/TicketHeader.tsx +0 -247
- package/src/components/supportTicket/TicketMetaTags.stories.tsx +0 -103
- package/src/components/supportTicket/TicketMetaTags.tsx +0 -85
- package/src/components/supportTicket/TicketReplyBox.stories.tsx +0 -355
- package/src/components/supportTicket/TicketReplyBox.tsx +0 -146
- package/src/components/supportTicket/fileToAttachment.ts +0 -24
- package/src/components/supportTicket/index.ts +0 -8
- package/src/components/supportTicket/meta.ts +0 -145
- package/src/components/ticketReferences/TicketReferences.stories.tsx +0 -301
- package/src/components/ticketReferences/TicketReferences.tsx +0 -899
- package/src/components/ticketReferences/index.ts +0 -2
- package/src/components/ticketThread/TicketThread.stories.tsx +0 -751
- package/src/components/ticketThread/TicketThread.tsx +0 -650
- package/src/components/ticketThread/index.ts +0 -6
- package/src/helpers/scrollbar.ts +0 -32
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
3
|
-
|
|
4
|
-
import { StoryMeta } from '../../types';
|
|
5
|
-
import { IInterfaceReference } from '../supportTicket/meta';
|
|
6
|
-
import { ITicketReferenceAttachment, TicketReferences } from './TicketReferences';
|
|
7
|
-
|
|
8
|
-
const NOW = Date.parse('2026-06-30T12:00:00Z');
|
|
9
|
-
const ago = (mins: number) => new Date(NOW - mins * 60_000).toISOString();
|
|
10
|
-
|
|
11
|
-
// The stories stand in for the authed blob-download endpoint by handing back an
|
|
12
|
-
// inline SVG data-URI per image id, so thumbnails + the lightbox render offline.
|
|
13
|
-
const svgUrl = (label: string, color: string) =>
|
|
14
|
-
`data:image/svg+xml;utf8,${encodeURIComponent(
|
|
15
|
-
`<svg xmlns="http://www.w3.org/2000/svg" width="640" height="400">` +
|
|
16
|
-
`<rect width="640" height="400" fill="${color}"/>` +
|
|
17
|
-
`<text x="320" y="215" font-size="30" fill="#ffffff" text-anchor="middle" ` +
|
|
18
|
-
`font-family="sans-serif">${label}</text></svg>`
|
|
19
|
-
)}`;
|
|
20
|
-
|
|
21
|
-
const REFERENCES: IInterfaceReference[] = [
|
|
22
|
-
{ interface_kind: 'workflow', interface_name: 'order-sync:1.0', reference_id: 'r1' },
|
|
23
|
-
{ interface_kind: 'workflow', interface_name: 'invoice-sync:2.3', reference_id: 'r2' },
|
|
24
|
-
{ interface_kind: 'service', interface_name: 'datasource-pool:2.3', reference_id: 'r3' },
|
|
25
|
-
{ interface_kind: 'job', interface_name: 'nightly-reconcile', reference_id: 'r4' },
|
|
26
|
-
{ interface_kind: 'connection', interface_name: 'pg-main-ro', reference_id: 'r5' },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
// Uploaders come already resolved from the endpoint: customer uploads carry the
|
|
30
|
-
// account, a staff reply's attachment reads "Qorus Support" on the customer plane.
|
|
31
|
-
const ATTACHMENTS: ITicketReferenceAttachment[] = [
|
|
32
|
-
{ attachment_id: 'img-1', filename: 'error-screenshot.png', content_type: 'image/png', size_bytes: 148_221, uploaded_by: 'acme-prod', uploader_type: 'customer', created: ago(180), message_id: 'm1' },
|
|
33
|
-
{ attachment_id: 'img-2', filename: 'pool-metrics.png', content_type: 'image/png', size_bytes: 96_540, uploaded_by: 'Qorus Support', uploader_type: 'staff', created: ago(120), message_id: 'm2' },
|
|
34
|
-
{ attachment_id: 'img-3', filename: 'stack-trace.png', content_type: 'image/png', size_bytes: 210_004, uploaded_by: 'acme-prod', uploader_type: 'customer', created: ago(60), message_id: 'm3' },
|
|
35
|
-
{ attachment_id: 'file-1', filename: 'nightly-trace.log', content_type: 'text/x-log', size_bytes: 219_136, uploaded_by: 'acme-prod', uploader_type: 'customer', created: ago(180), message_id: 'm1' },
|
|
36
|
-
{ attachment_id: 'file-2', filename: 'incident-report.pdf', content_type: 'application/pdf', size_bytes: 512_900, uploaded_by: 'Qorus Support', uploader_type: 'staff', created: ago(90), message_id: 'm2' },
|
|
37
|
-
{ attachment_id: 'file-3', filename: 'pool-config.yaml', content_type: 'application/yaml', size_bytes: 2_048, uploaded_by: 'acme-prod', uploader_type: 'customer', created: ago(90) },
|
|
38
|
-
{ attachment_id: 'file-4', filename: 'diagnostics.zip', content_type: 'application/zip', size_bytes: 3_400_000, uploaded_by: 'acme-prod', uploader_type: 'customer', created: ago(30), message_id: 'm3' },
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const IMG_URLS: Record<string, string> = {
|
|
42
|
-
'img-1': svgUrl('error-screenshot', '#7b3fe4'),
|
|
43
|
-
'img-2': svgUrl('pool-metrics', '#2872a0'),
|
|
44
|
-
'img-3': svgUrl('stack-trace', '#b23c3c'),
|
|
45
|
-
};
|
|
46
|
-
const fetchAttachmentUrl = (id: string) => Promise.resolve(IMG_URLS[id] ?? svgUrl(id, '#555555'));
|
|
47
|
-
|
|
48
|
-
const meta = {
|
|
49
|
-
component: TicketReferences,
|
|
50
|
-
title: 'Components/TicketReferences',
|
|
51
|
-
parameters: { layout: 'padded' },
|
|
52
|
-
args: {
|
|
53
|
-
references: REFERENCES,
|
|
54
|
-
attachments: ATTACHMENTS,
|
|
55
|
-
viewerRole: 'staff',
|
|
56
|
-
onDownloadAttachment: fn(),
|
|
57
|
-
fetchAttachmentUrl,
|
|
58
|
-
},
|
|
59
|
-
} satisfies StoryMeta<typeof TicketReferences>;
|
|
60
|
-
|
|
61
|
-
export default meta;
|
|
62
|
-
type Story = StoryObj<typeof meta>;
|
|
63
|
-
|
|
64
|
-
/** A busy ticket: 5 grouped interface references, 3 screenshots, 4 files, and the
|
|
65
|
-
* search / type-filter / sort strip a ticket this full earns. */
|
|
66
|
-
export const Populated: Story = {
|
|
67
|
-
parameters: {
|
|
68
|
-
docs: {
|
|
69
|
-
description: {
|
|
70
|
-
story:
|
|
71
|
-
'Renders a busy ticket with five grouped interface references, three screenshots, and four files — full enough to surface the search box, type-filter, and sort strip.',
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
play: async ({ canvasElement }) => {
|
|
76
|
-
const canvas = within(canvasElement);
|
|
77
|
-
await expect(canvas.getByText('Linked interfaces')).toBeInTheDocument();
|
|
78
|
-
await expect(canvas.getByText('Screenshots')).toBeInTheDocument();
|
|
79
|
-
await expect(canvas.getByText('Files')).toBeInTheDocument();
|
|
80
|
-
// references render as rows carrying their kind as metadata
|
|
81
|
-
await expect(canvasElement.textContent).toContain('workflow');
|
|
82
|
-
await expect(canvasElement.textContent).toContain('order-sync:1.0');
|
|
83
|
-
// a file row with provenance (staff view shows uploaders as stored)
|
|
84
|
-
await expect(canvas.getByText('incident-report.pdf')).toBeInTheDocument();
|
|
85
|
-
await expect(canvasElement.textContent).toContain('added by acme-prod');
|
|
86
|
-
// the control strip: search box + the type-filter and sort dropdowns
|
|
87
|
-
await expect(
|
|
88
|
-
canvas.getByPlaceholderText('Search files and references…')
|
|
89
|
-
).toBeInTheDocument();
|
|
90
|
-
await expect(canvas.getByText('All types')).toBeInTheDocument();
|
|
91
|
-
await expect(canvas.getByText('Newest first')).toBeInTheDocument();
|
|
92
|
-
// thumbnails resolve to images
|
|
93
|
-
await waitFor(() =>
|
|
94
|
-
expect(
|
|
95
|
-
canvasElement.querySelector('button[title="error-screenshot.png"] img')
|
|
96
|
-
).not.toBeNull()
|
|
97
|
-
);
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/** The control strip in action: search narrows to matches, a no-match query offers
|
|
102
|
-
* "Clear filters", and the type filter collapses the view to one family. */
|
|
103
|
-
export const Filtering: Story = {
|
|
104
|
-
parameters: {
|
|
105
|
-
docs: {
|
|
106
|
-
description: {
|
|
107
|
-
story:
|
|
108
|
-
"Renders the control strip in action — searching narrows to matching files and references, a no-match query offers 'Clear filters', and the type filter collapses the view to a single family.",
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
play: async ({ canvasElement }) => {
|
|
113
|
-
const canvas = within(canvasElement);
|
|
114
|
-
const box = canvas.getByPlaceholderText('Search files and references…');
|
|
115
|
-
|
|
116
|
-
// search narrows across both files and screenshots by filename
|
|
117
|
-
await userEvent.type(box, 'pool');
|
|
118
|
-
await waitFor(() => {
|
|
119
|
-
// "pool-*" survive, "error-screenshot"/"nightly-trace" fall away
|
|
120
|
-
expect(canvas.getByText('pool-config.yaml')).toBeInTheDocument();
|
|
121
|
-
expect(canvasElement.querySelector('button[title="pool-metrics.png"]')).not.toBeNull();
|
|
122
|
-
expect(canvasElement.querySelector('button[title="error-screenshot.png"]')).toBeNull();
|
|
123
|
-
expect(canvas.queryByText('nightly-trace.log')).toBeNull();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// a query that matches nothing surfaces the empty state + a clear affordance
|
|
127
|
-
await userEvent.clear(box);
|
|
128
|
-
await userEvent.type(box, 'zzz-no-such-file');
|
|
129
|
-
await waitFor(() =>
|
|
130
|
-
expect(canvasElement.textContent).toContain('No matching references or files')
|
|
131
|
-
);
|
|
132
|
-
await userEvent.click(canvas.getByText('Clear filters'));
|
|
133
|
-
await waitFor(() => expect(canvas.getByText('Files')).toBeInTheDocument());
|
|
134
|
-
|
|
135
|
-
// the type filter collapses to a single family (Screenshots only)
|
|
136
|
-
await userEvent.click(canvas.getByText('All types'));
|
|
137
|
-
await userEvent.click(await within(document.body).findByText(/^Screenshots \(3\)$/));
|
|
138
|
-
await waitFor(() => {
|
|
139
|
-
expect(canvas.queryByText('Files')).toBeNull();
|
|
140
|
-
expect(canvas.queryByText('Linked interfaces')).toBeNull();
|
|
141
|
-
expect(canvasElement.querySelector('button[title="stack-trace.png"]')).not.toBeNull();
|
|
142
|
-
});
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
/** Clicking a loaded screenshot opens the paging lightbox (portalled to body). */
|
|
147
|
-
export const LightboxOpens: Story = {
|
|
148
|
-
parameters: {
|
|
149
|
-
docs: {
|
|
150
|
-
description: {
|
|
151
|
-
story:
|
|
152
|
-
'Renders the references view and, when a loaded screenshot is clicked, opens the paging lightbox portalled to the body.',
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
play: async ({ canvasElement }) => {
|
|
157
|
-
const thumb = await waitFor(() => {
|
|
158
|
-
const el = canvasElement.querySelector<HTMLButtonElement>(
|
|
159
|
-
'button[title="error-screenshot.png"]'
|
|
160
|
-
);
|
|
161
|
-
if (!el || !el.querySelector('img')) {
|
|
162
|
-
throw new Error('thumbnail not ready');
|
|
163
|
-
}
|
|
164
|
-
return el;
|
|
165
|
-
});
|
|
166
|
-
await userEvent.click(thumb);
|
|
167
|
-
// error-screenshot is the oldest of the three, so under the default
|
|
168
|
-
// newest-first sort it sits last — the counter reads "3 / 3".
|
|
169
|
-
await waitFor(() => expect(document.body.textContent).toContain('3 / 3'));
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
/** The same ticket from the customer's side: their own uploads read "you", and a
|
|
174
|
-
* staff reply's attachment reads "Qorus Support" — never the raw staff identity. */
|
|
175
|
-
export const CustomerView: Story = {
|
|
176
|
-
parameters: {
|
|
177
|
-
docs: {
|
|
178
|
-
description: {
|
|
179
|
-
story:
|
|
180
|
-
"Renders the same ticket from the customer's side, where their own uploads read 'added by you' and a staff reply's attachment reads 'Qorus Support' rather than the raw staff identity.",
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
args: { viewerRole: 'customer' },
|
|
185
|
-
play: async ({ canvasElement }) => {
|
|
186
|
-
await waitFor(() => expect(canvasElement.textContent).toContain('added by you'));
|
|
187
|
-
await expect(canvasElement.textContent).toContain('added by Qorus Support');
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
/** Without a fetcher, screenshots degrade to download tiles rather than thumbnails. */
|
|
192
|
-
export const NoPreview: Story = {
|
|
193
|
-
parameters: {
|
|
194
|
-
docs: {
|
|
195
|
-
description: {
|
|
196
|
-
story:
|
|
197
|
-
'Renders the references view with no fetchAttachmentUrl, so screenshots degrade to download tiles rather than thumbnails.',
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
args: { fetchAttachmentUrl: undefined },
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
/** Nothing attached or linked. */
|
|
205
|
-
export const Empty: Story = {
|
|
206
|
-
parameters: {
|
|
207
|
-
docs: {
|
|
208
|
-
description: {
|
|
209
|
-
story:
|
|
210
|
-
"Renders the empty state with nothing attached or linked, showing 'No references or files yet'.",
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
args: { references: [], attachments: [], messages: [] },
|
|
215
|
-
play: async ({ canvasElement }) => {
|
|
216
|
-
await expect(canvasElement.textContent).toContain('No references or files yet');
|
|
217
|
-
},
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* With `onShowInChat` wired, a row that came from a reply gains a "three dots" menu
|
|
222
|
-
* offering to reveal it in the conversation.
|
|
223
|
-
*
|
|
224
|
-
* A row filed against the ticket itself carries the same menu, but its reveal is
|
|
225
|
-
* disabled and labelled "Filed on the ticket" — there's no message to jump to. That
|
|
226
|
-
* distinction between a reply-borne row and a ticket-level one is the thing to see here.
|
|
227
|
-
*/
|
|
228
|
-
export const ShowInChat: Story = {
|
|
229
|
-
parameters: {
|
|
230
|
-
docs: {
|
|
231
|
-
description: {
|
|
232
|
-
story:
|
|
233
|
-
"Renders references with onShowInChat wired — a reply-borne row's menu offers an active 'Show in chat' that calls onShowInChat, while a ticket-level row carries the same menu with its reveal disabled ('Filed on the ticket').",
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
args: {
|
|
238
|
-
messages: [
|
|
239
|
-
{
|
|
240
|
-
message_id: 'm-42',
|
|
241
|
-
author_type: 'customer',
|
|
242
|
-
author_id: 'acme-prod',
|
|
243
|
-
body: 'Same failure on the reconcile job.',
|
|
244
|
-
created: ago(30),
|
|
245
|
-
referenced_interfaces: [{ interface_kind: 'job', interface_name: 'nightly-reconcile' }],
|
|
246
|
-
},
|
|
247
|
-
],
|
|
248
|
-
onShowInChat: fn(),
|
|
249
|
-
},
|
|
250
|
-
play: async ({ args, canvasElement }) => {
|
|
251
|
-
const canvas = within(canvasElement);
|
|
252
|
-
await expect(canvas.getByText('nightly-reconcile')).toBeInTheDocument();
|
|
253
|
-
|
|
254
|
-
const rowFor = (label: string) =>
|
|
255
|
-
Array.from(canvasElement.querySelectorAll<HTMLElement>('.reqore-entity-row')).find((row) =>
|
|
256
|
-
row.textContent?.includes(label)
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
// the reply-borne reference offers the menu...
|
|
260
|
-
const fromReply = rowFor('nightly-reconcile');
|
|
261
|
-
const menuButton = fromReply?.querySelector<HTMLElement>(
|
|
262
|
-
'.reqore-entity-row-actions .reqore-button:last-child'
|
|
263
|
-
);
|
|
264
|
-
await userEvent.click(menuButton!);
|
|
265
|
-
const item = await waitFor(() => {
|
|
266
|
-
const found = Array.from(document.querySelectorAll<HTMLElement>('.reqore-menu-item')).find(
|
|
267
|
-
(el) => /Show in chat/.test(el.textContent || '')
|
|
268
|
-
);
|
|
269
|
-
if (!found) {
|
|
270
|
-
throw new Error('Show in chat not offered');
|
|
271
|
-
}
|
|
272
|
-
return found;
|
|
273
|
-
});
|
|
274
|
-
await userEvent.click(item);
|
|
275
|
-
await expect(args.onShowInChat).toHaveBeenCalledWith('m-42');
|
|
276
|
-
|
|
277
|
-
// ...and a ticket-level reference carries the SAME menu, so the rows don't look
|
|
278
|
-
// half-broken — but the reveal is disabled there, because it was filed on the
|
|
279
|
-
// ticket and has no message to jump to.
|
|
280
|
-
const ticketLevel = rowFor('order-sync:1.0');
|
|
281
|
-
const ticketMenu = ticketLevel?.querySelector<HTMLElement>(
|
|
282
|
-
'.reqore-entity-row-actions .reqore-button:last-child'
|
|
283
|
-
);
|
|
284
|
-
await expect(ticketMenu).toBeTruthy();
|
|
285
|
-
await userEvent.click(ticketMenu!);
|
|
286
|
-
const ticketEntry = await waitFor(() => {
|
|
287
|
-
const entry = Array.from(document.querySelectorAll<HTMLElement>('.reqore-menu-item')).find(
|
|
288
|
-
(el) => /Show in chat/.test(el.textContent || '')
|
|
289
|
-
);
|
|
290
|
-
if (!entry) {
|
|
291
|
-
throw new Error('the menu should still offer the entry, disabled');
|
|
292
|
-
}
|
|
293
|
-
return entry;
|
|
294
|
-
});
|
|
295
|
-
// it is genuinely unclickable, not merely styled as such — and the handler stays
|
|
296
|
-
// on its single call from the reply-borne row above
|
|
297
|
-
await expect(getComputedStyle(ticketEntry).pointerEvents).toBe('none');
|
|
298
|
-
await expect(ticketEntry.textContent).toContain('Filed on the ticket');
|
|
299
|
-
await expect(args.onShowInChat).toHaveBeenCalledTimes(1);
|
|
300
|
-
},
|
|
301
|
-
};
|