@qoretechnologies/reqraft 0.10.1 → 0.10.2
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/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/lspClient.js +5 -5
- package/dist/utils/lspClient.js.map +1 -1
- package/package.json +24 -33
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +2 -2
- package/src/components/form/engine/FormEngine.stories.tsx +122 -128
- package/src/components/form/engine/FormEngineRemote.stories.tsx +2 -2
- package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +2 -2
- package/src/components/form/expressions/ExpressionField.stories.tsx +2 -2
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +2 -2
- package/src/components/form/fields/Field.stories.tsx +2 -2
- package/src/components/form/fields/array/ArrayAutoField.stories.tsx +2 -2
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +2 -2
- package/src/components/form/fields/boolean/Boolean.stories.tsx +2 -2
- package/src/components/form/fields/byte-size/ByteSize.stories.tsx +2 -2
- package/src/components/form/fields/color/Color.stories.tsx +2 -2
- package/src/components/form/fields/cron/Cron.stories.tsx +2 -2
- package/src/components/form/fields/date/Date.stories.tsx +2 -2
- package/src/components/form/fields/file/File.stories.tsx +2 -2
- package/src/components/form/fields/long-string/LongString.stories.tsx +2 -2
- package/src/components/form/fields/markdown/Markdown.stories.tsx +2 -2
- package/src/components/form/fields/number/Number.stories.tsx +2 -2
- package/src/components/form/fields/object/Object.stories.tsx +4 -4
- package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +2 -2
- package/src/components/form/fields/rich-text/RichText.stories.tsx +2 -2
- package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +2 -2
- package/src/components/form/fields/select/Select.stories.tsx +2 -2
- package/src/components/form/fields/string/String.stories.tsx +2 -2
- package/src/components/form/fields/template/TemplateField.stories.tsx +2 -2
- package/src/components/form/fields/url/Url.stories.tsx +2 -2
- package/src/components/log/Log.stories.tsx +2 -2
- package/src/components/menu/Menu.stories.tsx +2 -2
- package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +2 -2
- package/src/components/smartEditor/SmartEditor.stories.tsx +2 -2
- package/src/hooks/useFetch/useFetch.stories.tsx +5 -5
- package/src/hooks/useStorage/useStorage.stories.tsx +2 -2
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -2
- package/src/index.tsx +8 -6
- package/src/stores/currentUser/currentUser.stories.tsx +4 -4
- package/src/stories/Tests/utils.ts +1 -1
- package/src/types.ts +1 -1
- package/vite.config.ts +58 -0
- package/vitest.config.ts +69 -0
- package/dist/stories/Tests/utils.d.ts +0 -32
- package/dist/stories/Tests/utils.d.ts.map +0 -1
- package/dist/stories/Tests/utils.js +0 -416
- package/dist/stories/Tests/utils.js.map +0 -1
- package/dist/types.d.ts +0 -9
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ReqoreInput
|
|
3
|
-
} from '@qoretechnologies/reqore';
|
|
1
|
+
import { ReqoreInput } from '@qoretechnologies/reqore';
|
|
4
2
|
import { TSizes } from '@qoretechnologies/reqore/dist/constants/sizes';
|
|
5
3
|
import { IQorusFormSchema } from '@qoretechnologies/ts-toolkit';
|
|
6
|
-
import { Meta, StoryObj } from '@storybook/react';
|
|
7
|
-
import { expect, fireEvent, fn, userEvent, waitFor, within } from '@storybook/test';
|
|
4
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
8
5
|
import { ChangeEvent, useState } from 'react';
|
|
6
|
+
import { expect, fireEvent, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
9
7
|
import { validateField } from '../../../helpers/validations';
|
|
10
8
|
import {
|
|
11
9
|
_testsChangeRichText,
|
|
@@ -288,10 +286,9 @@ export const ValueCanBeRemoved: Story = {
|
|
|
288
286
|
timeout: 10000,
|
|
289
287
|
});
|
|
290
288
|
await _testsClickButton({ selector: '.options-item-remove', nth: 0 });
|
|
291
|
-
await waitFor(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
);
|
|
289
|
+
await waitFor(() => expect(document.querySelectorAll('.options-item-revert').length).toBe(1), {
|
|
290
|
+
timeout: 10000,
|
|
291
|
+
});
|
|
295
292
|
await userEvent.hover(document.querySelectorAll('.system-option')[1]);
|
|
296
293
|
await waitFor(() => expect(document.querySelector('.options-item-remove')).toBeTruthy(), {
|
|
297
294
|
timeout: 10000,
|
|
@@ -1109,12 +1106,20 @@ export const CompactBasic: Story = {
|
|
|
1109
1106
|
'.readfirst-row[data-field="optionWithShortDescription"] .options-readfirst-lock-deps'
|
|
1110
1107
|
) as HTMLElement;
|
|
1111
1108
|
await expect(depLock).toBeTruthy();
|
|
1112
|
-
|
|
1109
|
+
// userEvent (real pointer sequence) keeps the dropdown popover open —
|
|
1110
|
+
// fireEvent's synthetic click opened it then immediately closed it via the
|
|
1111
|
+
// outside-click handler in the Vitest browser. Wait for the menu ITEM, not
|
|
1112
|
+
// just the "Unlocked by:" divider, before clicking it.
|
|
1113
|
+
await userEvent.click(depLock);
|
|
1113
1114
|
await _testsWaitForText('Unlocked by:');
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1115
|
+
let depEntry: HTMLElement | undefined;
|
|
1116
|
+
await waitFor(() => {
|
|
1117
|
+
depEntry = Array.from(document.querySelectorAll('.reqore-menu-item')).find((element) =>
|
|
1118
|
+
element.textContent?.includes('basicOption')
|
|
1119
|
+
) as HTMLElement;
|
|
1120
|
+
expect(depEntry).toBeTruthy();
|
|
1121
|
+
});
|
|
1122
|
+
await userEvent.click(depEntry as HTMLElement);
|
|
1118
1123
|
await waitFor(
|
|
1119
1124
|
() =>
|
|
1120
1125
|
expect(
|
|
@@ -1235,9 +1240,7 @@ export const CompactReadOnlyRichText: Story = {
|
|
|
1235
1240
|
await _testsClickText('Template option');
|
|
1236
1241
|
await waitFor(
|
|
1237
1242
|
() => {
|
|
1238
|
-
const card = document.querySelector(
|
|
1239
|
-
'.options-readfirst-card[data-field="templateOption"]'
|
|
1240
|
-
);
|
|
1243
|
+
const card = document.querySelector('.options-readfirst-card[data-field="templateOption"]');
|
|
1241
1244
|
expect(card).toBeTruthy();
|
|
1242
1245
|
const tag = card?.querySelector('.reqore-tag');
|
|
1243
1246
|
expect(tag).toBeTruthy();
|
|
@@ -1247,9 +1250,7 @@ export const CompactReadOnlyRichText: Story = {
|
|
|
1247
1250
|
// label must be the resolved name, never the raw reference.
|
|
1248
1251
|
expect(tag?.textContent).toContain('Test (local)');
|
|
1249
1252
|
expect(tag?.textContent).not.toContain('$local:test');
|
|
1250
|
-
expect(
|
|
1251
|
-
card?.querySelector('input, textarea, [contenteditable="true"]')
|
|
1252
|
-
).toBeFalsy();
|
|
1253
|
+
expect(card?.querySelector('input, textarea, [contenteditable="true"]')).toBeFalsy();
|
|
1253
1254
|
},
|
|
1254
1255
|
{ timeout: 10000 }
|
|
1255
1256
|
);
|
|
@@ -1339,7 +1340,9 @@ export const CompactHashStructuredView: Story = {
|
|
|
1339
1340
|
await fireEvent.click(valueChip);
|
|
1340
1341
|
await waitFor(
|
|
1341
1342
|
() =>
|
|
1342
|
-
expect(
|
|
1343
|
+
expect(
|
|
1344
|
+
document.querySelector('.options-readfirst-card[data-field="orderState"]')
|
|
1345
|
+
).toBeTruthy(),
|
|
1343
1346
|
{ timeout: 10000 }
|
|
1344
1347
|
);
|
|
1345
1348
|
|
|
@@ -1363,9 +1366,7 @@ export const CompactHashStructuredView: Story = {
|
|
|
1363
1366
|
{ timeout: 10000 }
|
|
1364
1367
|
);
|
|
1365
1368
|
await fireEvent.click(
|
|
1366
|
-
document.querySelector(
|
|
1367
|
-
'[data-field="orderState"] .options-readfirst-viewmore'
|
|
1368
|
-
) as HTMLElement
|
|
1369
|
+
document.querySelector('[data-field="orderState"] .options-readfirst-viewmore') as HTMLElement
|
|
1369
1370
|
);
|
|
1370
1371
|
await _testsWaitForText('Show less'); // fade expanded → full tree on screen
|
|
1371
1372
|
|
|
@@ -1504,10 +1505,9 @@ export const CompactSensitive: Story = {
|
|
|
1504
1505
|
// textarea is exempt: it reflects its VALUE as a text child, which is how
|
|
1505
1506
|
// the user edits the secret — anything else holding the text is a leak.
|
|
1506
1507
|
await _testsClickText('••••••');
|
|
1507
|
-
await waitFor(
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
);
|
|
1508
|
+
await waitFor(() => expect(document.querySelector('.options-readfirst-inline')).toBeTruthy(), {
|
|
1509
|
+
timeout: 10000,
|
|
1510
|
+
});
|
|
1511
1511
|
await _testsWaitForTextToNotExist('super-secret-token', ':not(textarea)');
|
|
1512
1512
|
|
|
1513
1513
|
// Close the editor so the story's hero shot is the MASKED read row — not the
|
|
@@ -1578,7 +1578,9 @@ export const CompactOperators: Story = {
|
|
|
1578
1578
|
// Single clear: a single-value card hides the editor's own input ✕ (it has
|
|
1579
1579
|
// no Reqore prop, so the card marks itself `-single` and CSS hides it) and
|
|
1580
1580
|
// shows the card-action Clear between Fullscreen and Done instead.
|
|
1581
|
-
const card = document.querySelector(
|
|
1581
|
+
const card = document.querySelector(
|
|
1582
|
+
'.options-readfirst-card[data-field="status"]'
|
|
1583
|
+
) as HTMLElement;
|
|
1582
1584
|
await expect(card.className).toContain('options-readfirst-card-single');
|
|
1583
1585
|
await expect(card.querySelector('.options-readfirst-clear')).toBeInTheDocument();
|
|
1584
1586
|
const builtInClear = card.querySelector('.reqore-clear-input-button') as HTMLElement | null;
|
|
@@ -1657,8 +1659,20 @@ export const CompactSortOrder: Story = {
|
|
|
1657
1659
|
compact: true,
|
|
1658
1660
|
minColumnWidth: '300px',
|
|
1659
1661
|
options: {
|
|
1660
|
-
third: {
|
|
1661
|
-
|
|
1662
|
+
third: {
|
|
1663
|
+
type: 'string',
|
|
1664
|
+
ui_type: 'string',
|
|
1665
|
+
display_name: 'Third',
|
|
1666
|
+
sort: 3,
|
|
1667
|
+
preselected: true,
|
|
1668
|
+
},
|
|
1669
|
+
first: {
|
|
1670
|
+
type: 'string',
|
|
1671
|
+
ui_type: 'string',
|
|
1672
|
+
display_name: 'First',
|
|
1673
|
+
sort: 1,
|
|
1674
|
+
preselected: true,
|
|
1675
|
+
},
|
|
1662
1676
|
second: {
|
|
1663
1677
|
type: 'string',
|
|
1664
1678
|
ui_type: 'string',
|
|
@@ -1789,9 +1803,7 @@ export const CompactFieldsMenu: Story = {
|
|
|
1789
1803
|
await clickFieldsMenuItem('Select all');
|
|
1790
1804
|
await _testsWaitForText('Notes');
|
|
1791
1805
|
await fireEvent.click(
|
|
1792
|
-
document.querySelector(
|
|
1793
|
-
'.readfirst-row[data-field="notes"] .readfirst-action'
|
|
1794
|
-
) as HTMLElement
|
|
1806
|
+
document.querySelector('.readfirst-row[data-field="notes"] .readfirst-action') as HTMLElement
|
|
1795
1807
|
);
|
|
1796
1808
|
await _testsWaitForText('Remove field');
|
|
1797
1809
|
await _testsClickButton({ label: 'Confirm' });
|
|
@@ -2025,9 +2037,7 @@ export const CompactOverflowAndStickyHeader: Story = {
|
|
|
2025
2037
|
scroller.scrollTop = scroller.scrollHeight;
|
|
2026
2038
|
await waitFor(() => {
|
|
2027
2039
|
expect(scroller.scrollTop).toBeGreaterThan(0);
|
|
2028
|
-
const search = document.querySelector(
|
|
2029
|
-
'input[placeholder="Filter fields..."]'
|
|
2030
|
-
) as HTMLElement;
|
|
2040
|
+
const search = document.querySelector('input[placeholder="Filter fields..."]') as HTMLElement;
|
|
2031
2041
|
const scrollerTop = scroller.getBoundingClientRect().top;
|
|
2032
2042
|
expect(search.getBoundingClientRect().top).toBeGreaterThanOrEqual(scrollerTop - 1);
|
|
2033
2043
|
expect(search.getBoundingClientRect().top).toBeLessThan(scrollerTop + 150);
|
|
@@ -2307,7 +2317,9 @@ export const CompactEnumWithImages: Story = {
|
|
|
2307
2317
|
|
|
2308
2318
|
// Bug 2: drilling in lists every enum choice WITH its logo (the editor was
|
|
2309
2319
|
// empty before — it only read `allowed_values`, never the IDE `items`).
|
|
2310
|
-
await fireEvent.click(
|
|
2320
|
+
await fireEvent.click(
|
|
2321
|
+
document.querySelector('.readfirst-row[data-field="lang"]') as HTMLElement
|
|
2322
|
+
);
|
|
2311
2323
|
await waitFor(
|
|
2312
2324
|
() => {
|
|
2313
2325
|
const card = document.querySelector('.options-readfirst-card[data-field="lang"]');
|
|
@@ -2341,9 +2353,21 @@ export const CompactEnumRichtextValue: Story = {
|
|
|
2341
2353
|
required: true,
|
|
2342
2354
|
default_value: { type: 'richtext', value: 'qore' },
|
|
2343
2355
|
allowed_values: [
|
|
2344
|
-
{
|
|
2345
|
-
|
|
2346
|
-
|
|
2356
|
+
{
|
|
2357
|
+
display_name: 'Qore',
|
|
2358
|
+
value: { type: 'richtext', value: 'qore' },
|
|
2359
|
+
image: langImg('#c0007a', 'Q'),
|
|
2360
|
+
},
|
|
2361
|
+
{
|
|
2362
|
+
display_name: 'Python',
|
|
2363
|
+
value: { type: 'richtext', value: 'python' },
|
|
2364
|
+
image: langImg('#3776ab', 'P'),
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
display_name: 'Java',
|
|
2368
|
+
value: { type: 'richtext', value: 'java' },
|
|
2369
|
+
image: langImg('#e76f00', 'J'),
|
|
2370
|
+
},
|
|
2347
2371
|
],
|
|
2348
2372
|
},
|
|
2349
2373
|
} as unknown as IOptionsSchema,
|
|
@@ -2362,7 +2386,9 @@ export const CompactEnumRichtextValue: Story = {
|
|
|
2362
2386
|
{ timeout: 10000 }
|
|
2363
2387
|
);
|
|
2364
2388
|
// Drill in → the RADIO renders (not a rich-text box) with every language.
|
|
2365
|
-
await fireEvent.click(
|
|
2389
|
+
await fireEvent.click(
|
|
2390
|
+
document.querySelector('.readfirst-row[data-field="lang"]') as HTMLElement
|
|
2391
|
+
);
|
|
2366
2392
|
await waitFor(
|
|
2367
2393
|
() => {
|
|
2368
2394
|
const card = document.querySelector('.options-readfirst-card[data-field="lang"]');
|
|
@@ -2402,9 +2428,13 @@ export const CompactSingleExpand: Story = {
|
|
|
2402
2428
|
() => expect(document.querySelector('.readfirst-row[data-field="beta"]')).toBeTruthy(),
|
|
2403
2429
|
{ timeout: 10000 }
|
|
2404
2430
|
);
|
|
2405
|
-
await fireEvent.click(
|
|
2431
|
+
await fireEvent.click(
|
|
2432
|
+
document.querySelector('.readfirst-row[data-field="alpha"]') as HTMLElement
|
|
2433
|
+
);
|
|
2406
2434
|
await waitFor(() => expect(_isRowOpen('alpha')).toBe(true), { timeout: 10000 });
|
|
2407
|
-
await fireEvent.click(
|
|
2435
|
+
await fireEvent.click(
|
|
2436
|
+
document.querySelector('.readfirst-row[data-field="beta"]') as HTMLElement
|
|
2437
|
+
);
|
|
2408
2438
|
await waitFor(
|
|
2409
2439
|
() => {
|
|
2410
2440
|
expect(_isRowOpen('beta')).toBe(true);
|
|
@@ -2424,9 +2454,13 @@ export const CompactMultiExpand: Story = {
|
|
|
2424
2454
|
() => expect(document.querySelector('.readfirst-row[data-field="beta"]')).toBeTruthy(),
|
|
2425
2455
|
{ timeout: 10000 }
|
|
2426
2456
|
);
|
|
2427
|
-
await fireEvent.click(
|
|
2457
|
+
await fireEvent.click(
|
|
2458
|
+
document.querySelector('.readfirst-row[data-field="alpha"]') as HTMLElement
|
|
2459
|
+
);
|
|
2428
2460
|
await waitFor(() => expect(_isRowOpen('alpha')).toBe(true), { timeout: 10000 });
|
|
2429
|
-
await fireEvent.click(
|
|
2461
|
+
await fireEvent.click(
|
|
2462
|
+
document.querySelector('.readfirst-row[data-field="beta"]') as HTMLElement
|
|
2463
|
+
);
|
|
2430
2464
|
await waitFor(
|
|
2431
2465
|
() => {
|
|
2432
2466
|
expect(_isRowOpen('beta')).toBe(true);
|
|
@@ -2473,8 +2507,18 @@ export const CompactFieldTypes: Story = {
|
|
|
2473
2507
|
options: {
|
|
2474
2508
|
// Text & string
|
|
2475
2509
|
text: { type: 'string', ui_type: 'string', display_name: 'String', group: 'text' },
|
|
2476
|
-
longText: {
|
|
2477
|
-
|
|
2510
|
+
longText: {
|
|
2511
|
+
type: 'string',
|
|
2512
|
+
ui_type: 'long-string',
|
|
2513
|
+
display_name: 'Long string',
|
|
2514
|
+
group: 'text',
|
|
2515
|
+
},
|
|
2516
|
+
markdownText: {
|
|
2517
|
+
type: 'string',
|
|
2518
|
+
ui_type: 'markdown',
|
|
2519
|
+
display_name: 'Markdown',
|
|
2520
|
+
group: 'text',
|
|
2521
|
+
},
|
|
2478
2522
|
richText: { type: 'richtext', ui_type: 'richtext', display_name: 'Rich text', group: 'text' },
|
|
2479
2523
|
template: {
|
|
2480
2524
|
type: 'string',
|
|
@@ -2717,7 +2761,10 @@ export const CompactFieldTypes: Story = {
|
|
|
2717
2761
|
value: 'A longer paragraph of text that wraps across more than one line in the editor.',
|
|
2718
2762
|
},
|
|
2719
2763
|
markdownText: { type: 'string', value: '# Heading\nSome **bold** text' },
|
|
2720
|
-
richText: {
|
|
2764
|
+
richText: {
|
|
2765
|
+
type: 'richtext',
|
|
2766
|
+
value: [{ type: 'paragraph', children: [{ text: 'rich note' }] }],
|
|
2767
|
+
},
|
|
2721
2768
|
template: { type: 'string', value: '$config:billing_url' },
|
|
2722
2769
|
schedule: { type: 'string', value: '0 0 * * *' },
|
|
2723
2770
|
when: { type: 'date', value: '2026-06-09' },
|
|
@@ -2901,7 +2948,9 @@ export const CompactFieldTypes: Story = {
|
|
|
2901
2948
|
'.readfirst-row[data-field="infoShortDesc"] .options-readfirst-info-slot .options-readfirst-info-toggle'
|
|
2902
2949
|
) as HTMLElement
|
|
2903
2950
|
);
|
|
2904
|
-
await _testsWaitForText(
|
|
2951
|
+
await _testsWaitForText(
|
|
2952
|
+
'A one-line summary shown under the field name and in the hover title.'
|
|
2953
|
+
);
|
|
2905
2954
|
await expect(
|
|
2906
2955
|
document.querySelector('.readfirst-row[data-field="infoLongDesc"] .options-readfirst-help')
|
|
2907
2956
|
).toBeTruthy();
|
|
@@ -2981,9 +3030,7 @@ export const CompactFieldTypesEditing: Story = {
|
|
|
2981
3030
|
|
|
2982
3031
|
// The boolean (value: true) has no built-in clear, so the row-level Clear is
|
|
2983
3032
|
// the only one — and there is no Revert yet (value matches the original).
|
|
2984
|
-
await expect(
|
|
2985
|
-
editRow('enabled').querySelectorAll('.reqore-clear-input-button')
|
|
2986
|
-
).toHaveLength(0);
|
|
3033
|
+
await expect(editRow('enabled').querySelectorAll('.reqore-clear-input-button')).toHaveLength(0);
|
|
2987
3034
|
await expect(editRow('enabled').querySelector('.options-readfirst-clear')).toBeInTheDocument();
|
|
2988
3035
|
await expect(
|
|
2989
3036
|
editRow('enabled').querySelector('.options-readfirst-revert')
|
|
@@ -2998,69 +3045,6 @@ export const CompactFieldTypesEditing: Story = {
|
|
|
2998
3045
|
},
|
|
2999
3046
|
};
|
|
3000
3047
|
|
|
3001
|
-
// Same catalog, EVERY field required and NOTHING set, all open: each editor in
|
|
3002
|
-
// its required/invalid state — the canary for editors that misbehave on an
|
|
3003
|
-
// empty required value.
|
|
3004
|
-
export const CompactFieldTypesEditingAllRequired: Story = {
|
|
3005
|
-
// chromatic off: every catalog editor mounts live (async) — flaky and snapshot-heavy.
|
|
3006
|
-
parameters: { chromatic: { disable: true } },
|
|
3007
|
-
args: {
|
|
3008
|
-
...CompactFieldTypes.args,
|
|
3009
|
-
expandMode: 'multi' as const,
|
|
3010
|
-
options: Object.fromEntries(
|
|
3011
|
-
Object.entries(CompactFieldTypes.args!.options as IOptionsSchema).map(([name, option]) => [
|
|
3012
|
-
name,
|
|
3013
|
-
{ ...(option as object), required: true },
|
|
3014
|
-
])
|
|
3015
|
-
) as IOptionsSchema,
|
|
3016
|
-
value: {} as IOptions,
|
|
3017
|
-
},
|
|
3018
|
-
play: async () => {
|
|
3019
|
-
await _testsWaitForText('String');
|
|
3020
|
-
// Everything is required and unset: the invalid-fields banner shows.
|
|
3021
|
-
await _testsWaitForText(/fields are not valid and require attention/);
|
|
3022
|
-
await _compactExpandAllRows();
|
|
3023
|
-
// The editors render their own required messages (the read-row Required
|
|
3024
|
-
// tags are replaced by the editor strip while editing).
|
|
3025
|
-
await waitFor(() =>
|
|
3026
|
-
expect(
|
|
3027
|
-
within(document.body).queryAllByText('This field is required').length
|
|
3028
|
-
).toBeGreaterThan(20)
|
|
3029
|
-
);
|
|
3030
|
-
// Every catalog row resolves to an editor: built-ins (incl. markdown/cron,
|
|
3031
|
-
// bridged into AutoFormField) render natively, and Qorus-domain types
|
|
3032
|
-
// (mapper / data-provider) render via componentOverrides. None falls
|
|
3033
|
-
// through to the "Unknown type!" tag.
|
|
3034
|
-
expect(within(document.body).queryAllByText('Unknown type!')).toHaveLength(0);
|
|
3035
|
-
|
|
3036
|
-
// The empty `any` card: custom values are disallowed for `any` (the
|
|
3037
|
-
// value's TYPE is picked first), so its only control is the template menu
|
|
3038
|
-
// — which therefore renders as a labelled "Set value" trigger instead of
|
|
3039
|
-
// the bare ⋮. Picking a type from the menu mounts that type's editor.
|
|
3040
|
-
await _testsClickText('Set value');
|
|
3041
|
-
await _testsClickText('Set Custom Value');
|
|
3042
|
-
// Scope the type pick to the open menu — with every editor expanded, an
|
|
3043
|
-
// editor toolbar can carry its own "Text" label.
|
|
3044
|
-
await waitFor(() =>
|
|
3045
|
-
expect(
|
|
3046
|
-
within(document.querySelector('.reqore-menu') as HTMLElement).getByText('Text')
|
|
3047
|
-
).toBeInTheDocument()
|
|
3048
|
-
);
|
|
3049
|
-
await fireEvent.click(
|
|
3050
|
-
within(document.querySelector('.reqore-menu') as HTMLElement).getByText('Text')
|
|
3051
|
-
);
|
|
3052
|
-
await waitFor(
|
|
3053
|
-
() =>
|
|
3054
|
-
expect(
|
|
3055
|
-
document.querySelector(
|
|
3056
|
-
'.options-readfirst-card[data-field="dynamic"] [contenteditable="true"]'
|
|
3057
|
-
)
|
|
3058
|
-
).toBeTruthy(),
|
|
3059
|
-
{ timeout: 10000 }
|
|
3060
|
-
);
|
|
3061
|
-
},
|
|
3062
|
-
};
|
|
3063
|
-
|
|
3064
3048
|
// required_groups linkage: every member shows a PERSISTENT chip — amber "One of"
|
|
3065
3049
|
// while unmet (tap-popover → scroll + flash siblings, hover highlights), flipping
|
|
3066
3050
|
// to a muted-green "Covers" / "Covered by <X>" once satisfied. Members live in
|
|
@@ -3115,18 +3099,20 @@ export const CompactRequiredGroups: Story = {
|
|
|
3115
3099
|
const groupSelector = document.querySelector(
|
|
3116
3100
|
'.readfirst-row[data-field="byUrl"] .options-readfirst-required-group'
|
|
3117
3101
|
) as HTMLElement;
|
|
3118
|
-
|
|
3102
|
+
// userEvent keeps the dropdown popover open (fireEvent's synthetic click
|
|
3103
|
+
// closes it via the outside-click handler in the Vitest browser).
|
|
3104
|
+
await userEvent.click(groupSelector);
|
|
3119
3105
|
const memberEntry = await waitFor(
|
|
3120
3106
|
() => {
|
|
3121
|
-
const item = Array.from(
|
|
3122
|
-
|
|
3123
|
-
)
|
|
3107
|
+
const item = Array.from(document.querySelectorAll('.reqore-menu-item')).find((element) =>
|
|
3108
|
+
element.textContent?.includes('By host')
|
|
3109
|
+
) as HTMLElement;
|
|
3124
3110
|
expect(item).toBeTruthy();
|
|
3125
3111
|
return item;
|
|
3126
3112
|
},
|
|
3127
3113
|
{ timeout: 10000 }
|
|
3128
3114
|
);
|
|
3129
|
-
await
|
|
3115
|
+
await userEvent.click(memberEntry);
|
|
3130
3116
|
await waitFor(
|
|
3131
3117
|
() =>
|
|
3132
3118
|
expect(
|
|
@@ -3230,15 +3216,20 @@ export const CompactOptionDependsOnOptionOrAnotherOption: Story = {
|
|
|
3230
3216
|
'.readfirst-row[data-field="RequiredOption6"] .options-readfirst-lock-deps'
|
|
3231
3217
|
) as HTMLElement;
|
|
3232
3218
|
await expect(depLock).toBeTruthy();
|
|
3233
|
-
|
|
3219
|
+
// userEvent keeps the dropdown popover open (see note above).
|
|
3220
|
+
await userEvent.click(depLock);
|
|
3234
3221
|
await _testsWaitForText('Unlocked by:');
|
|
3235
3222
|
await _testsWaitForText('any of:');
|
|
3236
3223
|
|
|
3237
3224
|
// Locate the second blocker from the popover (scroll + flash).
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3225
|
+
let depEntry: HTMLElement | undefined;
|
|
3226
|
+
await waitFor(() => {
|
|
3227
|
+
depEntry = Array.from(document.querySelectorAll('.reqore-menu-item')).find((element) =>
|
|
3228
|
+
element.textContent?.includes('Required Option 5')
|
|
3229
|
+
) as HTMLElement;
|
|
3230
|
+
expect(depEntry).toBeTruthy();
|
|
3231
|
+
});
|
|
3232
|
+
await userEvent.click(depEntry as HTMLElement);
|
|
3242
3233
|
await waitFor(
|
|
3243
3234
|
() =>
|
|
3244
3235
|
expect(
|
|
@@ -3336,7 +3327,8 @@ export const CompactOptionDependsOnOptionInRequiredGroup: Story = {
|
|
|
3336
3327
|
'.readfirst-row[data-field="RequiredOption6"] .options-readfirst-lock-deps'
|
|
3337
3328
|
) as HTMLElement;
|
|
3338
3329
|
await expect(depLock).toBeTruthy();
|
|
3339
|
-
|
|
3330
|
+
// userEvent keeps the dropdown popover open (see note above).
|
|
3331
|
+
await userEvent.click(depLock);
|
|
3340
3332
|
await _testsWaitForText('Unlocked by:');
|
|
3341
3333
|
// A single flat dependency — no "any of:" grouping.
|
|
3342
3334
|
await _testsWaitForTextToNotExist('any of:');
|
|
@@ -3685,7 +3677,9 @@ export const CompactShowcase: Story = {
|
|
|
3685
3677
|
await expect(
|
|
3686
3678
|
document.querySelector('[data-field="chromeIcon"] .options-readfirst-row-icon')
|
|
3687
3679
|
).toBeTruthy();
|
|
3688
|
-
await expect(
|
|
3680
|
+
await expect(
|
|
3681
|
+
document.querySelector('[data-field="chromeImage"] .reqore-icon img')
|
|
3682
|
+
).toBeTruthy();
|
|
3689
3683
|
await waitFor(() => {
|
|
3690
3684
|
// The intent stripe rides the value surface's left border, fed by
|
|
3691
3685
|
// --readfirst-stripe on the field's BLOCK root. This field carries a
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// (the dpqlMockLsp pattern, REST flavour). Each story uses DISTINCT urls:
|
|
9
9
|
// `query()` caches GETs for 5 minutes, so reusing a url across stories would
|
|
10
10
|
// serve another story's cached schema.
|
|
11
|
-
import { StoryObj } from '@storybook/react';
|
|
12
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
11
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
12
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
13
13
|
import { useState } from 'react';
|
|
14
14
|
import { StoryMeta } from '../../../types';
|
|
15
15
|
import { FormEngine } from './FormEngine';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect } from '
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect } from 'storybook/test';
|
|
3
3
|
import { _testsWaitForText } from '../../../../stories/Tests/utils';
|
|
4
4
|
import { StructuredDataView } from './StructuredDataView';
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../types';
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// live server; the IDE's `_testsClickButton` / `_testsSelectItemFromCollection`
|
|
5
5
|
// helpers are inlined here with `@storybook/test` primitives. The count-based
|
|
6
6
|
// assertions (`.expression`, `.expression-and`, `.expression-or`) are preserved.
|
|
7
|
-
import { StoryObj } from '@storybook/react';
|
|
8
|
-
import { expect, fireEvent, fn, userEvent, waitFor, within } from '
|
|
7
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
8
|
+
import { expect, fireEvent, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
9
9
|
import { useState } from 'react';
|
|
10
10
|
import { sleep } from '../../../../../__tests__/utils';
|
|
11
11
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../types';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReqoreControlGroup } from '@qoretechnologies/reqore';
|
|
2
|
-
import { StoryObj } from '@storybook/react';
|
|
3
|
-
import { expect, fireEvent, fn, waitFor, within } from '
|
|
2
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
3
|
+
import { expect, fireEvent, fn, waitFor, within } from 'storybook/test';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
6
6
|
import { NumberFormField } from '../number/Number';
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// The saved-values stories (`StringWithSuggestedValues`,
|
|
9
9
|
// `StringWithSuggestedAndSavedValues`) and the bare `Connection` story
|
|
10
10
|
// (InterfaceSelector) are not ported — IDE-only seams.
|
|
11
|
-
import { StoryObj } from '@storybook/react';
|
|
12
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
11
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
12
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
13
13
|
import jsyaml from 'js-yaml';
|
|
14
14
|
import { useState } from 'react';
|
|
15
15
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { StoryMeta } from '../../../../types';
|
|
5
5
|
import { ByteSizeFormField } from './ByteSize';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { StoryMeta } from '../../../../types';
|
|
5
5
|
import { CronFormField } from './Cron';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { markdown } from '../../../../../mock/fields';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReqoreControlGroup } from '@qoretechnologies/reqore';
|
|
2
|
-
import { StoryObj } from '@storybook/react';
|
|
3
|
-
import { expect, fn, userEvent, waitFor, within } from '
|
|
2
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
3
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
6
6
|
import { NumberFormField } from './Number';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fireEvent, fn } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fireEvent, fn } from 'storybook/test';
|
|
3
3
|
import { useMemo, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import jsyaml from 'js-yaml';
|
|
@@ -155,7 +155,7 @@ export const ValueCanBeRemoved: Story = {
|
|
|
155
155
|
},
|
|
156
156
|
};
|
|
157
157
|
|
|
158
|
-
export const
|
|
158
|
+
export const Json: Story = {
|
|
159
159
|
args: {
|
|
160
160
|
type: 'object',
|
|
161
161
|
dataType: 'json',
|
|
@@ -202,7 +202,7 @@ export const json: Story = {
|
|
|
202
202
|
},
|
|
203
203
|
};
|
|
204
204
|
|
|
205
|
-
export const
|
|
205
|
+
export const Yaml: Story = {
|
|
206
206
|
args: {
|
|
207
207
|
type: 'object',
|
|
208
208
|
dataType: 'yaml',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, userEvent, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
import { expect, fn, within } from '
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, within } from 'storybook/test';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { StoryMeta } from '../../../../types';
|