foldkit 0.43.1 → 0.44.0
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/devtools/overlay.d.ts.map +1 -1
- package/dist/devtools/overlay.js +4 -67
- package/dist/devtools/store.d.ts +10 -2
- package/dist/devtools/store.d.ts.map +1 -1
- package/dist/devtools/store.js +79 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +2 -2
- package/dist/test/apps/counter.d.ts +38 -0
- package/dist/test/apps/counter.d.ts.map +1 -0
- package/dist/test/apps/counter.js +25 -0
- package/dist/test/apps/formChild.d.ts +69 -0
- package/dist/test/apps/formChild.d.ts.map +1 -0
- package/dist/test/apps/formChild.js +84 -0
- package/dist/test/apps/keypress.d.ts +23 -0
- package/dist/test/apps/keypress.d.ts.map +1 -0
- package/dist/test/apps/keypress.js +39 -0
- package/dist/test/apps/login.d.ts +46 -0
- package/dist/test/apps/login.d.ts.map +1 -0
- package/dist/test/apps/login.js +83 -0
- package/dist/test/apps/logoutButton.d.ts +17 -0
- package/dist/test/apps/logoutButton.d.ts.map +1 -0
- package/dist/test/apps/logoutButton.js +22 -0
- package/dist/test/internal.d.ts +25 -0
- package/dist/test/internal.d.ts.map +1 -0
- package/dist/test/internal.js +39 -0
- package/dist/test/matchers.d.ts +94 -0
- package/dist/test/matchers.d.ts.map +1 -0
- package/dist/test/matchers.js +283 -0
- package/dist/test/public.d.ts +2 -2
- package/dist/test/public.d.ts.map +1 -1
- package/dist/test/public.js +2 -1
- package/dist/test/query.d.ts +87 -0
- package/dist/test/query.d.ts.map +1 -0
- package/dist/test/query.js +226 -0
- package/dist/test/scene.d.ts +106 -0
- package/dist/test/scene.d.ts.map +1 -0
- package/dist/test/scene.js +373 -0
- package/dist/test/{index.d.ts → story.d.ts} +13 -17
- package/dist/test/story.d.ts.map +1 -0
- package/dist/test/{index.js → story.js} +8 -36
- package/dist/test/vitest-setup.d.ts +19 -0
- package/dist/test/vitest-setup.d.ts.map +1 -0
- package/dist/test/vitest-setup.js +3 -0
- package/package.json +5 -5
- package/dist/test/index.d.ts.map +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Schema as S } from 'effect';
|
|
2
|
+
import * as Command from '../../command';
|
|
3
|
+
import { type Html } from '../../html';
|
|
4
|
+
export declare const Model: S.Struct<{
|
|
5
|
+
email: typeof S.String;
|
|
6
|
+
password: typeof S.String;
|
|
7
|
+
status: S.Literal<["Idle", "Submitting", "LoggedIn", "Error"]>;
|
|
8
|
+
username: typeof S.String;
|
|
9
|
+
error: typeof S.String;
|
|
10
|
+
}>;
|
|
11
|
+
export type Model = typeof Model.Type;
|
|
12
|
+
export declare const UpdatedEmail: import("../../schema").CallableTaggedStruct<"UpdatedEmail", {
|
|
13
|
+
value: typeof S.String;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const UpdatedPassword: import("../../schema").CallableTaggedStruct<"UpdatedPassword", {
|
|
16
|
+
value: typeof S.String;
|
|
17
|
+
}>;
|
|
18
|
+
export declare const SubmittedLogin: import("../../schema").CallableTaggedStruct<"SubmittedLogin", {}>;
|
|
19
|
+
export declare const SucceededAuthenticate: import("../../schema").CallableTaggedStruct<"SucceededAuthenticate", {
|
|
20
|
+
username: typeof S.String;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const FailedAuthenticate: import("../../schema").CallableTaggedStruct<"FailedAuthenticate", {
|
|
23
|
+
error: typeof S.String;
|
|
24
|
+
}>;
|
|
25
|
+
export declare const ClickedLogout: import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>;
|
|
26
|
+
export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"UpdatedEmail", {
|
|
27
|
+
value: typeof S.String;
|
|
28
|
+
}>, import("../../schema").CallableTaggedStruct<"UpdatedPassword", {
|
|
29
|
+
value: typeof S.String;
|
|
30
|
+
}>, import("../../schema").CallableTaggedStruct<"SubmittedLogin", {}>, import("../../schema").CallableTaggedStruct<"SucceededAuthenticate", {
|
|
31
|
+
username: typeof S.String;
|
|
32
|
+
}>, import("../../schema").CallableTaggedStruct<"FailedAuthenticate", {
|
|
33
|
+
error: typeof S.String;
|
|
34
|
+
}>, import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>]>;
|
|
35
|
+
export type Message = typeof Message.Type;
|
|
36
|
+
export declare const Authenticate: Command.CommandDefinition<"Authenticate", {
|
|
37
|
+
readonly _tag: "SucceededAuthenticate";
|
|
38
|
+
readonly username: string;
|
|
39
|
+
} | {
|
|
40
|
+
readonly _tag: "FailedAuthenticate";
|
|
41
|
+
readonly error: string;
|
|
42
|
+
}>;
|
|
43
|
+
export declare const initialModel: Model;
|
|
44
|
+
export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
|
|
45
|
+
export declare const view: (model: Model) => Html;
|
|
46
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/test/apps/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,KAAK,IAAI,EAAQ,MAAM,YAAY,CAAA;AAK5C,eAAO,MAAM,KAAK;;;;;;EAMhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,YAAY;;EAAyC,CAAA;AAClE,eAAO,MAAM,eAAe;;EAA4C,CAAA;AACxE,eAAO,MAAM,cAAc,mEAAsB,CAAA;AACjD,eAAO,MAAM,qBAAqB;;EAEhC,CAAA;AACF,eAAO,MAAM,kBAAkB;;EAA+C,CAAA;AAC9E,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAE/C,eAAO,MAAM,OAAO;;;;;;;;sEAOnB,CAAA;AACD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY;;;;;;EAIxB,CAAA;AAQD,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAA;AAID,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAyBxD,CAAA;AA2BH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAkEjC,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Effect, Match as M, Schema as S } from 'effect';
|
|
2
|
+
import * as Command from '../../command';
|
|
3
|
+
import { html } from '../../html';
|
|
4
|
+
import { m } from '../../message';
|
|
5
|
+
// MODEL
|
|
6
|
+
export const Model = S.Struct({
|
|
7
|
+
email: S.String,
|
|
8
|
+
password: S.String,
|
|
9
|
+
status: S.Literal('Idle', 'Submitting', 'LoggedIn', 'Error'),
|
|
10
|
+
username: S.String,
|
|
11
|
+
error: S.String,
|
|
12
|
+
});
|
|
13
|
+
// MESSAGE
|
|
14
|
+
export const UpdatedEmail = m('UpdatedEmail', { value: S.String });
|
|
15
|
+
export const UpdatedPassword = m('UpdatedPassword', { value: S.String });
|
|
16
|
+
export const SubmittedLogin = m('SubmittedLogin');
|
|
17
|
+
export const SucceededAuthenticate = m('SucceededAuthenticate', {
|
|
18
|
+
username: S.String,
|
|
19
|
+
});
|
|
20
|
+
export const FailedAuthenticate = m('FailedAuthenticate', { error: S.String });
|
|
21
|
+
export const ClickedLogout = m('ClickedLogout');
|
|
22
|
+
export const Message = S.Union(UpdatedEmail, UpdatedPassword, SubmittedLogin, SucceededAuthenticate, FailedAuthenticate, ClickedLogout);
|
|
23
|
+
// COMMAND
|
|
24
|
+
export const Authenticate = Command.define('Authenticate', SucceededAuthenticate, FailedAuthenticate);
|
|
25
|
+
const authenticate = Authenticate(Effect.sync(() => SucceededAuthenticate({ username: 'alice' })));
|
|
26
|
+
// INIT
|
|
27
|
+
export const initialModel = {
|
|
28
|
+
email: '',
|
|
29
|
+
password: '',
|
|
30
|
+
status: 'Idle',
|
|
31
|
+
username: '',
|
|
32
|
+
error: '',
|
|
33
|
+
};
|
|
34
|
+
// UPDATE
|
|
35
|
+
export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
|
|
36
|
+
UpdatedEmail: ({ value }) => [{ ...model, email: value }, []],
|
|
37
|
+
UpdatedPassword: ({ value }) => [{ ...model, password: value }, []],
|
|
38
|
+
SubmittedLogin: () => [
|
|
39
|
+
{ ...model, status: 'Submitting' },
|
|
40
|
+
[authenticate],
|
|
41
|
+
],
|
|
42
|
+
SucceededAuthenticate: ({ username }) => [
|
|
43
|
+
{ ...model, status: 'LoggedIn', username },
|
|
44
|
+
[],
|
|
45
|
+
],
|
|
46
|
+
FailedAuthenticate: ({ error }) => [
|
|
47
|
+
{ ...model, status: 'Error', error },
|
|
48
|
+
[],
|
|
49
|
+
],
|
|
50
|
+
ClickedLogout: () => [
|
|
51
|
+
{ ...model, status: 'Idle', username: '', email: '', password: '' },
|
|
52
|
+
[],
|
|
53
|
+
],
|
|
54
|
+
}));
|
|
55
|
+
// VIEW
|
|
56
|
+
const { div, form, input, button, span, label, p, OnInput, OnSubmit, OnClick, Id, For, Class, Type, Value, Placeholder, Role, AriaExpanded, AriaLabel, Disabled, } = html();
|
|
57
|
+
export const view = (model) => div([Id('app')], [
|
|
58
|
+
M.value(model.status).pipe(M.withReturnType(), M.when('Submitting', () => form([Class('login-form'), Disabled(true)], [button([Type('submit'), Disabled(true)], ['Signing in...'])])), M.when('LoggedIn', () => div([Class('logged-in'), Role('region'), AriaLabel('User session')], [
|
|
59
|
+
span([Class('greeting'), Role('status')], [`Welcome, ${model.username}!`]),
|
|
60
|
+
button([OnClick(ClickedLogout()), Role('button'), AriaExpanded(false)], ['Log out']),
|
|
61
|
+
])), M.when('Error', () => div([], [
|
|
62
|
+
p([Class('error'), Role('alert')], [model.error]),
|
|
63
|
+
button([OnClick(SubmittedLogin()), Class('retry')], ['Retry']),
|
|
64
|
+
])), M.when('Idle', () => form([OnSubmit(SubmittedLogin()), Class('login-form')], [
|
|
65
|
+
label([For('email'), Class('sr-only')], ['Email']),
|
|
66
|
+
input([
|
|
67
|
+
Id('email'),
|
|
68
|
+
Type('email'),
|
|
69
|
+
Placeholder('Email'),
|
|
70
|
+
Value(model.email),
|
|
71
|
+
OnInput(value => UpdatedEmail({ value })),
|
|
72
|
+
]),
|
|
73
|
+
label([For('password'), Class('sr-only')], ['Password']),
|
|
74
|
+
input([
|
|
75
|
+
Id('password'),
|
|
76
|
+
Type('password'),
|
|
77
|
+
Placeholder('Password'),
|
|
78
|
+
Value(model.password),
|
|
79
|
+
OnInput(value => UpdatedPassword({ value })),
|
|
80
|
+
]),
|
|
81
|
+
button([Type('submit'), Class('primary'), Disabled(false)], ['Sign in']),
|
|
82
|
+
])), M.exhaustive),
|
|
83
|
+
]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Option, Schema as S } from 'effect';
|
|
2
|
+
import type { Html } from '../../html';
|
|
3
|
+
export declare const Model: S.Struct<{
|
|
4
|
+
label: typeof S.String;
|
|
5
|
+
}>;
|
|
6
|
+
export type Model = typeof Model.Type;
|
|
7
|
+
export declare const ClickedLogout: import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>;
|
|
8
|
+
export declare const CompletedAction: import("../../schema").CallableTaggedStruct<"CompletedAction", {}>;
|
|
9
|
+
export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>, import("../../schema").CallableTaggedStruct<"CompletedAction", {}>]>;
|
|
10
|
+
export type Message = typeof Message.Type;
|
|
11
|
+
export declare const RequestedLogout: import("../../schema").CallableTaggedStruct<"RequestedLogout", {}>;
|
|
12
|
+
export declare const OutMessage: import("../../schema").CallableTaggedStruct<"RequestedLogout", {}>;
|
|
13
|
+
export type OutMessage = typeof OutMessage.Type;
|
|
14
|
+
export declare const initialModel: Model;
|
|
15
|
+
export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<never>, Option.Option<OutMessage>];
|
|
16
|
+
export declare const view: (model: Model) => Html;
|
|
17
|
+
//# sourceMappingURL=logoutButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logoutButton.d.ts","sourceRoot":"","sources":["../../../src/test/apps/logoutButton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAMtC,eAAO,MAAM,KAAK;;EAAgC,CAAA;AAClD,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,OAAO,iJAA0C,CAAA;AAC9D,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,UAAU,oEAA2B,CAAA;AAClD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,eAAO,MAAM,YAAY,EAAE,KAA4B,CAAA;AAIvD,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAShE,CAAA;AAMH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAC0C,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Match as M, Option, Schema as S } from 'effect';
|
|
2
|
+
import { html } from '../../html';
|
|
3
|
+
import { m } from '../../message';
|
|
4
|
+
// MODEL
|
|
5
|
+
export const Model = S.Struct({ label: S.String });
|
|
6
|
+
// MESSAGE
|
|
7
|
+
export const ClickedLogout = m('ClickedLogout');
|
|
8
|
+
export const CompletedAction = m('CompletedAction');
|
|
9
|
+
export const Message = S.Union(ClickedLogout, CompletedAction);
|
|
10
|
+
// OUT MESSAGE
|
|
11
|
+
export const RequestedLogout = m('RequestedLogout');
|
|
12
|
+
export const OutMessage = S.Union(RequestedLogout);
|
|
13
|
+
// INIT
|
|
14
|
+
export const initialModel = { label: 'Log out' };
|
|
15
|
+
// UPDATE
|
|
16
|
+
export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
|
|
17
|
+
ClickedLogout: () => [model, [], Option.some(RequestedLogout())],
|
|
18
|
+
CompletedAction: () => [model, [], Option.none()],
|
|
19
|
+
}));
|
|
20
|
+
// VIEW
|
|
21
|
+
const { div, button, OnClick, Role } = html();
|
|
22
|
+
export const view = (model) => div([], [button([OnClick(ClickedLogout()), Role('button')], [model.label])]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../command';
|
|
2
|
+
/** A Command in a test simulation, identified by name. */
|
|
3
|
+
export type AnyCommand = Readonly<{
|
|
4
|
+
name: string;
|
|
5
|
+
}>;
|
|
6
|
+
type UpdateResult<Model, OutMessage> = readonly [Model, ReadonlyArray<AnyCommand>] | readonly [Model, ReadonlyArray<AnyCommand>, OutMessage];
|
|
7
|
+
/** A Command definition paired with the result Message to resolve it with. */
|
|
8
|
+
export type ResolverPair<Name extends string = string, ResultMessage = unknown> = readonly [CommandDefinition<Name, ResultMessage>, ResultMessage];
|
|
9
|
+
/** Base shape of an internal simulation — shared between Story and Scene. */
|
|
10
|
+
export type BaseInternal<Model, Message, OutMessage = undefined> = Readonly<{
|
|
11
|
+
model: Model;
|
|
12
|
+
message: Message | undefined;
|
|
13
|
+
commands: ReadonlyArray<AnyCommand>;
|
|
14
|
+
outMessage: OutMessage;
|
|
15
|
+
updateFn: (model: Model, message: Message) => UpdateResult<Model, OutMessage>;
|
|
16
|
+
resolvers: Record<string, Message>;
|
|
17
|
+
}>;
|
|
18
|
+
/** Resolves a single command by name and feeds its result through update. */
|
|
19
|
+
export declare const resolveByName: <Model, Message>(internal: BaseInternal<Model, Message, unknown>, commandName: string, resolverMessage: Message) => BaseInternal<Model, Message, unknown> | undefined;
|
|
20
|
+
/** Throws when trying to send a message with unresolved Commands. */
|
|
21
|
+
export declare const assertNoUnresolvedCommands: (commands: ReadonlyArray<AnyCommand>, context: string) => void;
|
|
22
|
+
/** Throws when Commands remain at the end of a test. */
|
|
23
|
+
export declare const assertAllCommandsResolved: (commands: ReadonlyArray<AnyCommand>) => void;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/test/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAEnD,KAAK,YAAY,CAAC,KAAK,EAAE,UAAU,IAC/B,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,GAC3C,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAA;AAE3D,8EAA8E;AAC9E,MAAM,MAAM,YAAY,CACtB,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,aAAa,GAAG,OAAO,IACrB,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,aAAa,CAAC,CAAA;AAEpE,6EAA6E;AAC7E,MAAM,MAAM,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS,IAAI,QAAQ,CAAC;IAC1E,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IACnC,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAC7E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,aAAa,GAAI,KAAK,EAAE,OAAO,EAC1C,UAAU,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAC/C,aAAa,MAAM,EACnB,iBAAiB,OAAO,KACvB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,SAyBxC,CAAA;AAEH,qEAAqE;AACrE,eAAO,MAAM,0BAA0B,GACrC,UAAU,aAAa,CAAC,UAAU,CAAC,EACnC,SAAS,MAAM,KACd,IAcF,CAAA;AAED,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GACpC,UAAU,aAAa,CAAC,UAAU,CAAC,KAClC,IAcF,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Array, Option, pipe } from 'effect';
|
|
2
|
+
/** Resolves a single command by name and feeds its result through update. */
|
|
3
|
+
export const resolveByName = (internal, commandName, resolverMessage) => pipe(internal.commands, Array.findFirstIndex(({ name }) => name === commandName), Option.match({
|
|
4
|
+
onNone: () => undefined,
|
|
5
|
+
onSome: commandIndex => {
|
|
6
|
+
const remainingCommands = Array.remove(internal.commands, commandIndex);
|
|
7
|
+
const [nextModel, newCommands, ...rest] = internal.updateFn(internal.model, resolverMessage);
|
|
8
|
+
const outMessage = Array.isNonEmptyArray(rest)
|
|
9
|
+
? rest[0]
|
|
10
|
+
: internal.outMessage;
|
|
11
|
+
return {
|
|
12
|
+
...internal,
|
|
13
|
+
model: nextModel,
|
|
14
|
+
message: resolverMessage,
|
|
15
|
+
commands: Array.appendAll(remainingCommands, newCommands),
|
|
16
|
+
outMessage,
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
/** Throws when trying to send a message with unresolved Commands. */
|
|
21
|
+
export const assertNoUnresolvedCommands = (commands, context) => {
|
|
22
|
+
if (Array.isNonEmptyReadonlyArray(commands)) {
|
|
23
|
+
const names = pipe(commands, Array.map(({ name }) => ` ${name}`), Array.join('\n'));
|
|
24
|
+
throw new Error(`I found unresolved Commands ${context}:\n\n${names}\n\n` +
|
|
25
|
+
'Resolve all Commands before sending the next Message.\n' +
|
|
26
|
+
'Use resolve(Definition, ResultMessage) for each one,\n' +
|
|
27
|
+
'or resolveAll([...pairs]) to resolve them all at once.');
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/** Throws when Commands remain at the end of a test. */
|
|
31
|
+
export const assertAllCommandsResolved = (commands) => {
|
|
32
|
+
if (Array.isNonEmptyReadonlyArray(commands)) {
|
|
33
|
+
const names = pipe(commands, Array.map(({ name }) => ` ${name}`), Array.join('\n'));
|
|
34
|
+
throw new Error(`I found Commands without resolvers:\n\n${names}\n\n` +
|
|
35
|
+
'Every Command produced by update needs to be resolved.\n' +
|
|
36
|
+
'Use resolve(Definition, ResultMessage) for each one,\n' +
|
|
37
|
+
'or resolveAll([...pairs]) to resolve them all at once.');
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Option } from 'effect';
|
|
2
|
+
import type { VNode } from '../vdom';
|
|
3
|
+
/** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
|
|
4
|
+
export declare const sceneMatchers: {
|
|
5
|
+
toHaveText(received: Option.Option<VNode>, expected: string): {
|
|
6
|
+
pass: boolean;
|
|
7
|
+
message: () => string;
|
|
8
|
+
} | {
|
|
9
|
+
pass: boolean;
|
|
10
|
+
message: () => string;
|
|
11
|
+
};
|
|
12
|
+
toContainText(received: Option.Option<VNode>, expected: string): {
|
|
13
|
+
pass: boolean;
|
|
14
|
+
message: () => string;
|
|
15
|
+
} | {
|
|
16
|
+
pass: boolean;
|
|
17
|
+
message: () => string;
|
|
18
|
+
};
|
|
19
|
+
toHaveClass(received: Option.Option<VNode>, expected: string): {
|
|
20
|
+
pass: boolean;
|
|
21
|
+
message: () => string;
|
|
22
|
+
} | {
|
|
23
|
+
pass: boolean;
|
|
24
|
+
message: () => string;
|
|
25
|
+
};
|
|
26
|
+
toHaveAttr(received: Option.Option<VNode>, name: string, expectedValue?: string): {
|
|
27
|
+
pass: boolean;
|
|
28
|
+
message: () => string;
|
|
29
|
+
} | {
|
|
30
|
+
pass: boolean;
|
|
31
|
+
message: () => string;
|
|
32
|
+
};
|
|
33
|
+
toExist(received: Option.Option<VNode>): {
|
|
34
|
+
pass: boolean;
|
|
35
|
+
message: () => "Expected element not to exist but it does." | "Expected element to exist but it does not.";
|
|
36
|
+
};
|
|
37
|
+
toBeAbsent(received: Option.Option<VNode>): {
|
|
38
|
+
pass: boolean;
|
|
39
|
+
message: () => "Expected element not to be absent but it is." | "Expected element to be absent but it exists.";
|
|
40
|
+
};
|
|
41
|
+
toHaveStyle(received: Option.Option<VNode>, name: string, expectedValue?: string): {
|
|
42
|
+
pass: boolean;
|
|
43
|
+
message: () => string;
|
|
44
|
+
} | {
|
|
45
|
+
pass: boolean;
|
|
46
|
+
message: () => string;
|
|
47
|
+
};
|
|
48
|
+
toHaveHook(received: Option.Option<VNode>, name: string): {
|
|
49
|
+
pass: boolean;
|
|
50
|
+
message: () => string;
|
|
51
|
+
} | {
|
|
52
|
+
pass: boolean;
|
|
53
|
+
message: () => string;
|
|
54
|
+
};
|
|
55
|
+
toHaveHandler(received: Option.Option<VNode>, name: string): {
|
|
56
|
+
pass: boolean;
|
|
57
|
+
message: () => string;
|
|
58
|
+
} | {
|
|
59
|
+
pass: boolean;
|
|
60
|
+
message: () => string;
|
|
61
|
+
};
|
|
62
|
+
toHaveValue(received: Option.Option<VNode>, expected: string): {
|
|
63
|
+
pass: boolean;
|
|
64
|
+
message: () => string;
|
|
65
|
+
} | {
|
|
66
|
+
pass: false;
|
|
67
|
+
message: () => string;
|
|
68
|
+
} | {
|
|
69
|
+
pass: boolean;
|
|
70
|
+
message: () => string;
|
|
71
|
+
};
|
|
72
|
+
toBeDisabled(received: Option.Option<VNode>): {
|
|
73
|
+
pass: boolean;
|
|
74
|
+
message: () => "Expected element to be disabled but the element does not exist.";
|
|
75
|
+
} | {
|
|
76
|
+
pass: boolean;
|
|
77
|
+
message: () => "Expected element not to be disabled but it is." | "Expected element to be disabled but it is not.";
|
|
78
|
+
};
|
|
79
|
+
toBeEnabled(received: Option.Option<VNode>): {
|
|
80
|
+
pass: boolean;
|
|
81
|
+
message: () => "Expected element to be enabled but the element does not exist.";
|
|
82
|
+
} | {
|
|
83
|
+
pass: boolean;
|
|
84
|
+
message: () => "Expected element not to be enabled but it is." | "Expected element to be enabled but it is disabled.";
|
|
85
|
+
};
|
|
86
|
+
toBeChecked(received: Option.Option<VNode>): {
|
|
87
|
+
pass: boolean;
|
|
88
|
+
message: () => "Expected element to be checked but the element does not exist.";
|
|
89
|
+
} | {
|
|
90
|
+
pass: boolean;
|
|
91
|
+
message: () => "Expected element not to be checked but it is." | "Expected element to be checked but it is not.";
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/test/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAKpC,oGAAoG;AACpG,eAAO,MAAM,aAAa;yBACH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;4BAqBnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;0BAqBxC,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;;;;;;;0BAyBpB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;CAwB3C,CAAA"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { Option } from 'effect';
|
|
2
|
+
import { attr, textContent } from './query';
|
|
3
|
+
/** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
|
|
4
|
+
export const sceneMatchers = {
|
|
5
|
+
toHaveText(received, expected) {
|
|
6
|
+
return Option.match(received, {
|
|
7
|
+
onNone: () => ({
|
|
8
|
+
pass: false,
|
|
9
|
+
message: () => `Expected element to have text "${expected}" but the element does not exist.`,
|
|
10
|
+
}),
|
|
11
|
+
onSome: vnode => {
|
|
12
|
+
const actualText = textContent(vnode);
|
|
13
|
+
return {
|
|
14
|
+
pass: actualText === expected,
|
|
15
|
+
message: () =>
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
17
|
+
this.isNot
|
|
18
|
+
? `Expected element not to have text "${expected}" but it does.`
|
|
19
|
+
: `Expected element to have text "${expected}" but received "${actualText}".`,
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
toContainText(received, expected) {
|
|
25
|
+
return Option.match(received, {
|
|
26
|
+
onNone: () => ({
|
|
27
|
+
pass: false,
|
|
28
|
+
message: () => `Expected element to contain text "${expected}" but the element does not exist.`,
|
|
29
|
+
}),
|
|
30
|
+
onSome: vnode => {
|
|
31
|
+
const actualText = textContent(vnode);
|
|
32
|
+
return {
|
|
33
|
+
pass: actualText.includes(expected),
|
|
34
|
+
message: () =>
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
36
|
+
this.isNot
|
|
37
|
+
? `Expected element not to contain text "${expected}" but it does.`
|
|
38
|
+
: `Expected element to contain text "${expected}" but received "${actualText}".`,
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
toHaveClass(received, expected) {
|
|
44
|
+
return Option.match(received, {
|
|
45
|
+
onNone: () => ({
|
|
46
|
+
pass: false,
|
|
47
|
+
message: () => `Expected element to have class "${expected}" but the element does not exist.`,
|
|
48
|
+
}),
|
|
49
|
+
onSome: vnode => ({
|
|
50
|
+
pass: vnode.data?.class?.[expected] === true,
|
|
51
|
+
message: () =>
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
53
|
+
this.isNot
|
|
54
|
+
? `Expected element not to have class "${expected}" but it does.`
|
|
55
|
+
: `Expected element to have class "${expected}" but it does not.`,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
toHaveAttr(received, name, expectedValue) {
|
|
60
|
+
return Option.match(received, {
|
|
61
|
+
onNone: () => ({
|
|
62
|
+
pass: false,
|
|
63
|
+
message: () => expectedValue === undefined
|
|
64
|
+
? `Expected element to have attribute "${name}" but the element does not exist.`
|
|
65
|
+
: `Expected element to have attribute ${name}="${expectedValue}" but the element does not exist.`,
|
|
66
|
+
}),
|
|
67
|
+
onSome: vnode => {
|
|
68
|
+
const actualValue = attr(vnode, name);
|
|
69
|
+
if (expectedValue === undefined) {
|
|
70
|
+
return {
|
|
71
|
+
pass: Option.isSome(actualValue),
|
|
72
|
+
message: () =>
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
74
|
+
this.isNot
|
|
75
|
+
? `Expected element not to have attribute "${name}" but it does.`
|
|
76
|
+
: `Expected element to have attribute "${name}" but it is not present.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return Option.match(actualValue, {
|
|
80
|
+
onNone: () => ({
|
|
81
|
+
pass: false,
|
|
82
|
+
message: () => `Expected element to have attribute ${name}="${expectedValue}" but the attribute is not present.`,
|
|
83
|
+
}),
|
|
84
|
+
onSome: actual => ({
|
|
85
|
+
pass: actual === expectedValue,
|
|
86
|
+
message: () =>
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
88
|
+
this.isNot
|
|
89
|
+
? `Expected element not to have attribute ${name}="${expectedValue}" but it does.`
|
|
90
|
+
: `Expected element to have attribute ${name}="${expectedValue}" but received "${actual}".`,
|
|
91
|
+
}),
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
toExist(received) {
|
|
97
|
+
return {
|
|
98
|
+
pass: Option.isSome(received),
|
|
99
|
+
message: () =>
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
101
|
+
this.isNot
|
|
102
|
+
? 'Expected element not to exist but it does.'
|
|
103
|
+
: 'Expected element to exist but it does not.',
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
toBeAbsent(received) {
|
|
107
|
+
return {
|
|
108
|
+
pass: Option.isNone(received),
|
|
109
|
+
message: () =>
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
111
|
+
this.isNot
|
|
112
|
+
? 'Expected element not to be absent but it is.'
|
|
113
|
+
: 'Expected element to be absent but it exists.',
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
toHaveStyle(received, name, expectedValue) {
|
|
117
|
+
return Option.match(received, {
|
|
118
|
+
onNone: () => ({
|
|
119
|
+
pass: false,
|
|
120
|
+
message: () => expectedValue === undefined
|
|
121
|
+
? `Expected element to have style "${name}" but the element does not exist.`
|
|
122
|
+
: `Expected element to have style ${name}="${expectedValue}" but the element does not exist.`,
|
|
123
|
+
}),
|
|
124
|
+
onSome: vnode => {
|
|
125
|
+
const maybeActualValue = Option.fromNullable(vnode.data?.style?.[name]);
|
|
126
|
+
if (expectedValue === undefined) {
|
|
127
|
+
return {
|
|
128
|
+
pass: Option.isSome(maybeActualValue),
|
|
129
|
+
message: () =>
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
131
|
+
this.isNot
|
|
132
|
+
? `Expected element not to have style "${name}" but it does.`
|
|
133
|
+
: `Expected element to have style "${name}" but it is not present.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return Option.match(maybeActualValue, {
|
|
137
|
+
onNone: () => ({
|
|
138
|
+
pass: false,
|
|
139
|
+
message: () => `Expected element to have style ${name}="${expectedValue}" but the style is not present.`,
|
|
140
|
+
}),
|
|
141
|
+
onSome: actualValue => {
|
|
142
|
+
const actual = String(actualValue);
|
|
143
|
+
return {
|
|
144
|
+
pass: actual === expectedValue,
|
|
145
|
+
message: () =>
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
147
|
+
this.isNot
|
|
148
|
+
? `Expected element not to have style ${name}="${expectedValue}" but it does.`
|
|
149
|
+
: `Expected element to have style ${name}="${expectedValue}" but received "${actual}".`,
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
toHaveHook(received, name) {
|
|
157
|
+
return Option.match(received, {
|
|
158
|
+
onNone: () => ({
|
|
159
|
+
pass: false,
|
|
160
|
+
message: () => `Expected element to have hook "${name}" but the element does not exist.`,
|
|
161
|
+
}),
|
|
162
|
+
onSome: vnode => {
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
164
|
+
const hooks = vnode.data?.hook;
|
|
165
|
+
return {
|
|
166
|
+
pass: typeof hooks?.[name] === 'function',
|
|
167
|
+
message: () =>
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
169
|
+
this.isNot
|
|
170
|
+
? `Expected element not to have hook "${name}" but it does.`
|
|
171
|
+
: `Expected element to have hook "${name}" but it is not present.`,
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
toHaveHandler(received, name) {
|
|
177
|
+
return Option.match(received, {
|
|
178
|
+
onNone: () => ({
|
|
179
|
+
pass: false,
|
|
180
|
+
message: () => `Expected element to have handler "${name}" but the element does not exist.`,
|
|
181
|
+
}),
|
|
182
|
+
onSome: vnode => ({
|
|
183
|
+
pass: vnode.data?.on?.[name] !== undefined,
|
|
184
|
+
message: () =>
|
|
185
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
186
|
+
this.isNot
|
|
187
|
+
? `Expected element not to have handler "${name}" but it does.`
|
|
188
|
+
: `Expected element to have handler "${name}" but it is not present.`,
|
|
189
|
+
}),
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
toHaveValue(received, expected) {
|
|
193
|
+
return Option.match(received, {
|
|
194
|
+
onNone: () => ({
|
|
195
|
+
pass: false,
|
|
196
|
+
message: () => `Expected element to have value "${expected}" but the element does not exist.`,
|
|
197
|
+
}),
|
|
198
|
+
onSome: vnode => {
|
|
199
|
+
const actualValue = attr(vnode, 'value');
|
|
200
|
+
return Option.match(actualValue, {
|
|
201
|
+
onNone: () => ({
|
|
202
|
+
pass: false,
|
|
203
|
+
message: () => `Expected element to have value "${expected}" but the element has no value.`,
|
|
204
|
+
}),
|
|
205
|
+
onSome: actual => ({
|
|
206
|
+
pass: actual === expected,
|
|
207
|
+
message: () =>
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
209
|
+
this.isNot
|
|
210
|
+
? `Expected element not to have value "${expected}" but it does.`
|
|
211
|
+
: `Expected element to have value "${expected}" but received "${actual}".`,
|
|
212
|
+
}),
|
|
213
|
+
});
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
},
|
|
217
|
+
toBeDisabled(received) {
|
|
218
|
+
return Option.match(received, {
|
|
219
|
+
onNone: () => ({
|
|
220
|
+
pass: false,
|
|
221
|
+
message: () => 'Expected element to be disabled but the element does not exist.',
|
|
222
|
+
}),
|
|
223
|
+
onSome: vnode => {
|
|
224
|
+
const disabled = attr(vnode, 'disabled');
|
|
225
|
+
const ariaDisabled = attr(vnode, 'aria-disabled');
|
|
226
|
+
const pass = (Option.isSome(disabled) && disabled.value !== 'false') ||
|
|
227
|
+
(Option.isSome(ariaDisabled) && ariaDisabled.value === 'true');
|
|
228
|
+
return {
|
|
229
|
+
pass,
|
|
230
|
+
message: () =>
|
|
231
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
232
|
+
this.isNot
|
|
233
|
+
? 'Expected element not to be disabled but it is.'
|
|
234
|
+
: 'Expected element to be disabled but it is not.',
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
},
|
|
239
|
+
toBeEnabled(received) {
|
|
240
|
+
return Option.match(received, {
|
|
241
|
+
onNone: () => ({
|
|
242
|
+
pass: false,
|
|
243
|
+
message: () => 'Expected element to be enabled but the element does not exist.',
|
|
244
|
+
}),
|
|
245
|
+
onSome: vnode => {
|
|
246
|
+
const disabled = attr(vnode, 'disabled');
|
|
247
|
+
const ariaDisabled = attr(vnode, 'aria-disabled');
|
|
248
|
+
const isDisabled = (Option.isSome(disabled) && disabled.value !== 'false') ||
|
|
249
|
+
(Option.isSome(ariaDisabled) && ariaDisabled.value === 'true');
|
|
250
|
+
return {
|
|
251
|
+
pass: !isDisabled,
|
|
252
|
+
message: () =>
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
254
|
+
this.isNot
|
|
255
|
+
? 'Expected element not to be enabled but it is.'
|
|
256
|
+
: 'Expected element to be enabled but it is disabled.',
|
|
257
|
+
};
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
},
|
|
261
|
+
toBeChecked(received) {
|
|
262
|
+
return Option.match(received, {
|
|
263
|
+
onNone: () => ({
|
|
264
|
+
pass: false,
|
|
265
|
+
message: () => 'Expected element to be checked but the element does not exist.',
|
|
266
|
+
}),
|
|
267
|
+
onSome: vnode => {
|
|
268
|
+
const checked = attr(vnode, 'checked');
|
|
269
|
+
const ariaChecked = attr(vnode, 'aria-checked');
|
|
270
|
+
const pass = (Option.isSome(checked) && checked.value !== 'false') ||
|
|
271
|
+
(Option.isSome(ariaChecked) && ariaChecked.value === 'true');
|
|
272
|
+
return {
|
|
273
|
+
pass,
|
|
274
|
+
message: () =>
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
276
|
+
this.isNot
|
|
277
|
+
? 'Expected element not to be checked but it is.'
|
|
278
|
+
: 'Expected element to be checked but it is not.',
|
|
279
|
+
};
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
},
|
|
283
|
+
};
|
package/dist/test/public.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export * as Story from './story';
|
|
2
|
+
export * as Scene from './scene';
|
|
3
3
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/test/public.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/test/public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA"}
|
package/dist/test/public.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * as Story from './story';
|
|
2
|
+
export * as Scene from './scene';
|