@planet-matrix/mobius-model 0.6.0 → 0.10.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/CHANGELOG.md +50 -0
- package/oxlint.config.ts +1 -2
- package/package.json +29 -17
- package/scripts/build.ts +2 -52
- package/src/ai/README.md +1 -0
- package/src/ai/ai.ts +107 -0
- package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
- package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
- package/src/ai/chat-completion-ai/index.ts +7 -0
- package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
- package/src/ai/embedding-ai/embedding-ai.ts +63 -0
- package/src/ai/embedding-ai/embedding.ts +50 -0
- package/src/ai/embedding-ai/index.ts +4 -0
- package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
- package/src/ai/index.ts +4 -0
- package/src/aio/README.md +100 -0
- package/src/aio/content.ts +141 -0
- package/src/aio/index.ts +3 -0
- package/src/aio/json.ts +127 -0
- package/src/aio/prompt.ts +246 -0
- package/src/basic/README.md +20 -15
- package/src/basic/error.ts +19 -5
- package/src/basic/function.ts +2 -2
- package/src/basic/index.ts +1 -0
- package/src/basic/promise.ts +141 -71
- package/src/basic/schedule.ts +111 -0
- package/src/basic/stream.ts +135 -25
- package/src/credential/README.md +107 -0
- package/src/credential/api-key.ts +158 -0
- package/src/credential/bearer.ts +73 -0
- package/src/credential/index.ts +4 -0
- package/src/credential/json-web-token.ts +96 -0
- package/src/credential/password.ts +170 -0
- package/src/cron/README.md +86 -0
- package/src/cron/cron.ts +87 -0
- package/src/cron/index.ts +1 -0
- package/src/drizzle/README.md +1 -0
- package/src/drizzle/drizzle.ts +1 -0
- package/src/drizzle/helper.ts +47 -0
- package/src/drizzle/index.ts +5 -0
- package/src/drizzle/infer.ts +52 -0
- package/src/drizzle/kysely.ts +8 -0
- package/src/drizzle/pagination.ts +198 -0
- package/src/email/README.md +1 -0
- package/src/email/index.ts +1 -0
- package/src/email/resend.ts +25 -0
- package/src/event/class-event-proxy.ts +5 -6
- package/src/event/common.ts +13 -3
- package/src/event/event-manager.ts +3 -3
- package/src/event/instance-event-proxy.ts +5 -6
- package/src/event/internal.ts +4 -4
- package/src/exception/README.md +28 -19
- package/src/exception/error/error.ts +123 -0
- package/src/exception/error/index.ts +2 -0
- package/src/exception/error/match.ts +38 -0
- package/src/exception/error/must-fix.ts +17 -0
- package/src/exception/index.ts +2 -0
- package/src/file-system/find.ts +53 -0
- package/src/file-system/index.ts +2 -0
- package/src/file-system/path.ts +76 -0
- package/src/file-system/resolve.ts +22 -0
- package/src/form/README.md +25 -0
- package/src/form/index.ts +1 -0
- package/src/form/inputor-controller/base.ts +861 -0
- package/src/form/inputor-controller/boolean.ts +39 -0
- package/src/form/inputor-controller/file.ts +39 -0
- package/src/form/inputor-controller/form.ts +179 -0
- package/src/form/inputor-controller/helper.ts +117 -0
- package/src/form/inputor-controller/index.ts +17 -0
- package/src/form/inputor-controller/multi-select.ts +99 -0
- package/src/form/inputor-controller/number.ts +116 -0
- package/src/form/inputor-controller/select.ts +109 -0
- package/src/form/inputor-controller/text.ts +82 -0
- package/src/http/READMD.md +1 -0
- package/src/http/api/api-core.ts +84 -0
- package/src/http/api/api-handler.ts +79 -0
- package/src/http/api/api-host.ts +47 -0
- package/src/http/api/api-result.ts +56 -0
- package/src/http/api/api-schema.ts +154 -0
- package/src/http/api/api-server.ts +130 -0
- package/src/http/api/api-test.ts +142 -0
- package/src/http/api/api-type.ts +34 -0
- package/src/http/api/api.ts +81 -0
- package/src/http/api/index.ts +11 -0
- package/src/http/api-adapter/api-core-node-http.ts +260 -0
- package/src/http/api-adapter/api-host-node-http.ts +156 -0
- package/src/http/api-adapter/api-result-arktype.ts +294 -0
- package/src/http/api-adapter/api-result-zod.ts +286 -0
- package/src/http/api-adapter/index.ts +5 -0
- package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
- package/src/http/bin/gen-api-list/index.ts +1 -0
- package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
- package/src/http/bin/gen-api-test/index.ts +1 -0
- package/src/http/bin/gen-api-type/calc-code.ts +25 -0
- package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
- package/src/http/bin/gen-api-type/index.ts +2 -0
- package/src/http/bin/index.ts +2 -0
- package/src/http/index.ts +3 -0
- package/src/huawei/README.md +1 -0
- package/src/huawei/index.ts +2 -0
- package/src/huawei/moderation/index.ts +1 -0
- package/src/huawei/moderation/moderation.ts +355 -0
- package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
- package/src/huawei/obs/index.ts +1 -0
- package/src/huawei/obs/obs.ts +42 -0
- package/src/index.ts +21 -2
- package/src/json/README.md +92 -0
- package/src/json/index.ts +1 -0
- package/src/json/repair.ts +18 -0
- package/src/log/logger.ts +15 -4
- package/src/openai/README.md +1 -0
- package/src/openai/index.ts +1 -0
- package/src/openai/openai.ts +509 -0
- package/src/orchestration/README.md +9 -7
- package/src/orchestration/dispatching/dispatcher.ts +83 -0
- package/src/orchestration/dispatching/index.ts +2 -0
- package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
- package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
- package/src/orchestration/dispatching/selector/index.ts +2 -0
- package/src/orchestration/index.ts +2 -0
- package/src/orchestration/scheduling/index.ts +2 -0
- package/src/orchestration/scheduling/scheduler.ts +103 -0
- package/src/orchestration/scheduling/task.ts +32 -0
- package/src/random/README.md +8 -7
- package/src/random/base.ts +66 -0
- package/src/random/index.ts +5 -1
- package/src/random/random-boolean.ts +40 -0
- package/src/random/random-integer.ts +60 -0
- package/src/random/random-number.ts +72 -0
- package/src/random/random-string.ts +66 -0
- package/src/request/README.md +108 -0
- package/src/request/fetch/base.ts +108 -0
- package/src/request/fetch/browser.ts +280 -0
- package/src/request/fetch/general.ts +20 -0
- package/src/request/fetch/index.ts +4 -0
- package/src/request/fetch/nodejs.ts +280 -0
- package/src/request/index.ts +2 -0
- package/src/request/request/base.ts +246 -0
- package/src/request/request/general.ts +63 -0
- package/src/request/request/index.ts +3 -0
- package/src/request/request/resource.ts +68 -0
- package/src/result/README.md +4 -0
- package/src/result/controller.ts +58 -0
- package/src/result/either.ts +363 -0
- package/src/result/generator.ts +168 -0
- package/src/result/index.ts +3 -0
- package/src/route/README.md +105 -0
- package/src/route/adapter/browser.ts +122 -0
- package/src/route/adapter/driver.ts +56 -0
- package/src/route/adapter/index.ts +2 -0
- package/src/route/index.ts +3 -0
- package/src/route/router/index.ts +2 -0
- package/src/route/router/route.ts +630 -0
- package/src/route/router/router.ts +1641 -0
- package/src/route/uri/hash.ts +307 -0
- package/src/route/uri/index.ts +7 -0
- package/src/route/uri/pathname.ts +376 -0
- package/src/route/uri/search.ts +412 -0
- package/src/service/README.md +1 -0
- package/src/service/index.ts +1 -0
- package/src/service/service.ts +110 -0
- package/src/socket/README.md +105 -0
- package/src/socket/client/index.ts +2 -0
- package/src/socket/client/socket-unit.ts +658 -0
- package/src/socket/client/socket.ts +203 -0
- package/src/socket/common/index.ts +2 -0
- package/src/socket/common/socket-unit-common.ts +23 -0
- package/src/socket/common/socket-unit-heartbeat.ts +427 -0
- package/src/socket/index.ts +3 -0
- package/src/socket/server/index.ts +3 -0
- package/src/socket/server/server.ts +183 -0
- package/src/socket/server/socket-unit.ts +448 -0
- package/src/socket/server/socket.ts +264 -0
- package/src/storage/table.ts +3 -3
- package/src/timer/expiration/expiration-manager.ts +3 -3
- package/src/timer/expiration/remaining-manager.ts +3 -3
- package/src/tube/README.md +99 -0
- package/src/tube/helper.ts +137 -0
- package/src/tube/index.ts +2 -0
- package/src/tube/tube.ts +880 -0
- package/src/weixin/README.md +1 -0
- package/src/weixin/index.ts +2 -0
- package/src/weixin/official-account/authorization.ts +157 -0
- package/src/weixin/official-account/index.ts +2 -0
- package/src/weixin/official-account/js-api.ts +132 -0
- package/src/weixin/open/index.ts +1 -0
- package/src/weixin/open/oauth2.ts +131 -0
- package/tests/unit/ai/ai.spec.ts +85 -0
- package/tests/unit/aio/content.spec.ts +105 -0
- package/tests/unit/aio/json.spec.ts +146 -0
- package/tests/unit/aio/prompt.spec.ts +111 -0
- package/tests/unit/basic/error.spec.ts +16 -4
- package/tests/unit/basic/promise.spec.ts +158 -50
- package/tests/unit/basic/schedule.spec.ts +74 -0
- package/tests/unit/basic/stream.spec.ts +90 -37
- package/tests/unit/credential/api-key.spec.ts +36 -0
- package/tests/unit/credential/bearer.spec.ts +23 -0
- package/tests/unit/credential/json-web-token.spec.ts +23 -0
- package/tests/unit/credential/password.spec.ts +40 -0
- package/tests/unit/cron/cron.spec.ts +84 -0
- package/tests/unit/event/class-event-proxy.spec.ts +3 -3
- package/tests/unit/event/event-manager.spec.ts +3 -3
- package/tests/unit/event/instance-event-proxy.spec.ts +3 -3
- package/tests/unit/exception/error/error.spec.ts +83 -0
- package/tests/unit/exception/error/match.spec.ts +81 -0
- package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
- package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
- package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
- package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
- package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
- package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
- package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
- package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
- package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
- package/tests/unit/http/api/api-core-host.spec.ts +207 -0
- package/tests/unit/http/api/api-schema.spec.ts +120 -0
- package/tests/unit/http/api/api-server.spec.ts +363 -0
- package/tests/unit/http/api/api-test.spec.ts +117 -0
- package/tests/unit/http/api/api.spec.ts +121 -0
- package/tests/unit/http/api-adapter/node-http.spec.ts +187 -0
- package/tests/unit/identifier/uuid.spec.ts +0 -1
- package/tests/unit/json/repair.spec.ts +11 -0
- package/tests/unit/log/logger.spec.ts +19 -4
- package/tests/unit/openai/openai.spec.ts +64 -0
- package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
- package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
- package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
- package/tests/unit/random/base.spec.ts +58 -0
- package/tests/unit/random/random-boolean.spec.ts +25 -0
- package/tests/unit/random/random-integer.spec.ts +32 -0
- package/tests/unit/random/random-number.spec.ts +33 -0
- package/tests/unit/random/random-string.spec.ts +22 -0
- package/tests/unit/request/fetch/browser.spec.ts +222 -0
- package/tests/unit/request/fetch/general.spec.ts +43 -0
- package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
- package/tests/unit/request/request/base.spec.ts +382 -0
- package/tests/unit/request/request/general.spec.ts +160 -0
- package/tests/unit/result/controller.spec.ts +82 -0
- package/tests/unit/result/either.spec.ts +377 -0
- package/tests/unit/result/generator.spec.ts +273 -0
- package/tests/unit/route/router/route.spec.ts +430 -0
- package/tests/unit/route/router/router.spec.ts +407 -0
- package/tests/unit/route/uri/hash.spec.ts +72 -0
- package/tests/unit/route/uri/pathname.spec.ts +146 -0
- package/tests/unit/route/uri/search.spec.ts +107 -0
- package/tests/unit/socket/client.spec.ts +208 -0
- package/tests/unit/socket/server.spec.ts +133 -0
- package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
- package/tests/unit/tube/helper.spec.ts +139 -0
- package/tests/unit/tube/tube.spec.ts +501 -0
- package/vite.config.ts +2 -1
- package/dist/index.js +0 -50
- package/dist/index.js.map +0 -209
- package/src/random/string.ts +0 -35
- package/tests/unit/random/string.spec.ts +0 -11
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createTaggedError,
|
|
5
|
+
matchTaggedError,
|
|
6
|
+
matchTaggedErrorPartial,
|
|
7
|
+
} from "#Source/exception/index.ts"
|
|
8
|
+
|
|
9
|
+
class NetworkError extends createTaggedError("Network")<{
|
|
10
|
+
message: string
|
|
11
|
+
status: number
|
|
12
|
+
}>() {
|
|
13
|
+
//
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class ValidationError extends createTaggedError("Validation")<{
|
|
17
|
+
message: string
|
|
18
|
+
field: string
|
|
19
|
+
}>() {
|
|
20
|
+
//
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type ExampleTaggedError =
|
|
24
|
+
| NetworkError
|
|
25
|
+
| ValidationError
|
|
26
|
+
|
|
27
|
+
test("matchTaggedError dispatches by tag and throws when a handler is missing", () => {
|
|
28
|
+
const example1 = new NetworkError({
|
|
29
|
+
message: "bad gateway",
|
|
30
|
+
status: 502,
|
|
31
|
+
}) as ExampleTaggedError
|
|
32
|
+
const example2 = new ValidationError({
|
|
33
|
+
message: "invalid email",
|
|
34
|
+
field: "email",
|
|
35
|
+
}) as ExampleTaggedError
|
|
36
|
+
const example3 = matchTaggedError(example1, {
|
|
37
|
+
Network: (error) => `${error.tag}:${error.data.status}`,
|
|
38
|
+
Validation: (error) => `${error.tag}:${error.data.field}`,
|
|
39
|
+
})
|
|
40
|
+
const example4 = matchTaggedError(example2, {
|
|
41
|
+
Network: (error) => `${error.tag}:${error.data.status}`,
|
|
42
|
+
Validation: (error) => `${error.tag}:${error.data.field}`,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
expect(example3).toBe("Network:502")
|
|
46
|
+
expect(example4).toBe("Validation:email")
|
|
47
|
+
expect(() => {
|
|
48
|
+
// @ts-expect-error Testing runtime error when handler is missing
|
|
49
|
+
return matchTaggedError(example2, {
|
|
50
|
+
Network: (error) => error.data.status,
|
|
51
|
+
})
|
|
52
|
+
}).toThrow("No handler for tag: Validation")
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test("matchTaggedErrorPartial uses a fallback for unhandled tags", () => {
|
|
56
|
+
const example1 = new NetworkError({
|
|
57
|
+
message: "bad gateway",
|
|
58
|
+
status: 502,
|
|
59
|
+
}) as ExampleTaggedError
|
|
60
|
+
const example2 = new ValidationError({
|
|
61
|
+
message: "invalid email",
|
|
62
|
+
field: "email",
|
|
63
|
+
}) as ExampleTaggedError
|
|
64
|
+
const example3 = matchTaggedErrorPartial(
|
|
65
|
+
example1,
|
|
66
|
+
{
|
|
67
|
+
Network: (error) => `${error.tag}:${error.data.status}`,
|
|
68
|
+
},
|
|
69
|
+
(error) => `${error.tag}:${error.message}`,
|
|
70
|
+
)
|
|
71
|
+
const example4 = matchTaggedErrorPartial(
|
|
72
|
+
example2,
|
|
73
|
+
{
|
|
74
|
+
Network: (error) => `${error.tag}:${error.data.status}`,
|
|
75
|
+
},
|
|
76
|
+
(error) => `${error.tag}:${error.data.field}`,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
expect(example3).toBe("Network:502")
|
|
80
|
+
expect(example4).toBe("Validation:email")
|
|
81
|
+
})
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { expect, test, vi } from "vitest"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
BaseInputorContext,
|
|
5
|
+
BaseInputorControllerOptions,
|
|
6
|
+
BaseInputorSchema,
|
|
7
|
+
} from "#Source/form/index.ts"
|
|
8
|
+
import { BaseInputorController } from "#Source/form/index.ts"
|
|
9
|
+
|
|
10
|
+
const TEST_INPUTOR_TYPE_NAME = "test" as const
|
|
11
|
+
|
|
12
|
+
type TestExternalValue = string | undefined
|
|
13
|
+
type TestInternalValue = string | undefined
|
|
14
|
+
|
|
15
|
+
interface TestInputorSchema extends BaseInputorSchema<TestExternalValue> {
|
|
16
|
+
inputorTypeName: typeof TEST_INPUTOR_TYPE_NAME
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface TestInputorContext extends BaseInputorContext<TestExternalValue, TestInternalValue> {
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface TestInputorControllerOptions extends BaseInputorControllerOptions<TestExternalValue, TestInputorSchema> {
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class TestInputorController extends BaseInputorController<
|
|
26
|
+
TestExternalValue,
|
|
27
|
+
TestInternalValue,
|
|
28
|
+
TestInputorSchema,
|
|
29
|
+
TestInputorContext
|
|
30
|
+
> {
|
|
31
|
+
declare schemaType: TestInputorSchema
|
|
32
|
+
declare optionsType: TestInputorControllerOptions
|
|
33
|
+
declare constructorType: typeof TestInputorController
|
|
34
|
+
|
|
35
|
+
static inputorTypeName = TEST_INPUTOR_TYPE_NAME
|
|
36
|
+
|
|
37
|
+
inputorTypeName = TEST_INPUTOR_TYPE_NAME
|
|
38
|
+
protected voidExternalValue = undefined
|
|
39
|
+
protected voidInternalValue = undefined
|
|
40
|
+
|
|
41
|
+
protected override async constrainExternalValue(value: TestExternalValue): Promise<TestExternalValue> {
|
|
42
|
+
if (value === undefined) {
|
|
43
|
+
return await Promise.resolve(undefined)
|
|
44
|
+
}
|
|
45
|
+
return await Promise.resolve(value.trim())
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected override async constrainInternalValue(value: TestInternalValue): Promise<TestInternalValue> {
|
|
49
|
+
if (value === undefined) {
|
|
50
|
+
return await Promise.resolve(undefined)
|
|
51
|
+
}
|
|
52
|
+
return await Promise.resolve(value.trim())
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const createTestInputor = (
|
|
57
|
+
overrides: Partial<TestInputorControllerOptions> = {},
|
|
58
|
+
): TestInputorController => {
|
|
59
|
+
return new TestInputorController({
|
|
60
|
+
id: "test-id",
|
|
61
|
+
name: "test-name",
|
|
62
|
+
placeholder: "test-placeholder",
|
|
63
|
+
value: " initial ",
|
|
64
|
+
...overrides,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
test("BaseInputorController.isReady and waitForReady initialize defaults and emit initial hooks", async () => {
|
|
69
|
+
const valueChanges: Array<{ newValue: TestExternalValue; oldValue: TestExternalValue }> = []
|
|
70
|
+
const schemaChanges: Array<{ newSchema: TestInputorSchema; oldSchema: TestInputorSchema }> = []
|
|
71
|
+
const controller = createTestInputor({
|
|
72
|
+
onValueChange: (context) => {
|
|
73
|
+
valueChanges.push(context)
|
|
74
|
+
},
|
|
75
|
+
onSchemaChange: (context) => {
|
|
76
|
+
schemaChanges.push(context)
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
expect(controller.isReady()).toBe(false)
|
|
81
|
+
|
|
82
|
+
await controller.waitForReady()
|
|
83
|
+
|
|
84
|
+
expect(controller.isReady()).toBe(true)
|
|
85
|
+
expect(await controller.getSchema()).toEqual({
|
|
86
|
+
inputorTypeName: TEST_INPUTOR_TYPE_NAME,
|
|
87
|
+
id: "test-id",
|
|
88
|
+
name: "test-name",
|
|
89
|
+
placeholder: "test-placeholder",
|
|
90
|
+
value: "initial",
|
|
91
|
+
isVoid: false,
|
|
92
|
+
isFocused: false,
|
|
93
|
+
isTouched: false,
|
|
94
|
+
isDirty: false,
|
|
95
|
+
isDisabled: false,
|
|
96
|
+
isDebugMode: false,
|
|
97
|
+
})
|
|
98
|
+
expect(valueChanges).toEqual([
|
|
99
|
+
{
|
|
100
|
+
newValue: "initial",
|
|
101
|
+
oldValue: "initial",
|
|
102
|
+
},
|
|
103
|
+
])
|
|
104
|
+
expect(schemaChanges).toHaveLength(1)
|
|
105
|
+
expect(schemaChanges[0]!.newSchema).toEqual(schemaChanges[0]!.oldSchema)
|
|
106
|
+
expect(schemaChanges[0]!.newSchema.value).toBe("initial")
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test("BaseInputorController.getInternalValue, getContext, and isEqualSchema expose current state", async () => {
|
|
110
|
+
const controller = createTestInputor({
|
|
111
|
+
value: " alpha ",
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
await controller.waitForReady()
|
|
115
|
+
|
|
116
|
+
expect(controller.getInternalValue()).toBe("alpha")
|
|
117
|
+
expect(await controller.getContext()).toEqual({
|
|
118
|
+
inputorTypeName: TEST_INPUTOR_TYPE_NAME,
|
|
119
|
+
id: "test-id",
|
|
120
|
+
name: "test-name",
|
|
121
|
+
placeholder: "test-placeholder",
|
|
122
|
+
value: "alpha",
|
|
123
|
+
isVoid: false,
|
|
124
|
+
isFocused: false,
|
|
125
|
+
isTouched: false,
|
|
126
|
+
isDirty: false,
|
|
127
|
+
isDisabled: false,
|
|
128
|
+
isDebugMode: false,
|
|
129
|
+
internalValue: "alpha",
|
|
130
|
+
isReady: true,
|
|
131
|
+
})
|
|
132
|
+
expect(await controller.isEqualSchema({ value: "alpha", placeholder: "test-placeholder" })).toBe(true)
|
|
133
|
+
expect(await controller.isEqualSchema({ value: "beta" })).toBe(false)
|
|
134
|
+
expect(await controller.isEqualSchema(null)).toBe(false)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test("BaseInputorController.subscribeInputChange and updateInputValue emit input updates after debounce", async () => {
|
|
138
|
+
vi.useFakeTimers()
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const controller = createTestInputor({
|
|
142
|
+
value: "start",
|
|
143
|
+
inputDebounce: 20,
|
|
144
|
+
})
|
|
145
|
+
const inputChanges: Array<{ newInput: TestExternalValue; oldInput: TestExternalValue; oldValue: TestExternalValue }> = []
|
|
146
|
+
|
|
147
|
+
await controller.waitForReady()
|
|
148
|
+
controller.subscribeInputChange((context) => {
|
|
149
|
+
inputChanges.push(context)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
await controller.updateInputValue(" next ")
|
|
153
|
+
|
|
154
|
+
expect(inputChanges).toEqual([])
|
|
155
|
+
|
|
156
|
+
await vi.advanceTimersByTimeAsync(20)
|
|
157
|
+
|
|
158
|
+
expect(inputChanges).toEqual([
|
|
159
|
+
{
|
|
160
|
+
newInput: " next ",
|
|
161
|
+
oldInput: "start",
|
|
162
|
+
oldValue: "start",
|
|
163
|
+
},
|
|
164
|
+
])
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
vi.useRealTimers()
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
test("BaseInputorController.unsubscribeInputChange removes one input subscriber", async () => {
|
|
172
|
+
vi.useFakeTimers()
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
const controller = createTestInputor({ value: "start" })
|
|
176
|
+
let calls = 0
|
|
177
|
+
const subscriber = (): void => {
|
|
178
|
+
calls = calls + 1
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await controller.waitForReady()
|
|
182
|
+
controller.subscribeInputChange(subscriber)
|
|
183
|
+
controller.unsubscribeInputChange(subscriber)
|
|
184
|
+
|
|
185
|
+
await controller.updateInputValue("next")
|
|
186
|
+
await vi.advanceTimersByTimeAsync(0)
|
|
187
|
+
|
|
188
|
+
expect(calls).toBe(0)
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
vi.useRealTimers()
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test("BaseInputorController.clearInputChangeSubscribers removes all input subscribers", async () => {
|
|
196
|
+
vi.useFakeTimers()
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const controller = createTestInputor({ value: "start" })
|
|
200
|
+
let calls = 0
|
|
201
|
+
|
|
202
|
+
await controller.waitForReady()
|
|
203
|
+
controller.subscribeInputChange(() => {
|
|
204
|
+
calls = calls + 1
|
|
205
|
+
})
|
|
206
|
+
controller.subscribeInputChange(() => {
|
|
207
|
+
calls = calls + 1
|
|
208
|
+
})
|
|
209
|
+
controller.clearInputChangeSubscribers()
|
|
210
|
+
|
|
211
|
+
await controller.updateInputValue("next")
|
|
212
|
+
await vi.advanceTimersByTimeAsync(0)
|
|
213
|
+
|
|
214
|
+
expect(calls).toBe(0)
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
vi.useRealTimers()
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test("BaseInputorController.subscribeValueChange, applyInputValue, and updateValue emit value changes", async () => {
|
|
222
|
+
const controller = createTestInputor({ value: "start" })
|
|
223
|
+
const valueChanges: Array<{ newValue: TestExternalValue; oldValue: TestExternalValue }> = []
|
|
224
|
+
|
|
225
|
+
await controller.waitForReady()
|
|
226
|
+
controller.subscribeValueChange((context) => {
|
|
227
|
+
valueChanges.push(context)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
await controller.updateInputValue(" next ")
|
|
231
|
+
await controller.applyInputValue()
|
|
232
|
+
await controller.updateValue(" final ")
|
|
233
|
+
|
|
234
|
+
expect(valueChanges).toEqual([
|
|
235
|
+
{
|
|
236
|
+
newValue: "next",
|
|
237
|
+
oldValue: "start",
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
newValue: "final",
|
|
241
|
+
oldValue: "next",
|
|
242
|
+
},
|
|
243
|
+
])
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
test("BaseInputorController.unsubscribeValueChange removes one value subscriber", async () => {
|
|
247
|
+
const controller = createTestInputor({ value: "start" })
|
|
248
|
+
let calls = 0
|
|
249
|
+
const subscriber = (): void => {
|
|
250
|
+
calls = calls + 1
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
await controller.waitForReady()
|
|
254
|
+
controller.subscribeValueChange(subscriber)
|
|
255
|
+
controller.unsubscribeValueChange(subscriber)
|
|
256
|
+
await controller.updateValue("next")
|
|
257
|
+
|
|
258
|
+
expect(calls).toBe(0)
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test("BaseInputorController.clearValueChangeSubscribers removes all value subscribers", async () => {
|
|
262
|
+
const controller = createTestInputor({ value: "start" })
|
|
263
|
+
let calls = 0
|
|
264
|
+
|
|
265
|
+
await controller.waitForReady()
|
|
266
|
+
controller.subscribeValueChange(() => {
|
|
267
|
+
calls = calls + 1
|
|
268
|
+
})
|
|
269
|
+
controller.subscribeValueChange(() => {
|
|
270
|
+
calls = calls + 1
|
|
271
|
+
})
|
|
272
|
+
controller.clearValueChangeSubscribers()
|
|
273
|
+
await controller.updateValue("next")
|
|
274
|
+
|
|
275
|
+
expect(calls).toBe(0)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
test("BaseInputorController.subscribeSchemaChange and updatePlaceholder emit schema changes", async () => {
|
|
279
|
+
const controller = createTestInputor({ value: "start" })
|
|
280
|
+
const schemaChanges: Array<{ newSchema: TestInputorSchema; oldSchema: TestInputorSchema }> = []
|
|
281
|
+
|
|
282
|
+
await controller.waitForReady()
|
|
283
|
+
await Promise.resolve()
|
|
284
|
+
controller.subscribeSchemaChange((context) => {
|
|
285
|
+
schemaChanges.push(context)
|
|
286
|
+
})
|
|
287
|
+
await controller.updatePlaceholder("next-placeholder")
|
|
288
|
+
|
|
289
|
+
expect(schemaChanges.length).toBeGreaterThanOrEqual(1)
|
|
290
|
+
expect(schemaChanges.at(-1)!.oldSchema.placeholder).toBe("test-placeholder")
|
|
291
|
+
expect(schemaChanges.at(-1)!.newSchema.placeholder).toBe("next-placeholder")
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
test("BaseInputorController.unsubscribeSchemaChange removes one schema subscriber", async () => {
|
|
295
|
+
const controller = createTestInputor({ value: "start" })
|
|
296
|
+
let calls = 0
|
|
297
|
+
const subscriber = (): void => {
|
|
298
|
+
calls = calls + 1
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
await controller.waitForReady()
|
|
302
|
+
controller.subscribeSchemaChange(subscriber)
|
|
303
|
+
controller.unsubscribeSchemaChange(subscriber)
|
|
304
|
+
await controller.updatePlaceholder("next-placeholder")
|
|
305
|
+
|
|
306
|
+
expect(calls).toBe(0)
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
test("BaseInputorController.clearSchemaChangeSubscribers removes all schema subscribers", async () => {
|
|
310
|
+
const controller = createTestInputor({ value: "start" })
|
|
311
|
+
let calls = 0
|
|
312
|
+
|
|
313
|
+
await controller.waitForReady()
|
|
314
|
+
controller.subscribeSchemaChange(() => {
|
|
315
|
+
calls = calls + 1
|
|
316
|
+
})
|
|
317
|
+
controller.subscribeSchemaChange(() => {
|
|
318
|
+
calls = calls + 1
|
|
319
|
+
})
|
|
320
|
+
controller.clearSchemaChangeSubscribers()
|
|
321
|
+
await controller.updatePlaceholder("next-placeholder")
|
|
322
|
+
|
|
323
|
+
expect(calls).toBe(0)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
test("BaseInputorController.updateIsVoid resets the value to its void value", async () => {
|
|
327
|
+
const controller = createTestInputor({ value: "start" })
|
|
328
|
+
|
|
329
|
+
await controller.waitForReady()
|
|
330
|
+
await controller.updateIsVoid(true)
|
|
331
|
+
|
|
332
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
333
|
+
value: undefined,
|
|
334
|
+
isVoid: true,
|
|
335
|
+
isDirty: true,
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
test("BaseInputorController.updateIsFocused also marks the controller as touched", async () => {
|
|
340
|
+
const controller = createTestInputor({ value: "start" })
|
|
341
|
+
|
|
342
|
+
await controller.waitForReady()
|
|
343
|
+
await controller.updateIsFocused(true)
|
|
344
|
+
|
|
345
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
346
|
+
isFocused: true,
|
|
347
|
+
isTouched: true,
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
test("BaseInputorController.updateIsTouched updates touched state directly", async () => {
|
|
352
|
+
const controller = createTestInputor({ value: "start" })
|
|
353
|
+
|
|
354
|
+
await controller.waitForReady()
|
|
355
|
+
await controller.updateIsTouched(true)
|
|
356
|
+
|
|
357
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
358
|
+
isTouched: true,
|
|
359
|
+
})
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
test("BaseInputorController.updateIsDirty updates dirty state directly", async () => {
|
|
363
|
+
const controller = createTestInputor({ value: "start" })
|
|
364
|
+
|
|
365
|
+
await controller.waitForReady()
|
|
366
|
+
await controller.updateIsDirty(true)
|
|
367
|
+
|
|
368
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
369
|
+
isDirty: true,
|
|
370
|
+
})
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
test("BaseInputorController.updateIsDisabled updates disabled state directly", async () => {
|
|
374
|
+
const controller = createTestInputor({ value: "start" })
|
|
375
|
+
|
|
376
|
+
await controller.waitForReady()
|
|
377
|
+
await controller.updateIsDisabled(true)
|
|
378
|
+
|
|
379
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
380
|
+
isDisabled: true,
|
|
381
|
+
})
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
test("BaseInputorController.updateIsDebugMode updates debug mode directly", async () => {
|
|
385
|
+
const controller = createTestInputor({ value: "start" })
|
|
386
|
+
|
|
387
|
+
await controller.waitForReady()
|
|
388
|
+
await controller.updateIsDebugMode(true)
|
|
389
|
+
|
|
390
|
+
expect(await controller.getSchema()).toMatchObject({
|
|
391
|
+
isDebugMode: true,
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
test("BaseInputorController.updateSchema applies multiple schema fields in one pass", async () => {
|
|
396
|
+
const controller = createTestInputor({ value: "start" })
|
|
397
|
+
|
|
398
|
+
await controller.waitForReady()
|
|
399
|
+
await controller.updateSchema({
|
|
400
|
+
...(await controller.getSchema()),
|
|
401
|
+
placeholder: "schema-placeholder",
|
|
402
|
+
value: " schema-value ",
|
|
403
|
+
isFocused: true,
|
|
404
|
+
isTouched: true,
|
|
405
|
+
isDirty: true,
|
|
406
|
+
isDisabled: true,
|
|
407
|
+
isDebugMode: true,
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
expect(await controller.getSchema()).toEqual({
|
|
411
|
+
inputorTypeName: TEST_INPUTOR_TYPE_NAME,
|
|
412
|
+
id: "test-id",
|
|
413
|
+
name: "test-name",
|
|
414
|
+
placeholder: "schema-placeholder",
|
|
415
|
+
value: "schema-value",
|
|
416
|
+
isVoid: false,
|
|
417
|
+
isFocused: true,
|
|
418
|
+
isTouched: true,
|
|
419
|
+
isDirty: true,
|
|
420
|
+
isDisabled: true,
|
|
421
|
+
isDebugMode: true,
|
|
422
|
+
})
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
test("BaseInputorController.destroy clears every subscriber collection", async () => {
|
|
426
|
+
vi.useFakeTimers()
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
const controller = createTestInputor({ value: "start" })
|
|
430
|
+
let inputCalls = 0
|
|
431
|
+
let valueCalls = 0
|
|
432
|
+
let schemaCalls = 0
|
|
433
|
+
|
|
434
|
+
await controller.waitForReady()
|
|
435
|
+
controller.subscribeInputChange(() => {
|
|
436
|
+
inputCalls = inputCalls + 1
|
|
437
|
+
})
|
|
438
|
+
controller.subscribeValueChange(() => {
|
|
439
|
+
valueCalls = valueCalls + 1
|
|
440
|
+
})
|
|
441
|
+
controller.subscribeSchemaChange(() => {
|
|
442
|
+
schemaCalls = schemaCalls + 1
|
|
443
|
+
})
|
|
444
|
+
controller.destroy()
|
|
445
|
+
|
|
446
|
+
await controller.updateInputValue("next")
|
|
447
|
+
await vi.advanceTimersByTimeAsync(0)
|
|
448
|
+
await controller.updateValue("final")
|
|
449
|
+
await controller.updatePlaceholder("after-destroy")
|
|
450
|
+
|
|
451
|
+
expect(inputCalls).toBe(0)
|
|
452
|
+
expect(valueCalls).toBe(0)
|
|
453
|
+
expect(schemaCalls).toBe(0)
|
|
454
|
+
}
|
|
455
|
+
finally {
|
|
456
|
+
vi.useRealTimers()
|
|
457
|
+
}
|
|
458
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BOOLEAN_INPUTOR_TYPE_NAME,
|
|
5
|
+
BooleanInputorController,
|
|
6
|
+
} from "#Source/form/index.ts"
|
|
7
|
+
|
|
8
|
+
test("BooleanInputorController.getSchema exposes boolean schema state and updateValue toggles it", async () => {
|
|
9
|
+
const controller = new BooleanInputorController({
|
|
10
|
+
id: "boolean-id",
|
|
11
|
+
value: false,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
await controller.waitForReady()
|
|
15
|
+
await controller.updateValue(true)
|
|
16
|
+
|
|
17
|
+
expect(await controller.getSchema()).toEqual({
|
|
18
|
+
inputorTypeName: BOOLEAN_INPUTOR_TYPE_NAME,
|
|
19
|
+
id: "boolean-id",
|
|
20
|
+
name: `boolean-boolean-id`,
|
|
21
|
+
placeholder: "",
|
|
22
|
+
value: true,
|
|
23
|
+
isVoid: false,
|
|
24
|
+
isFocused: false,
|
|
25
|
+
isTouched: false,
|
|
26
|
+
isDirty: true,
|
|
27
|
+
isDisabled: false,
|
|
28
|
+
isDebugMode: false,
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FILE_INPUTOR_TYPE_NAME,
|
|
5
|
+
FileInputorController,
|
|
6
|
+
} from "#Source/form/index.ts"
|
|
7
|
+
|
|
8
|
+
test("FileInputorController.getSchema stores file values and reports file metadata", async () => {
|
|
9
|
+
const file = new File(["alpha"], "alpha.txt", {
|
|
10
|
+
type: "text/plain",
|
|
11
|
+
})
|
|
12
|
+
const controller = new FileInputorController({
|
|
13
|
+
id: "file-id",
|
|
14
|
+
value: file,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
await controller.waitForReady()
|
|
18
|
+
|
|
19
|
+
const schema = await controller.getSchema()
|
|
20
|
+
|
|
21
|
+
expect(schema.inputorTypeName).toBe(FILE_INPUTOR_TYPE_NAME)
|
|
22
|
+
expect(schema.id).toBe("file-id")
|
|
23
|
+
expect(schema.name).toBe("file-file-id")
|
|
24
|
+
expect(schema.value?.name).toBe("alpha.txt")
|
|
25
|
+
expect(schema.value?.type).toBe("text/plain")
|
|
26
|
+
expect(schema.isDirty).toBe(false)
|
|
27
|
+
})
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FormInputorController,
|
|
5
|
+
NumberInputorController,
|
|
6
|
+
TextInputorController,
|
|
7
|
+
} from "#Source/form/index.ts"
|
|
8
|
+
|
|
9
|
+
const createItems = (): {
|
|
10
|
+
name: TextInputorController
|
|
11
|
+
age: NumberInputorController
|
|
12
|
+
} => {
|
|
13
|
+
return {
|
|
14
|
+
name: new TextInputorController({
|
|
15
|
+
id: "form-name-id",
|
|
16
|
+
value: "alpha",
|
|
17
|
+
}),
|
|
18
|
+
age: new NumberInputorController({
|
|
19
|
+
id: "form-age-id",
|
|
20
|
+
value: 1,
|
|
21
|
+
min: 0,
|
|
22
|
+
max: 99,
|
|
23
|
+
}),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
test("FormInputorController.updateValue decodes external values into child items", async () => {
|
|
28
|
+
const items = createItems()
|
|
29
|
+
const controller = new FormInputorController<
|
|
30
|
+
{ name: string | undefined; age: number | undefined },
|
|
31
|
+
typeof items
|
|
32
|
+
>({
|
|
33
|
+
id: "form-id",
|
|
34
|
+
value: {
|
|
35
|
+
name: "alpha",
|
|
36
|
+
age: 1,
|
|
37
|
+
},
|
|
38
|
+
items,
|
|
39
|
+
encodeValue: (schemaDict) => {
|
|
40
|
+
return {
|
|
41
|
+
name: schemaDict.name.value,
|
|
42
|
+
age: schemaDict.age.value,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
decodeValue: (value) => {
|
|
46
|
+
return {
|
|
47
|
+
name: value.name,
|
|
48
|
+
age: value.age,
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
await Promise.all([
|
|
54
|
+
items.name.waitForReady(),
|
|
55
|
+
items.age.waitForReady(),
|
|
56
|
+
controller.waitForReady(),
|
|
57
|
+
])
|
|
58
|
+
await controller.updateValue({
|
|
59
|
+
name: "beta",
|
|
60
|
+
age: 8,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
expect((await items.name.getSchema()).value).toBe("beta")
|
|
64
|
+
expect((await items.age.getSchema()).value).toBe(8)
|
|
65
|
+
expect((await controller.getSchema()).value).toEqual({
|
|
66
|
+
name: "beta",
|
|
67
|
+
age: 8,
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("FormInputorController reacts to child schema changes through encodeValue", async () => {
|
|
72
|
+
const items = createItems()
|
|
73
|
+
const controller = new FormInputorController<
|
|
74
|
+
{ name: string | undefined; age: number | undefined },
|
|
75
|
+
typeof items
|
|
76
|
+
>({
|
|
77
|
+
id: "form-id",
|
|
78
|
+
value: {
|
|
79
|
+
name: "alpha",
|
|
80
|
+
age: 1,
|
|
81
|
+
},
|
|
82
|
+
items,
|
|
83
|
+
encodeValue: (schemaDict) => {
|
|
84
|
+
return {
|
|
85
|
+
name: schemaDict.name.value,
|
|
86
|
+
age: schemaDict.age.value,
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
decodeValue: (value) => {
|
|
90
|
+
return {
|
|
91
|
+
name: value.name,
|
|
92
|
+
age: value.age,
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await Promise.all([
|
|
98
|
+
items.name.waitForReady(),
|
|
99
|
+
items.age.waitForReady(),
|
|
100
|
+
controller.waitForReady(),
|
|
101
|
+
])
|
|
102
|
+
await Promise.resolve()
|
|
103
|
+
|
|
104
|
+
const nextFormValue = new Promise<{ name: string | undefined; age: number | undefined }>((resolve) => {
|
|
105
|
+
controller.subscribeValueChange((context) => {
|
|
106
|
+
resolve(context.newValue)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
await items.name.updateValue("gamma")
|
|
111
|
+
|
|
112
|
+
expect(await nextFormValue).toEqual({
|
|
113
|
+
name: "gamma",
|
|
114
|
+
age: 1,
|
|
115
|
+
})
|
|
116
|
+
expect((await controller.getSchema()).value).toEqual({
|
|
117
|
+
name: "gamma",
|
|
118
|
+
age: 1,
|
|
119
|
+
})
|
|
120
|
+
})
|