@weasel-js/labkit 1.7.1 → 1.7.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/chrome/index.js +4 -4
- package/dist/{chunk-GAHELLJT.js → chunk-RODIY7HI.js} +7 -7
- package/dist/{chunk-GAHELLJT.js.map → chunk-RODIY7HI.js.map} +1 -1
- package/dist/{chunk-4KSC7NXL.js → chunk-U6UQVGFP.js} +1984 -1892
- package/dist/chunk-U6UQVGFP.js.map +1 -0
- package/dist/chunk-WFALF2X2.js +302 -0
- package/dist/chunk-WFALF2X2.js.map +1 -0
- package/dist/{chunk-JFOJESJF.js → chunk-WWJDPNZZ.js} +22 -22
- package/dist/chunk-WWJDPNZZ.js.map +1 -0
- package/dist/{chunk-CEGFXTBD.js → chunk-XRX5S5NT.js} +4 -4
- package/dist/{chunk-CEGFXTBD.js.map → chunk-XRX5S5NT.js.map} +1 -1
- package/dist/{chunk-FB4MIZOO.js → chunk-XZDCEMEL.js} +6 -6
- package/dist/chunk-XZDCEMEL.js.map +1 -0
- package/dist/controls/index.d.ts +55 -3
- package/dist/controls/index.js +3 -2
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +135 -134
- package/dist/index.js.map +1 -1
- package/dist/layers/index.js +1 -1
- package/dist/passthrough/weasel-ui.js +1 -1
- package/dist/primitives/index.js +3 -3
- package/dist/styles.css +228 -11
- package/package.json +11 -11
- package/src/annotations/capture.browser.test.ts +9 -3
- package/src/canvas/Stage.test.tsx +34 -25
- package/src/chrome/labRegions.test.tsx +37 -26
- package/src/chrome/regions/PaletteRegion.test.tsx +2 -2
- package/src/controls/ControlMatrix.less +245 -0
- package/src/controls/ControlMatrix.stories.less +13 -0
- package/src/controls/ControlMatrix.stories.tsx +135 -0
- package/src/controls/ControlMatrix.test.tsx +206 -0
- package/src/controls/ControlMatrix.tsx +446 -0
- package/src/controls/ControlPanel.tsx +4 -2
- package/src/controls/index.ts +6 -0
- package/src/dragdrop/dragDrop.test.tsx +34 -33
- package/src/index.ts +6 -0
- package/src/lab/Lab.chrome.test.tsx +15 -10
- package/src/lab/Lab.nebula.test.tsx +5 -5
- package/src/lab/Lab.surface.test.tsx +30 -21
- package/src/lab/Lab.test.tsx +75 -74
- package/src/lab/Lab.undock.test.tsx +15 -10
- package/src/lab/LabHeader.test.tsx +15 -14
- package/src/lab/LabPalette.test.tsx +12 -7
- package/src/lab/LabShell.less +1 -2
- package/src/lab/LabZoom.test.tsx +55 -44
- package/src/lab/Workspace.surface.test.tsx +16 -13
- package/src/lab/Workspace.test.tsx +32 -27
- package/src/overview/OverviewMarks.test.tsx +9 -8
- package/src/overview/TrialOverview.test.tsx +18 -17
- package/src/primitives/FpsMeter.less +1 -2
- package/src/primitives/JobProgress.less +1 -2
- package/src/primitives/ScaleIndicator.less +1 -1
- package/src/primitives/StatusBar.less +1 -1
- package/src/specimen/Specimen.less +1 -0
- package/src/styles.less +3 -0
- package/src/trial/Trial.annotations.persist.test.tsx +20 -9
- package/src/trial/Trial.annotations.test.tsx +46 -41
- package/src/trial/Trial.canvas.test.tsx +21 -17
- package/src/trial/Trial.config.test.tsx +34 -27
- package/src/trial/Trial.loupe.test.tsx +27 -18
- package/src/trial/Trial.targets.test.tsx +9 -8
- package/src/trial/Trial.test.tsx +51 -46
- package/src/trial/Trial.trialId.test.tsx +7 -6
- package/dist/chunk-4KSC7NXL.js.map +0 -1
- package/dist/chunk-FB4MIZOO.js.map +0 -1
- package/dist/chunk-JFOJESJF.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { act, fireEvent,
|
|
1
|
+
import { act, fireEvent, screen } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { renderSettled } from '@weasel-js/react/testing/renderSettled';
|
|
3
4
|
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
|
4
5
|
import { defineInstrument } from '../instrument/defineInstrument';
|
|
5
6
|
import { Lab } from '../lab/Lab';
|
|
@@ -53,27 +54,29 @@ function pointAt(host: Element, x: number, y: number): void {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
describe('a lens the instrument mounts', () => {
|
|
56
|
-
it('gives a trial a toolbar toggle, and no lens until it is on', () => {
|
|
57
|
-
const { container } =
|
|
57
|
+
it('gives a trial a toolbar toggle, and no lens until it is on', async () => {
|
|
58
|
+
const { container } = await renderSettled(
|
|
58
59
|
<Lab instruments={[canvasInstrument]} defaultInstrument="Drawn" />,
|
|
59
60
|
);
|
|
60
61
|
expect(screen.getByRole('button', { name: 'Loupe' })).toHaveAttribute('aria-pressed', 'false');
|
|
61
62
|
expect(lens(container)).toBeNull();
|
|
62
63
|
});
|
|
63
64
|
|
|
64
|
-
it('offers nothing to an instrument that mounts none', () => {
|
|
65
|
-
|
|
65
|
+
it('offers nothing to an instrument that mounts none', async () => {
|
|
66
|
+
await renderSettled(<Lab instruments={[noLoupe]} defaultInstrument="Plain" />);
|
|
66
67
|
expect(screen.queryByRole('button', { name: 'Loupe' })).toBeNull();
|
|
67
68
|
});
|
|
68
69
|
|
|
69
|
-
it('drops out of a trial that suppresses it', () => {
|
|
70
|
-
|
|
70
|
+
it('drops out of a trial that suppresses it', async () => {
|
|
71
|
+
await renderSettled(
|
|
72
|
+
<Lab instruments={[canvasInstrument]} defaultInstrument="Drawn" suppress={['loupe']} />,
|
|
73
|
+
);
|
|
71
74
|
expect(screen.queryByRole('button', { name: 'Loupe' })).toBeNull();
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
it('raises the lens over a canvas stack once it is on and aimed', async () => {
|
|
75
78
|
const user = userEvent.setup();
|
|
76
|
-
const { container } =
|
|
79
|
+
const { container } = await renderSettled(
|
|
77
80
|
<Lab instruments={[canvasInstrument]} defaultInstrument="Drawn" />,
|
|
78
81
|
);
|
|
79
82
|
await user.click(screen.getByRole('button', { name: 'Loupe' }));
|
|
@@ -95,7 +98,9 @@ describe('a lens the instrument mounts', () => {
|
|
|
95
98
|
|
|
96
99
|
it('asks a DOM instrument to draw itself again at the magnified camera', async () => {
|
|
97
100
|
const user = userEvent.setup();
|
|
98
|
-
const { container } =
|
|
101
|
+
const { container } = await renderSettled(
|
|
102
|
+
<Lab instruments={[domInstrument]} defaultInstrument="Written" />,
|
|
103
|
+
);
|
|
99
104
|
await user.click(screen.getByRole('button', { name: 'Loupe' }));
|
|
100
105
|
|
|
101
106
|
const host = container.querySelector('.lk-loupe-host');
|
|
@@ -108,12 +113,14 @@ describe('a lens the instrument mounts', () => {
|
|
|
108
113
|
expect(screen.getByTestId('body')).toBeInTheDocument();
|
|
109
114
|
});
|
|
110
115
|
|
|
111
|
-
it('wraps nothing for an instrument that mounts no lens', () => {
|
|
112
|
-
const { container } =
|
|
116
|
+
it('wraps nothing for an instrument that mounts no lens', async () => {
|
|
117
|
+
const { container } = await renderSettled(
|
|
118
|
+
<Lab instruments={[noLoupe]} defaultInstrument="Plain" />,
|
|
119
|
+
);
|
|
113
120
|
expect(container.querySelector('.lk-loupe-host')).toBeNull();
|
|
114
121
|
});
|
|
115
122
|
|
|
116
|
-
it('raises a lens told `enabled` without the trial toggle', () => {
|
|
123
|
+
it('raises a lens told `enabled` without the trial toggle', async () => {
|
|
117
124
|
const always = defineInstrument<Record<string, never>, Record<string, never>>({
|
|
118
125
|
name: 'Always',
|
|
119
126
|
defaultConfig: () => ({}),
|
|
@@ -121,7 +128,9 @@ describe('a lens the instrument mounts', () => {
|
|
|
121
128
|
render: () => <TrialLoupe enabled />,
|
|
122
129
|
canvas: { layers: [{ id: 'main', draw: () => undefined }] },
|
|
123
130
|
});
|
|
124
|
-
const { container } =
|
|
131
|
+
const { container } = await renderSettled(
|
|
132
|
+
<Lab instruments={[always]} defaultInstrument="Always" />,
|
|
133
|
+
);
|
|
125
134
|
const stack = container.querySelector('.lk-canvas-stack');
|
|
126
135
|
if (!stack) throw new Error('no canvas stack');
|
|
127
136
|
pointAt(stack, 60, 40);
|
|
@@ -130,7 +139,7 @@ describe('a lens the instrument mounts', () => {
|
|
|
130
139
|
|
|
131
140
|
it('puts the lens away again when the toggle goes off', async () => {
|
|
132
141
|
const user = userEvent.setup();
|
|
133
|
-
const { container } =
|
|
142
|
+
const { container } = await renderSettled(
|
|
134
143
|
<Lab instruments={[canvasInstrument]} defaultInstrument="Drawn" />,
|
|
135
144
|
);
|
|
136
145
|
const toggle = screen.getByRole('button', { name: 'Loupe' });
|
|
@@ -148,7 +157,7 @@ describe('a lens the instrument mounts', () => {
|
|
|
148
157
|
describe('the loupe and the trial camera share one dispatcher', () => {
|
|
149
158
|
const frame = () => new Promise<void>((r) => requestAnimationFrame(() => r()));
|
|
150
159
|
|
|
151
|
-
function mountDrawn() {
|
|
160
|
+
async function mountDrawn() {
|
|
152
161
|
const zooms: number[] = [];
|
|
153
162
|
const drawn = defineInstrument<Record<string, never>, Record<string, never>>({
|
|
154
163
|
name: 'Zoomed',
|
|
@@ -166,7 +175,7 @@ describe('the loupe and the trial camera share one dispatcher', () => {
|
|
|
166
175
|
],
|
|
167
176
|
},
|
|
168
177
|
});
|
|
169
|
-
const r =
|
|
178
|
+
const r = await renderSettled(<Lab instruments={[drawn]} defaultInstrument="Zoomed" />);
|
|
170
179
|
const stack = r.container.querySelector('.lk-canvas-stack');
|
|
171
180
|
if (!stack) throw new Error('no canvas stack');
|
|
172
181
|
return { ...r, stack, zooms };
|
|
@@ -185,7 +194,7 @@ describe('the loupe and the trial camera share one dispatcher', () => {
|
|
|
185
194
|
};
|
|
186
195
|
|
|
187
196
|
it('zooms the camera while the lens is down', async () => {
|
|
188
|
-
const h = mountDrawn();
|
|
197
|
+
const h = await mountDrawn();
|
|
189
198
|
await act(async () => {
|
|
190
199
|
await frame();
|
|
191
200
|
});
|
|
@@ -198,7 +207,7 @@ describe('the loupe and the trial camera share one dispatcher', () => {
|
|
|
198
207
|
|
|
199
208
|
it('gives the wheel to the lens while it is up, and leaves the camera alone', async () => {
|
|
200
209
|
const user = userEvent.setup();
|
|
201
|
-
const h = mountDrawn();
|
|
210
|
+
const h = await mountDrawn();
|
|
202
211
|
await user.click(screen.getByRole('button', { name: 'Loupe' }));
|
|
203
212
|
pointAt(h.stack, 60, 40);
|
|
204
213
|
expect(lens(h.container)).not.toBeNull();
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* trial open, a `targets` that ignored the trial it was asked about would look
|
|
5
5
|
* identical.
|
|
6
6
|
*/
|
|
7
|
-
import { act, fireEvent,
|
|
7
|
+
import { act, fireEvent, screen } from '@testing-library/react';
|
|
8
|
+
import { renderSettled } from '@weasel-js/react/testing/renderSettled';
|
|
8
9
|
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
9
10
|
import type { AnnotationTarget } from '../annotations/types';
|
|
10
11
|
import { defineInstrument } from '../instrument/defineInstrument';
|
|
@@ -63,13 +64,13 @@ function CaptureLab() {
|
|
|
63
64
|
);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
function mountTwoTrials(): [string, string] {
|
|
67
|
-
|
|
67
|
+
async function mountTwoTrials(): Promise<[string, string]> {
|
|
68
|
+
await renderSettled(
|
|
68
69
|
<Lab instruments={[subject]} defaultInstrument="Subject">
|
|
69
70
|
<CaptureLab />
|
|
70
71
|
</Lab>,
|
|
71
72
|
);
|
|
72
|
-
act(() => labRef?.addTrial('Subject'));
|
|
73
|
+
await act(async () => labRef?.addTrial('Subject'));
|
|
73
74
|
const ids = labRef?.trials.map((t) => t.id) ?? [];
|
|
74
75
|
const [a, b] = ids;
|
|
75
76
|
if (!a || !b) throw new Error('expected two trials');
|
|
@@ -82,13 +83,13 @@ describe('annotations.targets', () => {
|
|
|
82
83
|
labRef = null;
|
|
83
84
|
});
|
|
84
85
|
|
|
85
|
-
it('is told which trial is asking', () => {
|
|
86
|
-
const [a, b] = mountTwoTrials();
|
|
86
|
+
it('is told which trial is asking', async () => {
|
|
87
|
+
const [a, b] = await mountTwoTrials();
|
|
87
88
|
expect(new Set(asked.map((t) => t.id))).toEqual(new Set([a, b]));
|
|
88
89
|
});
|
|
89
90
|
|
|
90
|
-
it("is told that trial's own view, not the other's", () => {
|
|
91
|
-
const [a, b] = mountTwoTrials();
|
|
91
|
+
it("is told that trial's own view, not the other's", async () => {
|
|
92
|
+
const [a, b] = await mountTwoTrials();
|
|
92
93
|
fireEvent.click(screen.getByTestId(`zoom-${a}`));
|
|
93
94
|
expect(lastAsk(a).view).toEqual({ zoom: 3, pan: { x: 0, y: 0 } });
|
|
94
95
|
expect(lastAsk(b).view).toEqual({ zoom: 1, pan: { x: 0, y: 0 } });
|
package/src/trial/Trial.test.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { fireEvent,
|
|
1
|
+
import { fireEvent, screen, within } from '@testing-library/react';
|
|
2
|
+
import { renderSettled } from '@weasel-js/react/testing/renderSettled';
|
|
2
3
|
import { type ReactNode, useState } from 'react';
|
|
3
4
|
import { describe, expect, it, vi } from 'vitest';
|
|
4
5
|
import { useStore } from 'zustand/react';
|
|
@@ -102,19 +103,19 @@ function ChromeFromStore({
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
describe('<TrialChrome>', () => {
|
|
105
|
-
it('renders children in the content area', () => {
|
|
106
|
-
|
|
106
|
+
it('renders children in the content area', async () => {
|
|
107
|
+
await renderSettled(<ChromeHarness />);
|
|
107
108
|
expect(screen.getByTestId('content')).toBeInTheDocument();
|
|
108
109
|
});
|
|
109
110
|
|
|
110
|
-
it('renders the built-in trial actions', () => {
|
|
111
|
-
|
|
111
|
+
it('renders the built-in trial actions', async () => {
|
|
112
|
+
await renderSettled(<ChromeHarness />);
|
|
112
113
|
expect(screen.getByRole('button', { name: 'Close trial' })).toBeInTheDocument();
|
|
113
114
|
expect(screen.getByRole('button', { name: 'Clone trial' })).toBeInTheDocument();
|
|
114
115
|
});
|
|
115
116
|
|
|
116
|
-
it('puts clone, reset and snapshot at the end of the title bar, beside close', () => {
|
|
117
|
-
const { container } =
|
|
117
|
+
it('puts clone, reset and snapshot at the end of the title bar, beside close', async () => {
|
|
118
|
+
const { container } = await renderSettled(<ChromeHarness />);
|
|
118
119
|
const titlebar = container.querySelector('.lk-trial__titlebar');
|
|
119
120
|
if (!titlebar) throw new Error('no title bar');
|
|
120
121
|
expect(titlebar).toContainElement(screen.getByRole('button', { name: 'Clone trial' }));
|
|
@@ -125,15 +126,15 @@ describe('<TrialChrome>', () => {
|
|
|
125
126
|
expect(labels).toEqual(['Clone trial', 'Reset trial', 'Save snapshot', 'Close trial']);
|
|
126
127
|
});
|
|
127
128
|
|
|
128
|
-
it('disables close on the last trial', () => {
|
|
129
|
-
|
|
129
|
+
it('disables close on the last trial', async () => {
|
|
130
|
+
await renderSettled(<ChromeHarness isLastTrial />);
|
|
130
131
|
expect(screen.getByRole('button', { name: /close/i })).toBeDisabled();
|
|
131
132
|
});
|
|
132
133
|
|
|
133
|
-
it('omits undo and redo unless the instrument declares undo', () => {
|
|
134
|
-
|
|
134
|
+
it('omits undo and redo unless the instrument declares undo', async () => {
|
|
135
|
+
await renderSettled(<ChromeHarness />);
|
|
135
136
|
expect(screen.queryByRole('button', { name: 'Undo' })).toBeNull();
|
|
136
|
-
|
|
137
|
+
await renderSettled(
|
|
137
138
|
<ChromeHarness
|
|
138
139
|
instrument={{ ...stubInstrument, undo: {} }}
|
|
139
140
|
undoBindings={{ canUndo: true, canRedo: false, undo: vi.fn(), redo: vi.fn() }}
|
|
@@ -143,7 +144,7 @@ describe('<TrialChrome>', () => {
|
|
|
143
144
|
expect(screen.getByRole('button', { name: 'Redo' })).toBeDisabled();
|
|
144
145
|
});
|
|
145
146
|
|
|
146
|
-
it('offers the snapshot loader once a snapshot exists', () => {
|
|
147
|
+
it('offers the snapshot loader once a snapshot exists', async () => {
|
|
147
148
|
const snapshot: SavedSnapshot = {
|
|
148
149
|
id: 's1',
|
|
149
150
|
name: 'First',
|
|
@@ -153,17 +154,19 @@ describe('<TrialChrome>', () => {
|
|
|
153
154
|
state: {},
|
|
154
155
|
savedAt: 1,
|
|
155
156
|
};
|
|
156
|
-
|
|
157
|
+
await renderSettled(<ChromeHarness labOverrides={{ savedSnapshots: [snapshot] }} />);
|
|
157
158
|
expect(screen.getByRole('button', { name: /load snapshot/i })).toBeInTheDocument();
|
|
158
159
|
});
|
|
159
160
|
|
|
160
|
-
it('renders a consumer contribution alongside the built-ins', () => {
|
|
161
|
-
|
|
161
|
+
it('renders a consumer contribution alongside the built-ins', async () => {
|
|
162
|
+
await renderSettled(
|
|
163
|
+
<ChromeHarness chrome={[{ id: 'mine', region: 'status', item: { text: 'ready' } }]} />,
|
|
164
|
+
);
|
|
162
165
|
expect(screen.getByText('ready')).toBeInTheDocument();
|
|
163
166
|
});
|
|
164
167
|
|
|
165
|
-
it('leads the title bar with a contribution that does not set `end`', () => {
|
|
166
|
-
const { container } =
|
|
168
|
+
it('leads the title bar with a contribution that does not set `end`', async () => {
|
|
169
|
+
const { container } = await renderSettled(
|
|
167
170
|
<ChromeHarness
|
|
168
171
|
chrome={[
|
|
169
172
|
{
|
|
@@ -183,8 +186,8 @@ describe('<TrialChrome>', () => {
|
|
|
183
186
|
expect(lead.compareDocumentPosition(heading) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
184
187
|
});
|
|
185
188
|
|
|
186
|
-
it('reads the instrument name until a contribution calls setTitle', () => {
|
|
187
|
-
|
|
189
|
+
it('reads the instrument name until a contribution calls setTitle', async () => {
|
|
190
|
+
await renderSettled(
|
|
188
191
|
<ChromeHarness
|
|
189
192
|
chrome={[
|
|
190
193
|
{
|
|
@@ -205,9 +208,9 @@ describe('<TrialChrome>', () => {
|
|
|
205
208
|
expect(screen.getByRole('region', { name: 'Trial Sprocket 7' })).toBeInTheDocument();
|
|
206
209
|
});
|
|
207
210
|
|
|
208
|
-
it("reads the instrument's title over its name, and returns to it on setTitle(null)", () => {
|
|
211
|
+
it("reads the instrument's title over its name, and returns to it on setTitle(null)", async () => {
|
|
209
212
|
const titled: Instrument = { ...stubInstrument, title: 'Stub / Default' };
|
|
210
|
-
|
|
213
|
+
await renderSettled(
|
|
211
214
|
<ChromeHarness
|
|
212
215
|
instrument={titled}
|
|
213
216
|
chrome={[
|
|
@@ -232,9 +235,9 @@ describe('<TrialChrome>', () => {
|
|
|
232
235
|
expect(screen.getByRole('region', { name: 'Trial Stub / Default' })).toBeInTheDocument();
|
|
233
236
|
});
|
|
234
237
|
|
|
235
|
-
it('Cmd+S triggers saveSnapshot', () => {
|
|
238
|
+
it('Cmd+S triggers saveSnapshot', async () => {
|
|
236
239
|
const saveSnapshot = vi.fn();
|
|
237
|
-
|
|
240
|
+
await renderSettled(<ChromeHarness labOverrides={{ saveSnapshot }} />);
|
|
238
241
|
const region = screen.getByRole('region', { name: /trial/i });
|
|
239
242
|
fireEvent.keyDown(region, { key: 's', metaKey: true });
|
|
240
243
|
expect(saveSnapshot).toHaveBeenCalledWith('ws-1', undefined);
|
|
@@ -242,30 +245,32 @@ describe('<TrialChrome>', () => {
|
|
|
242
245
|
});
|
|
243
246
|
|
|
244
247
|
describe('chrome regions in a mounted lab', () => {
|
|
245
|
-
function renderLabWith(instrument: Instrument) {
|
|
246
|
-
return
|
|
248
|
+
async function renderLabWith(instrument: Instrument) {
|
|
249
|
+
return renderSettled(
|
|
250
|
+
<Lab title="T" instruments={[instrument]} defaultInstrument={instrument.name} />,
|
|
251
|
+
);
|
|
247
252
|
}
|
|
248
253
|
|
|
249
|
-
it('puts zoom in the viewport region and not in the toolbar', () => {
|
|
250
|
-
renderLabWith({ ...stubInstrument, canvas: { layers: [] }, undo: {} });
|
|
254
|
+
it('puts zoom in the viewport region and not in the toolbar', async () => {
|
|
255
|
+
await renderLabWith({ ...stubInstrument, canvas: { layers: [] }, undo: {} });
|
|
251
256
|
const toolbar = document.querySelector('.lk-trial__toolbar') as HTMLElement;
|
|
252
257
|
const viewport = document.querySelector('.lk-viewport-controls') as HTMLElement;
|
|
253
258
|
expect(within(viewport).getByRole('button', { name: 'Zoom in' })).toBeInTheDocument();
|
|
254
259
|
expect(within(toolbar).queryByRole('button', { name: 'Zoom in' })).toBeNull();
|
|
255
260
|
});
|
|
256
261
|
|
|
257
|
-
it('renders no undo group for an instrument that does not declare undo', () => {
|
|
258
|
-
renderLabWith({ ...stubInstrument, canvas: { layers: [] } });
|
|
262
|
+
it('renders no undo group for an instrument that does not declare undo', async () => {
|
|
263
|
+
await renderLabWith({ ...stubInstrument, canvas: { layers: [] } });
|
|
259
264
|
expect(screen.queryByRole('button', { name: 'Undo' })).toBeNull();
|
|
260
265
|
});
|
|
261
266
|
|
|
262
|
-
it('renders no viewport region for an instrument with no canvas', () => {
|
|
263
|
-
renderLabWith(stubInstrument);
|
|
267
|
+
it('renders no viewport region for an instrument with no canvas', async () => {
|
|
268
|
+
await renderLabWith(stubInstrument);
|
|
264
269
|
expect(document.querySelector('.lk-viewport-controls')).toBeNull();
|
|
265
270
|
});
|
|
266
271
|
|
|
267
|
-
it('Lab provides context for nested TrialChrome', () => {
|
|
268
|
-
renderLabWith(stubInstrument);
|
|
272
|
+
it('Lab provides context for nested TrialChrome', async () => {
|
|
273
|
+
await renderLabWith(stubInstrument);
|
|
269
274
|
expect(document.querySelector('.lk-lab')).toBeTruthy();
|
|
270
275
|
});
|
|
271
276
|
});
|
|
@@ -291,46 +296,46 @@ describe('<TrialChrome> — state that outlives a mount', () => {
|
|
|
291
296
|
},
|
|
292
297
|
];
|
|
293
298
|
|
|
294
|
-
it('keeps a title across a remount', () => {
|
|
299
|
+
it('keeps a title across a remount', async () => {
|
|
295
300
|
const store = makeChromeStore();
|
|
296
|
-
const first =
|
|
301
|
+
const first = await renderSettled(<ChromeHarness store={store} chrome={renameChrome} />);
|
|
297
302
|
fireEvent.click(screen.getByRole('button', { name: 'Rename' }));
|
|
298
303
|
first.unmount();
|
|
299
304
|
|
|
300
|
-
|
|
305
|
+
await renderSettled(<ChromeHarness store={store} chrome={renameChrome} />);
|
|
301
306
|
expect(screen.getByRole('region', { name: 'Trial Sprocket 7' })).toBeInTheDocument();
|
|
302
307
|
});
|
|
303
308
|
|
|
304
|
-
it('keeps a folded sidebar section across a remount', () => {
|
|
309
|
+
it('keeps a folded sidebar section across a remount', async () => {
|
|
305
310
|
const store = makeChromeStore();
|
|
306
|
-
const first =
|
|
311
|
+
const first = await renderSettled(<ChromeHarness store={store} chrome={sectionChrome} />);
|
|
307
312
|
expect(screen.getByTestId('notes-body')).toBeInTheDocument();
|
|
308
313
|
fireEvent.click(screen.getByRole('button', { name: 'Notes' }));
|
|
309
314
|
expect(screen.queryByTestId('notes-body')).toBeNull();
|
|
310
315
|
first.unmount();
|
|
311
316
|
|
|
312
|
-
|
|
317
|
+
await renderSettled(<ChromeHarness store={store} chrome={sectionChrome} />);
|
|
313
318
|
expect(screen.getByRole('button', { name: 'Notes' })).toHaveAttribute('aria-expanded', 'false');
|
|
314
319
|
expect(screen.queryByTestId('notes-body')).toBeNull();
|
|
315
320
|
});
|
|
316
321
|
|
|
317
|
-
it('keeps a folded settings group across a remount', () => {
|
|
322
|
+
it('keeps a folded settings group across a remount', async () => {
|
|
318
323
|
const sectioned: Instrument = {
|
|
319
324
|
...stubInstrument,
|
|
320
325
|
config: f.schema({ size: f.number(1).section('Shape') }),
|
|
321
326
|
};
|
|
322
327
|
const store = makeChromeStore();
|
|
323
|
-
const first =
|
|
328
|
+
const first = await renderSettled(<ChromeHarness store={store} instrument={sectioned} />);
|
|
324
329
|
const twisty = screen.getByRole('button', { name: 'Shape' });
|
|
325
330
|
expect(twisty).toHaveAttribute('aria-expanded', 'true');
|
|
326
331
|
fireEvent.click(twisty);
|
|
327
332
|
first.unmount();
|
|
328
333
|
|
|
329
|
-
|
|
334
|
+
await renderSettled(<ChromeHarness store={store} instrument={sectioned} />);
|
|
330
335
|
expect(screen.getByRole('button', { name: 'Shape' })).toHaveAttribute('aria-expanded', 'false');
|
|
331
336
|
});
|
|
332
337
|
|
|
333
|
-
it('reopens a section that starts collapsed, and keeps it open across a remount', () => {
|
|
338
|
+
it('reopens a section that starts collapsed, and keeps it open across a remount', async () => {
|
|
334
339
|
const collapsedChrome: ChromeProps['chrome'] = [
|
|
335
340
|
{
|
|
336
341
|
id: 'notes',
|
|
@@ -343,12 +348,12 @@ describe('<TrialChrome> — state that outlives a mount', () => {
|
|
|
343
348
|
},
|
|
344
349
|
];
|
|
345
350
|
const store = makeChromeStore();
|
|
346
|
-
const first =
|
|
351
|
+
const first = await renderSettled(<ChromeHarness store={store} chrome={collapsedChrome} />);
|
|
347
352
|
expect(screen.queryByTestId('notes-body')).toBeNull();
|
|
348
353
|
fireEvent.click(screen.getByRole('button', { name: 'Notes' }));
|
|
349
354
|
first.unmount();
|
|
350
355
|
|
|
351
|
-
|
|
356
|
+
await renderSettled(<ChromeHarness store={store} chrome={collapsedChrome} />);
|
|
352
357
|
expect(screen.getByTestId('notes-body')).toBeInTheDocument();
|
|
353
358
|
});
|
|
354
359
|
});
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* `SingletonExperiment` — so `useTrialState()` threw everywhere else, which
|
|
5
5
|
* made the documented hook pattern unreachable from an instrument's `render`.
|
|
6
6
|
*/
|
|
7
|
-
import { act,
|
|
7
|
+
import { act, screen } from '@testing-library/react';
|
|
8
|
+
import { renderSettled } from '@weasel-js/react/testing/renderSettled';
|
|
8
9
|
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
|
9
10
|
import { defineInstrument } from '../instrument/defineInstrument';
|
|
10
11
|
import { Lab } from '../lab/Lab';
|
|
@@ -30,16 +31,16 @@ const reader = defineInstrument<{ hits: number }, Record<string, never>>({
|
|
|
30
31
|
});
|
|
31
32
|
|
|
32
33
|
describe('<Trial> trial-scoped hooks', () => {
|
|
33
|
-
it('lets an instrument read its own trial state through useTrialState', () => {
|
|
34
|
-
|
|
34
|
+
it('lets an instrument read its own trial state through useTrialState', async () => {
|
|
35
|
+
await renderSettled(<Lab instruments={[reader]} defaultInstrument="Reader" />);
|
|
35
36
|
expect(screen.getByTestId('probe')).toHaveTextContent('hits:7');
|
|
36
37
|
});
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
describe('<Trial> root element', () => {
|
|
40
|
-
it('carries its trial id, so a lab can find a trial from outside', () => {
|
|
41
|
+
it('carries its trial id, so a lab can find a trial from outside', async () => {
|
|
41
42
|
let labRef: LabContextValue | null = null;
|
|
42
|
-
const { container } =
|
|
43
|
+
const { container } = await renderSettled(
|
|
43
44
|
<Lab instruments={[reader]} defaultInstrument="Reader">
|
|
44
45
|
<LabContext.Consumer>
|
|
45
46
|
{(value) => {
|
|
@@ -49,7 +50,7 @@ describe('<Trial> root element', () => {
|
|
|
49
50
|
</LabContext.Consumer>
|
|
50
51
|
</Lab>,
|
|
51
52
|
);
|
|
52
|
-
act(() => (labRef as LabContextValue | null)?.addTrial('Reader'));
|
|
53
|
+
await act(async () => (labRef as LabContextValue | null)?.addTrial('Reader'));
|
|
53
54
|
const ids = (labRef as LabContextValue | null)?.trials.map((t) => t.id) ?? [];
|
|
54
55
|
expect(ids).toHaveLength(2);
|
|
55
56
|
const roots = container.querySelectorAll<HTMLElement>('.lk-trial[data-trial-id]');
|