foldkit 0.45.0 → 0.46.1
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/propsModule.d.ts +3 -0
- package/dist/propsModule.d.ts.map +1 -0
- package/dist/propsModule.js +50 -0
- package/dist/test/apps/interactions.d.ts +26 -0
- package/dist/test/apps/interactions.d.ts.map +1 -0
- package/dist/test/apps/interactions.js +59 -0
- package/dist/test/apps/multiRole.d.ts +13 -0
- package/dist/test/apps/multiRole.d.ts.map +1 -0
- package/dist/test/apps/multiRole.js +19 -0
- package/dist/test/matchers.d.ts +26 -2
- package/dist/test/matchers.d.ts.map +1 -1
- package/dist/test/matchers.js +89 -9
- package/dist/test/query.d.ts +111 -11
- package/dist/test/query.d.ts.map +1 -1
- package/dist/test/query.js +262 -33
- package/dist/test/scene.d.ts +77 -8
- package/dist/test/scene.d.ts.map +1 -1
- package/dist/test/scene.js +281 -28
- package/dist/test/vitest-setup.d.ts +0 -17
- package/dist/test/vitest-setup.d.ts.map +1 -1
- package/dist/test/vitest-setup.js +2 -3
- package/dist/test/vitest.d.ts +33 -0
- package/dist/test/vitest.d.ts.map +1 -0
- package/dist/test/vitest.js +16 -0
- package/dist/vdom.d.ts.map +1 -1
- package/dist/vdom.js +2 -1
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propsModule.d.ts","sourceRoot":"","sources":["../src/propsModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AA0DtC,eAAO,MAAM,WAAW,EAAE,MAAqD,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** A custom props module that extends snabbdom's built-in propsModule with
|
|
2
|
+
* proper cleanup of removed properties.
|
|
3
|
+
*
|
|
4
|
+
* Snabbdom's propsModule only iterates over _new_ props — it never resets
|
|
5
|
+
* old props that disappeared between renders. This means `elm.disabled = true`
|
|
6
|
+
* persists even after `Disabled(true)` is removed from the attribute array.
|
|
7
|
+
* Since a disabled button swallows click events at the browser level, an
|
|
8
|
+
* `OnClick` handler that replaces `Disabled` at the same index silently fails.
|
|
9
|
+
*
|
|
10
|
+
* Instead of relying on the old vnode's `data.props` for cleanup (which
|
|
11
|
+
* requires snabbdom to patch rather than recreate), this module tracks which
|
|
12
|
+
* properties it has set on each DOM element via a WeakMap. On every create or
|
|
13
|
+
* update hook, it compares the tracked set against the new vnode's props and
|
|
14
|
+
* resets anything that was removed to its type-appropriate default: booleans →
|
|
15
|
+
* false, strings → '', numbers → 0. The WeakMap entries are garbage-collected
|
|
16
|
+
* when the element is removed from the DOM. */
|
|
17
|
+
const managedProps = new WeakMap();
|
|
18
|
+
function updateProps(_oldVnode, vnode) {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
20
|
+
const elm = vnode.elm;
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
22
|
+
const props = (vnode.data?.props ?? {});
|
|
23
|
+
const previous = managedProps.get(elm) ?? {};
|
|
24
|
+
if (props === previous) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const key in props) {
|
|
28
|
+
const cur = props[key];
|
|
29
|
+
const old = previous[key];
|
|
30
|
+
if (old !== cur && (key !== 'value' || elm[key] !== cur)) {
|
|
31
|
+
elm[key] = cur;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const key in previous) {
|
|
35
|
+
if (!(key in props)) {
|
|
36
|
+
const old = previous[key];
|
|
37
|
+
if (typeof old === 'boolean') {
|
|
38
|
+
elm[key] = false;
|
|
39
|
+
}
|
|
40
|
+
else if (typeof old === 'string') {
|
|
41
|
+
elm[key] = '';
|
|
42
|
+
}
|
|
43
|
+
else if (typeof old === 'number') {
|
|
44
|
+
elm[key] = 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
managedProps.set(elm, { ...props });
|
|
49
|
+
}
|
|
50
|
+
export const propsModule = { create: updateProps, update: updateProps };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Schema as S } from 'effect';
|
|
2
|
+
import { type Html } from '../../html';
|
|
3
|
+
export declare const Model: S.Struct<{
|
|
4
|
+
clicks: typeof S.Number;
|
|
5
|
+
doubleClicks: typeof S.Number;
|
|
6
|
+
hovered: typeof S.Boolean;
|
|
7
|
+
focused: typeof S.Boolean;
|
|
8
|
+
changed: typeof S.String;
|
|
9
|
+
}>;
|
|
10
|
+
export type Model = typeof Model.Type;
|
|
11
|
+
export declare const ClickedButton: import("../../schema").CallableTaggedStruct<"ClickedButton", {}>;
|
|
12
|
+
export declare const DoubleClickedButton: import("../../schema").CallableTaggedStruct<"DoubleClickedButton", {}>;
|
|
13
|
+
export declare const HoveredTarget: import("../../schema").CallableTaggedStruct<"HoveredTarget", {}>;
|
|
14
|
+
export declare const FocusedInput: import("../../schema").CallableTaggedStruct<"FocusedInput", {}>;
|
|
15
|
+
export declare const BlurredInput: import("../../schema").CallableTaggedStruct<"BlurredInput", {}>;
|
|
16
|
+
export declare const ChangedSelect: import("../../schema").CallableTaggedStruct<"ChangedSelect", {
|
|
17
|
+
value: typeof S.String;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"ClickedButton", {}>, import("../../schema").CallableTaggedStruct<"DoubleClickedButton", {}>, import("../../schema").CallableTaggedStruct<"HoveredTarget", {}>, import("../../schema").CallableTaggedStruct<"FocusedInput", {}>, import("../../schema").CallableTaggedStruct<"BlurredInput", {}>, import("../../schema").CallableTaggedStruct<"ChangedSelect", {
|
|
20
|
+
value: typeof S.String;
|
|
21
|
+
}>]>;
|
|
22
|
+
export type Message = typeof Message.Type;
|
|
23
|
+
export declare const initialModel: Model;
|
|
24
|
+
export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<never>];
|
|
25
|
+
export declare const view: (model: Model) => Html;
|
|
26
|
+
//# sourceMappingURL=interactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../../src/test/apps/interactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhD,OAAO,EAAE,KAAK,IAAI,EAAQ,MAAM,YAAY,CAAA;AAK5C,eAAO,MAAM,KAAK;;;;;;EAMhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,mBAAmB,wEAA2B,CAAA;AAC3D,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,YAAY,iEAAoB,CAAA;AAC7C,eAAO,MAAM,YAAY,iEAAoB,CAAA;AAC7C,eAAO,MAAM,aAAa;;EAA0C,CAAA;AAEpE,eAAO,MAAM,OAAO;;IAOnB,CAAA;AACD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAA;AAID,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAcrC,CAAA;AAqBH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IA2BjC,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Match as M, Schema as S } from 'effect';
|
|
2
|
+
import { html } from '../../html';
|
|
3
|
+
import { m } from '../../message';
|
|
4
|
+
// MODEL
|
|
5
|
+
export const Model = S.Struct({
|
|
6
|
+
clicks: S.Number,
|
|
7
|
+
doubleClicks: S.Number,
|
|
8
|
+
hovered: S.Boolean,
|
|
9
|
+
focused: S.Boolean,
|
|
10
|
+
changed: S.String,
|
|
11
|
+
});
|
|
12
|
+
// MESSAGE
|
|
13
|
+
export const ClickedButton = m('ClickedButton');
|
|
14
|
+
export const DoubleClickedButton = m('DoubleClickedButton');
|
|
15
|
+
export const HoveredTarget = m('HoveredTarget');
|
|
16
|
+
export const FocusedInput = m('FocusedInput');
|
|
17
|
+
export const BlurredInput = m('BlurredInput');
|
|
18
|
+
export const ChangedSelect = m('ChangedSelect', { value: S.String });
|
|
19
|
+
export const Message = S.Union(ClickedButton, DoubleClickedButton, HoveredTarget, FocusedInput, BlurredInput, ChangedSelect);
|
|
20
|
+
// INIT
|
|
21
|
+
export const initialModel = {
|
|
22
|
+
clicks: 0,
|
|
23
|
+
doubleClicks: 0,
|
|
24
|
+
hovered: false,
|
|
25
|
+
focused: false,
|
|
26
|
+
changed: '',
|
|
27
|
+
};
|
|
28
|
+
// UPDATE
|
|
29
|
+
export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
|
|
30
|
+
ClickedButton: () => [{ ...model, clicks: model.clicks + 1 }, []],
|
|
31
|
+
DoubleClickedButton: () => [
|
|
32
|
+
{ ...model, doubleClicks: model.doubleClicks + 1 },
|
|
33
|
+
[],
|
|
34
|
+
],
|
|
35
|
+
HoveredTarget: () => [{ ...model, hovered: true }, []],
|
|
36
|
+
FocusedInput: () => [{ ...model, focused: true }, []],
|
|
37
|
+
BlurredInput: () => [{ ...model, focused: false }, []],
|
|
38
|
+
ChangedSelect: ({ value }) => [{ ...model, changed: value }, []],
|
|
39
|
+
}));
|
|
40
|
+
// VIEW
|
|
41
|
+
const { div, button, input, select, option, OnClick, OnDblClick, OnMouseEnter, OnFocus, OnBlur, OnChange, Role, AriaLabel, Value, } = html();
|
|
42
|
+
export const view = (model) => div([], [
|
|
43
|
+
button([
|
|
44
|
+
OnClick(ClickedButton()),
|
|
45
|
+
OnDblClick(DoubleClickedButton()),
|
|
46
|
+
OnMouseEnter(HoveredTarget()),
|
|
47
|
+
AriaLabel('action'),
|
|
48
|
+
], [`clicks=${model.clicks} dbl=${model.doubleClicks}`]),
|
|
49
|
+
input([
|
|
50
|
+
Role('textbox'),
|
|
51
|
+
AriaLabel('name'),
|
|
52
|
+
OnFocus(FocusedInput()),
|
|
53
|
+
OnBlur(BlurredInput()),
|
|
54
|
+
]),
|
|
55
|
+
select([AriaLabel('fruit'), OnChange(value => ChangedSelect({ value }))], [
|
|
56
|
+
option([Value('apple')], ['Apple']),
|
|
57
|
+
option([Value('banana')], ['Banana']),
|
|
58
|
+
]),
|
|
59
|
+
]);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Schema as S } from 'effect';
|
|
2
|
+
import { type Html } from '../../html';
|
|
3
|
+
export declare const Model: S.Struct<{
|
|
4
|
+
clicks: typeof S.Number;
|
|
5
|
+
}>;
|
|
6
|
+
export type Model = typeof Model.Type;
|
|
7
|
+
export declare const ClickedFallback: import("../../schema").CallableTaggedStruct<"ClickedFallback", {}>;
|
|
8
|
+
export declare const Message: import("../../schema").CallableTaggedStruct<"ClickedFallback", {}>;
|
|
9
|
+
export type Message = typeof Message.Type;
|
|
10
|
+
export declare const initialModel: Model;
|
|
11
|
+
export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<never>];
|
|
12
|
+
export declare const view: (model: Model) => Html;
|
|
13
|
+
//# sourceMappingURL=multiRole.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiRole.d.ts","sourceRoot":"","sources":["../../../src/test/apps/multiRole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhD,OAAO,EAAE,KAAK,IAAI,EAAQ,MAAM,YAAY,CAAA;AAK5C,eAAO,MAAM,KAAK;;EAAiC,CAAA;AACnD,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,OAAO,oEAA2B,CAAA;AAC/C,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY,EAAE,KAAqB,CAAA;AAIhD,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAMrC,CAAA;AAMH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IASjC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Match as M, Schema as S } from 'effect';
|
|
2
|
+
import { html } from '../../html';
|
|
3
|
+
import { m } from '../../message';
|
|
4
|
+
// MODEL
|
|
5
|
+
export const Model = S.Struct({ clicks: S.Number });
|
|
6
|
+
// MESSAGE
|
|
7
|
+
export const ClickedFallback = m('ClickedFallback');
|
|
8
|
+
export const Message = S.Union(ClickedFallback);
|
|
9
|
+
// INIT
|
|
10
|
+
export const initialModel = { clicks: 0 };
|
|
11
|
+
// UPDATE
|
|
12
|
+
export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
|
|
13
|
+
ClickedFallback: () => [{ ...model, clicks: model.clicks + 1 }, []],
|
|
14
|
+
}));
|
|
15
|
+
// VIEW
|
|
16
|
+
const { div, OnClick, Role } = html();
|
|
17
|
+
export const view = (model) => div([], [
|
|
18
|
+
div([Role('doc-subtitle heading'), OnClick(ClickedFallback())], [`Fallback element clicks=${model.clicks}`]),
|
|
19
|
+
]);
|
package/dist/test/matchers.d.ts
CHANGED
|
@@ -2,14 +2,14 @@ import { Option } from 'effect';
|
|
|
2
2
|
import type { VNode } from '../vdom';
|
|
3
3
|
/** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
|
|
4
4
|
export declare const sceneMatchers: {
|
|
5
|
-
toHaveText(received: Option.Option<VNode>, expected: string): {
|
|
5
|
+
toHaveText(received: Option.Option<VNode>, expected: string | RegExp): {
|
|
6
6
|
pass: boolean;
|
|
7
7
|
message: () => string;
|
|
8
8
|
} | {
|
|
9
9
|
pass: boolean;
|
|
10
10
|
message: () => string;
|
|
11
11
|
};
|
|
12
|
-
toContainText(received: Option.Option<VNode>, expected: string): {
|
|
12
|
+
toContainText(received: Option.Option<VNode>, expected: string | RegExp): {
|
|
13
13
|
pass: boolean;
|
|
14
14
|
message: () => string;
|
|
15
15
|
} | {
|
|
@@ -83,6 +83,30 @@ export declare const sceneMatchers: {
|
|
|
83
83
|
pass: boolean;
|
|
84
84
|
message: () => "Expected element not to be enabled but it is." | "Expected element to be enabled but it is disabled.";
|
|
85
85
|
};
|
|
86
|
+
toBeEmpty(received: Option.Option<VNode>): {
|
|
87
|
+
pass: boolean;
|
|
88
|
+
message: () => "Expected element to be empty but the element does not exist.";
|
|
89
|
+
} | {
|
|
90
|
+
pass: boolean;
|
|
91
|
+
message: () => string;
|
|
92
|
+
};
|
|
93
|
+
toBeVisible(received: Option.Option<VNode>): {
|
|
94
|
+
pass: boolean;
|
|
95
|
+
message: () => "Expected element to be visible but the element does not exist.";
|
|
96
|
+
} | {
|
|
97
|
+
pass: boolean;
|
|
98
|
+
message: () => "Expected element not to be visible but it is." | "Expected element to be visible but it is hidden.";
|
|
99
|
+
};
|
|
100
|
+
toHaveId(received: Option.Option<VNode>, expected: string): {
|
|
101
|
+
pass: boolean;
|
|
102
|
+
message: () => string;
|
|
103
|
+
} | {
|
|
104
|
+
pass: false;
|
|
105
|
+
message: () => string;
|
|
106
|
+
} | {
|
|
107
|
+
pass: boolean;
|
|
108
|
+
message: () => string;
|
|
109
|
+
};
|
|
86
110
|
toBeChecked(received: Option.Option<VNode>): {
|
|
87
111
|
pass: boolean;
|
|
88
112
|
message: () => "Expected element to be checked but the element does not exist.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/test/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/test/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,QAAQ,CAAA;AAElD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAcpC,oGAAoG;AACpG,eAAO,MAAM,aAAa;yBACH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,GAAG,MAAM;;;;;;;4BAqB5C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,GAAG,MAAM;;;;;;;0BAqBjD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;yBAmBhD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QACxB,MAAM,kBACI,MAAM;;;;;;;sBA2CN,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;yBAWjB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;0BAY7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QACxB,MAAM,kBACI,MAAM;;;;;;;yBA8CH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,MAAM;;;;;;;4BAsB/B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,MAAM;;;;;;;0BAkBpC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;;;;2BA4BrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;0BAyBrB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;wBAyBtB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;uBAgBnB,MAAM;;0BAUL,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;uBAiCvB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;;;;0BA4BnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;CAwB3C,CAAA"}
|
package/dist/test/matchers.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { Option } from 'effect';
|
|
1
|
+
import { Option, String as String_ } from 'effect';
|
|
2
2
|
import { attr, textContent } from './query';
|
|
3
|
+
const describeExpected = (expected) => expected instanceof RegExp ? `${expected}` : `"${expected}"`;
|
|
4
|
+
const textMatches = (value, expected) => expected instanceof RegExp ? expected.test(value) : value === expected;
|
|
5
|
+
const textIncludes = (value, expected) => expected instanceof RegExp ? expected.test(value) : value.includes(expected);
|
|
3
6
|
/** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
|
|
4
7
|
export const sceneMatchers = {
|
|
5
8
|
toHaveText(received, expected) {
|
|
6
9
|
return Option.match(received, {
|
|
7
10
|
onNone: () => ({
|
|
8
11
|
pass: false,
|
|
9
|
-
message: () => `Expected element to have text
|
|
12
|
+
message: () => `Expected element to have text ${describeExpected(expected)} but the element does not exist.`,
|
|
10
13
|
}),
|
|
11
14
|
onSome: vnode => {
|
|
12
15
|
const actualText = textContent(vnode);
|
|
13
16
|
return {
|
|
14
|
-
pass: actualText
|
|
17
|
+
pass: textMatches(actualText, expected),
|
|
15
18
|
message: () =>
|
|
16
19
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
17
20
|
this.isNot
|
|
18
|
-
? `Expected element not to have text
|
|
19
|
-
: `Expected element to have text
|
|
21
|
+
? `Expected element not to have text ${describeExpected(expected)} but it does.`
|
|
22
|
+
: `Expected element to have text ${describeExpected(expected)} but received "${actualText}".`,
|
|
20
23
|
};
|
|
21
24
|
},
|
|
22
25
|
});
|
|
@@ -25,17 +28,17 @@ export const sceneMatchers = {
|
|
|
25
28
|
return Option.match(received, {
|
|
26
29
|
onNone: () => ({
|
|
27
30
|
pass: false,
|
|
28
|
-
message: () => `Expected element to contain text
|
|
31
|
+
message: () => `Expected element to contain text ${describeExpected(expected)} but the element does not exist.`,
|
|
29
32
|
}),
|
|
30
33
|
onSome: vnode => {
|
|
31
34
|
const actualText = textContent(vnode);
|
|
32
35
|
return {
|
|
33
|
-
pass: actualText
|
|
36
|
+
pass: textIncludes(actualText, expected),
|
|
34
37
|
message: () =>
|
|
35
38
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
36
39
|
this.isNot
|
|
37
|
-
? `Expected element not to contain text
|
|
38
|
-
: `Expected element to contain text
|
|
40
|
+
? `Expected element not to contain text ${describeExpected(expected)} but it does.`
|
|
41
|
+
: `Expected element to contain text ${describeExpected(expected)} but received "${actualText}".`,
|
|
39
42
|
};
|
|
40
43
|
},
|
|
41
44
|
});
|
|
@@ -258,6 +261,83 @@ export const sceneMatchers = {
|
|
|
258
261
|
},
|
|
259
262
|
});
|
|
260
263
|
},
|
|
264
|
+
toBeEmpty(received) {
|
|
265
|
+
return Option.match(received, {
|
|
266
|
+
onNone: () => ({
|
|
267
|
+
pass: false,
|
|
268
|
+
message: () => 'Expected element to be empty but the element does not exist.',
|
|
269
|
+
}),
|
|
270
|
+
onSome: vnode => {
|
|
271
|
+
const childCount = (vnode.children ?? []).length;
|
|
272
|
+
const text = textContent(vnode);
|
|
273
|
+
const pass = String_.isEmpty(text) && childCount === 0;
|
|
274
|
+
const actual = String_.isNonEmpty(text)
|
|
275
|
+
? `received text "${text}"`
|
|
276
|
+
: `received ${childCount} child(ren)`;
|
|
277
|
+
return {
|
|
278
|
+
pass,
|
|
279
|
+
message: () =>
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
281
|
+
this.isNot
|
|
282
|
+
? 'Expected element not to be empty but it is.'
|
|
283
|
+
: `Expected element to be empty but ${actual}.`,
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
},
|
|
288
|
+
toBeVisible(received) {
|
|
289
|
+
return Option.match(received, {
|
|
290
|
+
onNone: () => ({
|
|
291
|
+
pass: false,
|
|
292
|
+
message: () => 'Expected element to be visible but the element does not exist.',
|
|
293
|
+
}),
|
|
294
|
+
onSome: vnode => {
|
|
295
|
+
const hiddenAttr = attr(vnode, 'hidden');
|
|
296
|
+
const hiddenByAttr = Option.isSome(hiddenAttr) && hiddenAttr.value !== 'false';
|
|
297
|
+
const ariaHidden = attr(vnode, 'aria-hidden');
|
|
298
|
+
const hiddenByAria = Option.isSome(ariaHidden) && ariaHidden.value === 'true';
|
|
299
|
+
const display = vnode.data?.style?.['display'];
|
|
300
|
+
const visibility = vnode.data?.style?.['visibility'];
|
|
301
|
+
const isHidden = hiddenByAttr ||
|
|
302
|
+
hiddenByAria ||
|
|
303
|
+
display === 'none' ||
|
|
304
|
+
visibility === 'hidden';
|
|
305
|
+
return {
|
|
306
|
+
pass: !isHidden,
|
|
307
|
+
message: () =>
|
|
308
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
309
|
+
this.isNot
|
|
310
|
+
? 'Expected element not to be visible but it is.'
|
|
311
|
+
: 'Expected element to be visible but it is hidden.',
|
|
312
|
+
};
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
},
|
|
316
|
+
toHaveId(received, expected) {
|
|
317
|
+
return Option.match(received, {
|
|
318
|
+
onNone: () => ({
|
|
319
|
+
pass: false,
|
|
320
|
+
message: () => `Expected element to have id "${expected}" but the element does not exist.`,
|
|
321
|
+
}),
|
|
322
|
+
onSome: vnode => {
|
|
323
|
+
const actualId = attr(vnode, 'id');
|
|
324
|
+
return Option.match(actualId, {
|
|
325
|
+
onNone: () => ({
|
|
326
|
+
pass: false,
|
|
327
|
+
message: () => `Expected element to have id "${expected}" but the element has no id.`,
|
|
328
|
+
}),
|
|
329
|
+
onSome: actual => ({
|
|
330
|
+
pass: actual === expected,
|
|
331
|
+
message: () =>
|
|
332
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
333
|
+
this.isNot
|
|
334
|
+
? `Expected element not to have id "${expected}" but it does.`
|
|
335
|
+
: `Expected element to have id "${expected}" but received "${actual}".`,
|
|
336
|
+
}),
|
|
337
|
+
});
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
},
|
|
261
341
|
toBeChecked(received) {
|
|
262
342
|
return Option.match(received, {
|
|
263
343
|
onNone: () => ({
|
package/dist/test/query.d.ts
CHANGED
|
@@ -14,6 +14,16 @@ type SimpleSelector = Readonly<{
|
|
|
14
14
|
}>;
|
|
15
15
|
type Selector = ReadonlyArray<SimpleSelector>;
|
|
16
16
|
export declare const parseSelector: (input: string) => Selector;
|
|
17
|
+
/** Returns the ancestor chain of `target` within `root`, ordered from root to
|
|
18
|
+
* the immediate parent of `target` (exclusive). Returns an empty array when
|
|
19
|
+
* `target` is `root` itself or is not present in the subtree. */
|
|
20
|
+
export declare const ancestorsOf: (root: VNode, target: VNode) => ReadonlyArray<VNode>;
|
|
21
|
+
/** Computes the accessible name of an element. Resolves via
|
|
22
|
+
* `aria-labelledby`, `aria-label`, `<label for>`, text content, then `title`. */
|
|
23
|
+
export declare const accessibleName: (root: VNode) => (vnode: VNode) => string;
|
|
24
|
+
/** Computes the accessible description of an element. Resolves via
|
|
25
|
+
* `aria-describedby` (joining referenced elements' text content). */
|
|
26
|
+
export declare const accessibleDescription: (root: VNode) => (vnode: VNode) => string;
|
|
17
27
|
/** Finds the first VNode matching the CSS selector. */
|
|
18
28
|
export declare const find: {
|
|
19
29
|
(html: VNode, selectorString: string): Option.Option<VNode>;
|
|
@@ -31,14 +41,21 @@ export declare const attr: {
|
|
|
31
41
|
(vnode: VNode, name: string): Option.Option<string>;
|
|
32
42
|
(name: string): (vnode: VNode) => Option.Option<string>;
|
|
33
43
|
};
|
|
34
|
-
|
|
35
|
-
export declare const getByRole: (role: string, options?: Readonly<{
|
|
44
|
+
type RoleOptions = Readonly<{
|
|
36
45
|
name?: string;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
level?: number;
|
|
47
|
+
checked?: boolean | 'mixed';
|
|
48
|
+
selected?: boolean;
|
|
49
|
+
pressed?: boolean | 'mixed';
|
|
50
|
+
expanded?: boolean;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
/** Finds the first element with the given ARIA role and optional matching options.
|
|
54
|
+
* Supports `name` (accessible name), `level` (heading level), `checked`,
|
|
55
|
+
* `selected`, `pressed`, `expanded`, and `disabled` state filters. */
|
|
56
|
+
export declare const getByRole: (role: string, options?: RoleOptions) => (html: VNode) => Option.Option<VNode>;
|
|
57
|
+
/** Finds all elements with the given ARIA role and optional matching options. */
|
|
58
|
+
export declare const getAllByRole: (role: string, options?: RoleOptions) => (html: VNode) => ReadonlyArray<VNode>;
|
|
42
59
|
/** Finds the most specific element matching the given text content.
|
|
43
60
|
* Skips text VNodes (sel undefined) — only returns actual DOM elements. */
|
|
44
61
|
export declare const getByText: (target: string, options?: Readonly<{
|
|
@@ -50,6 +67,34 @@ export declare const getByPlaceholder: (placeholderValue: string) => (html: VNod
|
|
|
50
67
|
* first, then `<label for="id">` association, then `<label>` nesting,
|
|
51
68
|
* then `aria-labelledby` reverse lookup. */
|
|
52
69
|
export declare const getByLabel: (labelValue: string) => (html: VNode) => Option.Option<VNode>;
|
|
70
|
+
/** Finds every element with the given label text. Applies the same four
|
|
71
|
+
* resolution strategies as `getByLabel` (`aria-label`, `<label for="id">`,
|
|
72
|
+
* `<label>` nesting, `aria-labelledby`) and returns deduplicated matches. */
|
|
73
|
+
export declare const getAllByLabel: (labelValue: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
74
|
+
/** Finds the first element with the given `alt` attribute. */
|
|
75
|
+
export declare const getByAltText: (altValue: string) => (html: VNode) => Option.Option<VNode>;
|
|
76
|
+
/** Finds the first element with the given `title` attribute. */
|
|
77
|
+
export declare const getByTitle: (titleValue: string) => (html: VNode) => Option.Option<VNode>;
|
|
78
|
+
/** Finds the first element with the given `data-testid` attribute. */
|
|
79
|
+
export declare const getByTestId: (testIdValue: string) => (html: VNode) => Option.Option<VNode>;
|
|
80
|
+
/** Finds all elements matching the given text content.
|
|
81
|
+
* Includes nested ancestors — a `<div><p>hi</p></div>` with text "hi" yields both. */
|
|
82
|
+
export declare const getAllByText: (target: string, options?: Readonly<{
|
|
83
|
+
exact?: boolean;
|
|
84
|
+
}>) => (html: VNode) => ReadonlyArray<VNode>;
|
|
85
|
+
/** Finds all elements with the given placeholder attribute. */
|
|
86
|
+
export declare const getAllByPlaceholder: (placeholderValue: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
87
|
+
/** Finds all elements with the given `alt` attribute. */
|
|
88
|
+
export declare const getAllByAltText: (altValue: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
89
|
+
/** Finds all elements with the given `title` attribute. */
|
|
90
|
+
export declare const getAllByTitle: (titleValue: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
91
|
+
/** Finds all elements with the given `data-testid` attribute. */
|
|
92
|
+
export declare const getAllByTestId: (testIdValue: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
93
|
+
/** Finds all form controls whose current value matches. */
|
|
94
|
+
export declare const getAllByDisplayValue: (displayValueString: string) => (html: VNode) => ReadonlyArray<VNode>;
|
|
95
|
+
/** Finds the first form control whose current value matches. Checks the `value`
|
|
96
|
+
* attribute on inputs, textareas, and selects. */
|
|
97
|
+
export declare const getByDisplayValue: (displayValue: string) => (html: VNode) => Option.Option<VNode>;
|
|
53
98
|
/** A deferred element query that resolves against a VNode tree. Callable as a
|
|
54
99
|
* function (`locator(html)`) so it composes directly in `flow` and `pipe` chains.
|
|
55
100
|
* Used by interaction steps (`click`, `type`, `submit`, `keydown`) to
|
|
@@ -57,14 +102,27 @@ export declare const getByLabel: (labelValue: string) => (html: VNode) => Option
|
|
|
57
102
|
export type Locator = ((html: VNode) => Option.Option<VNode>) & Readonly<{
|
|
58
103
|
description: string;
|
|
59
104
|
}>;
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
105
|
+
/** A deferred multi-element query that resolves to all matching VNodes.
|
|
106
|
+
* Produced by `all*` locator factories and by `filter(...)`. Convert to a
|
|
107
|
+
* single-match `Locator` via `first`, `last`, or `nth(n)`. */
|
|
108
|
+
export type LocatorAll = ((html: VNode) => ReadonlyArray<VNode>) & Readonly<{
|
|
109
|
+
description: string;
|
|
110
|
+
}>;
|
|
111
|
+
/** Creates a Locator that finds an element by ARIA role. Supports matching on
|
|
112
|
+
* `name`, `level`, `checked`, `selected`, `pressed`, `expanded`, and `disabled`. */
|
|
113
|
+
export declare const role: (roleValue: string, options?: RoleOptions) => Locator;
|
|
64
114
|
/** Creates a Locator that finds an element by placeholder attribute. */
|
|
65
115
|
export declare const placeholder: (placeholderValue: string) => Locator;
|
|
66
116
|
/** Creates a Locator that finds an element by aria-label. */
|
|
67
117
|
export declare const label: (labelValue: string) => Locator;
|
|
118
|
+
/** Creates a Locator that finds an element by its `alt` attribute. */
|
|
119
|
+
export declare const altText: (altValue: string) => Locator;
|
|
120
|
+
/** Creates a Locator that finds an element by its `title` attribute. */
|
|
121
|
+
export declare const title: (titleValue: string) => Locator;
|
|
122
|
+
/** Creates a Locator that finds an element by its `data-testid` attribute. */
|
|
123
|
+
export declare const testId: (testIdValue: string) => Locator;
|
|
124
|
+
/** Creates a Locator that finds a form control by its current `value`. */
|
|
125
|
+
export declare const displayValue: (valueString: string) => Locator;
|
|
68
126
|
/** Creates a Locator that finds the most specific element matching the given text content. */
|
|
69
127
|
export declare const text: (target: string, options?: Readonly<{
|
|
70
128
|
exact?: boolean;
|
|
@@ -79,6 +137,48 @@ export declare const within: {
|
|
|
79
137
|
(parent: Locator, child: Locator): Locator;
|
|
80
138
|
(child: Locator): (parent: Locator) => Locator;
|
|
81
139
|
};
|
|
140
|
+
/** Creates a LocatorAll that finds every element matching the role. */
|
|
141
|
+
export declare const allRole: (roleValue: string, options?: RoleOptions) => LocatorAll;
|
|
142
|
+
/** Creates a LocatorAll that finds every element matching the text. */
|
|
143
|
+
export declare const allText: (target: string, options?: Readonly<{
|
|
144
|
+
exact?: boolean;
|
|
145
|
+
}>) => LocatorAll;
|
|
146
|
+
/** Creates a LocatorAll that finds every element with the given label. */
|
|
147
|
+
export declare const allLabel: (labelValue: string) => LocatorAll;
|
|
148
|
+
/** Creates a LocatorAll that finds every element with the given placeholder. */
|
|
149
|
+
export declare const allPlaceholder: (placeholderValue: string) => LocatorAll;
|
|
150
|
+
/** Creates a LocatorAll that finds every element with the given alt text. */
|
|
151
|
+
export declare const allAltText: (altValue: string) => LocatorAll;
|
|
152
|
+
/** Creates a LocatorAll that finds every element with the given title. */
|
|
153
|
+
export declare const allTitle: (titleValue: string) => LocatorAll;
|
|
154
|
+
/** Creates a LocatorAll that finds every element with the given data-testid. */
|
|
155
|
+
export declare const allTestId: (testIdValue: string) => LocatorAll;
|
|
156
|
+
/** Creates a LocatorAll that finds every form control with the given value. */
|
|
157
|
+
export declare const allDisplayValue: (valueString: string) => LocatorAll;
|
|
158
|
+
/** Creates a LocatorAll from a CSS selector — returns every match. */
|
|
159
|
+
export declare const allSelector: (css: string) => LocatorAll;
|
|
160
|
+
/** Picks the first match from a LocatorAll, producing a single-match Locator. */
|
|
161
|
+
export declare const first: (locatorAll: LocatorAll) => Locator;
|
|
162
|
+
/** Picks the last match from a LocatorAll, producing a single-match Locator. */
|
|
163
|
+
export declare const last: (locatorAll: LocatorAll) => Locator;
|
|
164
|
+
/** Picks the nth match (0-indexed) from a LocatorAll, producing a Locator. */
|
|
165
|
+
export declare const nth: {
|
|
166
|
+
(locatorAll: LocatorAll, index: number): Locator;
|
|
167
|
+
(index: number): (locatorAll: LocatorAll) => Locator;
|
|
168
|
+
};
|
|
169
|
+
type FilterOptions = Readonly<{
|
|
170
|
+
has?: Locator;
|
|
171
|
+
hasNot?: Locator;
|
|
172
|
+
hasText?: string;
|
|
173
|
+
hasNotText?: string;
|
|
174
|
+
}>;
|
|
175
|
+
/** Filters a LocatorAll's matches. Supports `has`/`hasNot` to keep entries
|
|
176
|
+
* that do/don't contain a matching descendant, and `hasText`/`hasNotText`
|
|
177
|
+
* to keep entries whose text content does/doesn't include a substring. */
|
|
178
|
+
export declare const filter: {
|
|
179
|
+
(locatorAll: LocatorAll, options: FilterOptions): LocatorAll;
|
|
180
|
+
(options: FilterOptions): (locatorAll: LocatorAll) => LocatorAll;
|
|
181
|
+
};
|
|
82
182
|
/** Resolves a target (CSS selector string or Locator) against a VNode tree. */
|
|
83
183
|
export declare const resolveTarget: (html: VNode, target: string | Locator) => Readonly<{
|
|
84
184
|
maybeElement: Option.Option<VNode>;
|
package/dist/test/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/test/query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/test/query.ts"],"names":[],"mappings":"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"}
|