@ic-reactor/candid 3.0.8-beta.2 → 3.0.10-beta.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata-display-reactor.d.ts +4 -4
- package/dist/metadata-display-reactor.d.ts.map +1 -1
- package/dist/metadata-display-reactor.js +1 -1
- package/dist/metadata-display-reactor.js.map +1 -1
- package/dist/visitor/returns/index.d.ts +23 -71
- package/dist/visitor/returns/index.d.ts.map +1 -1
- package/dist/visitor/returns/index.js +156 -306
- package/dist/visitor/returns/index.js.map +1 -1
- package/dist/visitor/returns/types.d.ts +77 -120
- package/dist/visitor/returns/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/metadata-display-reactor.ts +8 -8
- package/src/visitor/returns/index.test.ts +323 -390
- package/src/visitor/returns/index.ts +239 -385
- package/src/visitor/returns/types.ts +96 -200
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest"
|
|
2
|
-
import { IDL } from "
|
|
2
|
+
import { IDL } from "../types"
|
|
3
3
|
import { ResultFieldVisitor } from "./index"
|
|
4
4
|
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
ResultNode,
|
|
6
|
+
ResolvedNode,
|
|
7
|
+
RecordNode,
|
|
8
|
+
VariantNode,
|
|
9
|
+
TupleNode,
|
|
10
|
+
OptionalNode,
|
|
11
|
+
VectorNode,
|
|
12
|
+
BlobNode,
|
|
13
|
+
RecursiveNode,
|
|
14
|
+
NumberNode,
|
|
15
|
+
TextNode,
|
|
16
|
+
PrincipalNode,
|
|
17
|
+
BooleanNode,
|
|
18
|
+
NullNode,
|
|
19
|
+
MethodMeta,
|
|
20
|
+
ServiceMeta,
|
|
20
21
|
} from "./types"
|
|
21
22
|
|
|
22
23
|
describe("ResultFieldVisitor", () => {
|
|
@@ -35,33 +36,33 @@ describe("ResultFieldVisitor", () => {
|
|
|
35
36
|
expect(field.label).toBe("message")
|
|
36
37
|
expect(field.candidType).toBe("text")
|
|
37
38
|
expect(field.displayType).toBe("string")
|
|
38
|
-
expect(field.
|
|
39
|
+
expect(field.format).toBe("plain")
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
it("should handle text with special label detection", () => {
|
|
42
43
|
const emailField = visitor.visitText(IDL.Text, "email")
|
|
43
|
-
expect(emailField.
|
|
44
|
+
expect(emailField.format).toBe("email")
|
|
44
45
|
|
|
45
46
|
const urlField = visitor.visitText(IDL.Text, "website_url")
|
|
46
|
-
expect(urlField.
|
|
47
|
+
expect(urlField.format).toBe("url")
|
|
47
48
|
|
|
48
49
|
const phoneField = visitor.visitText(IDL.Text, "phone_number")
|
|
49
|
-
expect(phoneField.
|
|
50
|
+
expect(phoneField.format).toBe("phone")
|
|
50
51
|
|
|
51
52
|
const uuidField = visitor.visitText(IDL.Text, "transaction_uuid")
|
|
52
|
-
expect(uuidField.
|
|
53
|
+
expect(uuidField.format).toBe("uuid")
|
|
53
54
|
|
|
54
55
|
const btcField = visitor.visitText(IDL.Text, "btc_address")
|
|
55
|
-
expect(btcField.
|
|
56
|
+
expect(btcField.format).toBe("btc")
|
|
56
57
|
|
|
57
58
|
const ethField = visitor.visitText(IDL.Text, "ethereum_address")
|
|
58
|
-
expect(ethField.
|
|
59
|
+
expect(ethField.format).toBe("eth")
|
|
59
60
|
|
|
60
61
|
const accountIdField = visitor.visitText(IDL.Text, "account_id")
|
|
61
|
-
expect(accountIdField.
|
|
62
|
+
expect(accountIdField.format).toBe("account-id")
|
|
62
63
|
|
|
63
64
|
const principalField = visitor.visitText(IDL.Text, "canister_id")
|
|
64
|
-
expect(principalField.
|
|
65
|
+
expect(principalField.format).toBe("principal")
|
|
65
66
|
})
|
|
66
67
|
|
|
67
68
|
it("should handle bool type", () => {
|
|
@@ -106,7 +107,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
106
107
|
expect(field.type).toBe("number")
|
|
107
108
|
expect(field.candidType).toBe("nat")
|
|
108
109
|
expect(field.displayType).toBe("string") // BigInt → string
|
|
109
|
-
expect(field.
|
|
110
|
+
expect(field.format).toBe("normal")
|
|
110
111
|
})
|
|
111
112
|
|
|
112
113
|
it("should map int to string display type", () => {
|
|
@@ -191,30 +192,30 @@ describe("ResultFieldVisitor", () => {
|
|
|
191
192
|
describe("Number format detection", () => {
|
|
192
193
|
it("should detect timestamp format from label", () => {
|
|
193
194
|
const timestampField = visitor.visitFixedNat(IDL.Nat64, "created_at")
|
|
194
|
-
expect(timestampField.
|
|
195
|
+
expect(timestampField.format).toBe("timestamp")
|
|
195
196
|
|
|
196
197
|
const dateField = visitor.visitNat(IDL.Nat, "timestamp_nanos")
|
|
197
|
-
expect(dateField.
|
|
198
|
+
expect(dateField.format).toBe("timestamp")
|
|
198
199
|
|
|
199
200
|
const deadlineField = visitor.visitNat(IDL.Nat, "deadline")
|
|
200
|
-
expect(deadlineField.
|
|
201
|
+
expect(deadlineField.format).toBe("timestamp")
|
|
201
202
|
})
|
|
202
203
|
|
|
203
204
|
it("should detect cycle format from label", () => {
|
|
204
205
|
const cycleField = visitor.visitNat(IDL.Nat, "cycles")
|
|
205
|
-
expect(cycleField.
|
|
206
|
+
expect(cycleField.format).toBe("cycle")
|
|
206
207
|
|
|
207
208
|
// "cycle" as standalone word
|
|
208
209
|
const cycleSingleField = visitor.visitNat(IDL.Nat, "cycle")
|
|
209
|
-
expect(cycleSingleField.
|
|
210
|
+
expect(cycleSingleField.format).toBe("cycle")
|
|
210
211
|
})
|
|
211
212
|
|
|
212
213
|
it("should default to normal format", () => {
|
|
213
214
|
const amountField = visitor.visitNat(IDL.Nat, "amount")
|
|
214
|
-
expect(amountField.
|
|
215
|
+
expect(amountField.format).toBe("normal")
|
|
215
216
|
|
|
216
217
|
const countField = visitor.visitNat(IDL.Nat, "count")
|
|
217
|
-
expect(countField.
|
|
218
|
+
expect(countField.format).toBe("normal")
|
|
218
219
|
})
|
|
219
220
|
})
|
|
220
221
|
})
|
|
@@ -242,15 +243,15 @@ describe("ResultFieldVisitor", () => {
|
|
|
242
243
|
expect(field.label).toBe("person")
|
|
243
244
|
expect(field.candidType).toBe("record")
|
|
244
245
|
expect(field.displayType).toBe("object")
|
|
245
|
-
expect(field.fields).toHaveLength(2)
|
|
246
|
+
expect(Object.keys(field.fields)).toHaveLength(2)
|
|
246
247
|
|
|
247
|
-
const nameField = field.fields
|
|
248
|
+
const nameField = field.fields["name"]
|
|
248
249
|
if (!nameField || nameField.type !== "text") {
|
|
249
250
|
throw new Error("Name field not found or not text")
|
|
250
251
|
}
|
|
251
252
|
expect(nameField.displayType).toBe("string")
|
|
252
253
|
|
|
253
|
-
const ageField = field.fields
|
|
254
|
+
const ageField = field.fields["age"]
|
|
254
255
|
if (!ageField || ageField.type !== "number") {
|
|
255
256
|
throw new Error("Age field not found or not number")
|
|
256
257
|
}
|
|
@@ -277,14 +278,14 @@ describe("ResultFieldVisitor", () => {
|
|
|
277
278
|
|
|
278
279
|
expect(field.type).toBe("record")
|
|
279
280
|
|
|
280
|
-
const addressField = field.fields
|
|
281
|
+
const addressField = field.fields["address"] as RecordNode
|
|
281
282
|
if (!addressField || addressField.type !== "record") {
|
|
282
283
|
throw new Error("Address field not found or not a record")
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
expect(addressField.type).toBe("record")
|
|
286
287
|
expect(addressField.displayType).toBe("object")
|
|
287
|
-
expect(addressField.fields).toHaveLength(2)
|
|
288
|
+
expect(Object.keys(addressField.fields)).toHaveLength(2)
|
|
288
289
|
})
|
|
289
290
|
|
|
290
291
|
it("should handle ICRC-1 account record", () => {
|
|
@@ -303,22 +304,23 @@ describe("ResultFieldVisitor", () => {
|
|
|
303
304
|
|
|
304
305
|
expect(field.type).toBe("record")
|
|
305
306
|
|
|
306
|
-
const ownerField = field.fields
|
|
307
|
+
const ownerField = field.fields["owner"]
|
|
307
308
|
if (!ownerField || ownerField.type !== "principal") {
|
|
308
309
|
throw new Error("Owner field not found or not principal")
|
|
309
310
|
}
|
|
310
311
|
expect(ownerField.type).toBe("principal")
|
|
311
312
|
expect(ownerField.displayType).toBe("string")
|
|
312
313
|
|
|
313
|
-
const subaccountField = field.fields
|
|
314
|
+
const subaccountField = field.fields["subaccount"] as OptionalNode
|
|
314
315
|
if (!subaccountField || subaccountField.type !== "optional") {
|
|
315
316
|
throw new Error("Subaccount field not found or not optional")
|
|
316
317
|
}
|
|
317
318
|
expect(subaccountField.type).toBe("optional")
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
// Resolve an example value to validate inner blob type
|
|
320
|
+
const subaccountResolved = subaccountField.resolve([
|
|
321
|
+
new Uint8Array([1, 2, 3]),
|
|
322
|
+
])
|
|
323
|
+
expect((subaccountResolved.value as ResolvedNode).type).toBe("blob")
|
|
322
324
|
})
|
|
323
325
|
})
|
|
324
326
|
|
|
@@ -342,10 +344,14 @@ describe("ResultFieldVisitor", () => {
|
|
|
342
344
|
expect(field.type).toBe("variant")
|
|
343
345
|
expect(field.candidType).toBe("variant")
|
|
344
346
|
expect(field.displayType).toBe("variant")
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
expect(
|
|
348
|
-
expect(
|
|
347
|
+
// Validate options by resolving each option
|
|
348
|
+
const resolvedActive = field.resolve({ Active: null })
|
|
349
|
+
expect(resolvedActive.selected).toBe("Active")
|
|
350
|
+
expect(resolvedActive.selectedOption.type).toBe("null")
|
|
351
|
+
const resolvedInactive = field.resolve({ Inactive: null })
|
|
352
|
+
expect(resolvedInactive.selected).toBe("Inactive")
|
|
353
|
+
const resolvedPending = field.resolve({ Pending: null })
|
|
354
|
+
expect(resolvedPending.selected).toBe("Pending")
|
|
349
355
|
})
|
|
350
356
|
|
|
351
357
|
it("should handle variant with payloads", () => {
|
|
@@ -385,26 +391,19 @@ describe("ResultFieldVisitor", () => {
|
|
|
385
391
|
)
|
|
386
392
|
|
|
387
393
|
expect(field.type).toBe("variant")
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (!transferField || transferField.type !== "record") {
|
|
398
|
-
throw new Error("Transfer field not found or not record")
|
|
399
|
-
}
|
|
400
|
-
expect(transferField.type).toBe("record")
|
|
401
|
-
expect(transferField.fields).toHaveLength(3)
|
|
394
|
+
// Validate Transfer payload
|
|
395
|
+
const transferResolved = field.resolve({
|
|
396
|
+
Transfer: { from: "aaaaa-aa", to: "bbbbb-bb", amount: BigInt(1) },
|
|
397
|
+
})
|
|
398
|
+
expect(transferResolved.selected).toBe("Transfer")
|
|
399
|
+
expect(transferResolved.selectedOption.type).toBe("record")
|
|
400
|
+
expect(
|
|
401
|
+
Object.keys((transferResolved.selectedOption as RecordNode).fields)
|
|
402
|
+
).toHaveLength(3)
|
|
402
403
|
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
expect(approveField.type).toBe("number")
|
|
404
|
+
const approveResolved = field.resolve({ Approve: BigInt(5) })
|
|
405
|
+
expect(approveResolved.selected).toBe("Approve")
|
|
406
|
+
expect(approveResolved.selectedOption.type).toBe("number")
|
|
408
407
|
})
|
|
409
408
|
|
|
410
409
|
it("should detect Result variant (Ok/Err)", () => {
|
|
@@ -423,20 +422,16 @@ describe("ResultFieldVisitor", () => {
|
|
|
423
422
|
|
|
424
423
|
expect(field.type).toBe("variant")
|
|
425
424
|
expect(field.displayType).toBe("result") // Special result type
|
|
426
|
-
expect(field.options).toContain("Ok")
|
|
427
|
-
expect(field.options).toContain("Err")
|
|
428
425
|
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
expect(okField.displayType).toBe("string")
|
|
426
|
+
const okResolved = field.resolve({ Ok: BigInt(1) })
|
|
427
|
+
expect(okResolved.selected).toBe("Ok")
|
|
428
|
+
expect(okResolved.selectedOption.type).toBe("number")
|
|
429
|
+
expect(okResolved.selectedOption.displayType).toBe("string")
|
|
434
430
|
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
expect(errField.displayType).toBe("string")
|
|
431
|
+
const errResolved = field.resolve({ Err: "error" })
|
|
432
|
+
expect(errResolved.selected).toBe("Err")
|
|
433
|
+
expect(errResolved.selectedOption.type).toBe("text")
|
|
434
|
+
expect(errResolved.selectedOption.displayType).toBe("string")
|
|
440
435
|
})
|
|
441
436
|
|
|
442
437
|
it("should detect complex Result variant", () => {
|
|
@@ -475,17 +470,15 @@ describe("ResultFieldVisitor", () => {
|
|
|
475
470
|
|
|
476
471
|
expect(field.displayType).toBe("result")
|
|
477
472
|
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
expect(
|
|
473
|
+
const okResolved = field.resolve({
|
|
474
|
+
Ok: { id: BigInt(1), data: new Uint8Array([1, 2, 3]) },
|
|
475
|
+
})
|
|
476
|
+
expect(okResolved.selected).toBe("Ok")
|
|
477
|
+
expect(okResolved.selectedOption.type).toBe("record")
|
|
483
478
|
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
expect(errField.type).toBe("variant")
|
|
479
|
+
const errResolved = field.resolve({ Err: { NotFound: null } })
|
|
480
|
+
expect(errResolved.selected).toBe("Err")
|
|
481
|
+
expect(errResolved.selectedOption.type).toBe("variant")
|
|
489
482
|
})
|
|
490
483
|
|
|
491
484
|
it("should not detect non-Result variant with Ok and other options", () => {
|
|
@@ -516,9 +509,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
516
509
|
expect(field.type).toBe("tuple")
|
|
517
510
|
expect(field.candidType).toBe("tuple")
|
|
518
511
|
expect(field.displayType).toBe("array")
|
|
519
|
-
expect(field.
|
|
520
|
-
expect(field.
|
|
521
|
-
expect(field.
|
|
512
|
+
expect(field.items).toHaveLength(2)
|
|
513
|
+
expect(field.items[0].type).toBe("text")
|
|
514
|
+
expect(field.items[1].type).toBe("number")
|
|
522
515
|
})
|
|
523
516
|
|
|
524
517
|
it("should handle tuple with mixed types", () => {
|
|
@@ -534,17 +527,17 @@ describe("ResultFieldVisitor", () => {
|
|
|
534
527
|
"data"
|
|
535
528
|
)
|
|
536
529
|
|
|
537
|
-
expect(field.
|
|
538
|
-
expect(field.
|
|
539
|
-
expect(field.
|
|
540
|
-
const numField = field.
|
|
530
|
+
expect(field.items).toHaveLength(4)
|
|
531
|
+
expect(field.items[0].type).toBe("principal")
|
|
532
|
+
expect(field.items[1].type).toBe("number")
|
|
533
|
+
const numField = field.items[1]
|
|
541
534
|
if (numField.type === "number") {
|
|
542
535
|
expect(numField.displayType).toBe("string") // nat64 → string
|
|
543
536
|
} else {
|
|
544
537
|
throw new Error("Expected number field")
|
|
545
538
|
}
|
|
546
|
-
expect(field.
|
|
547
|
-
expect(field.
|
|
539
|
+
expect(field.items[2].type).toBe("boolean")
|
|
540
|
+
expect(field.items[3].type).toBe("blob")
|
|
548
541
|
})
|
|
549
542
|
})
|
|
550
543
|
|
|
@@ -556,7 +549,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
556
549
|
expect(field.type).toBe("optional")
|
|
557
550
|
expect(field.candidType).toBe("opt")
|
|
558
551
|
expect(field.displayType).toBe("nullable") // opt T → T | null
|
|
559
|
-
|
|
552
|
+
// Validate inner by resolving a value
|
|
553
|
+
const optResolved = field.resolve(["Bob"])
|
|
554
|
+
expect((optResolved.value as ResolvedNode).type).toBe("text")
|
|
560
555
|
})
|
|
561
556
|
|
|
562
557
|
it("should handle optional record", () => {
|
|
@@ -568,7 +563,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
568
563
|
const field = visitor.visitOpt(optType, recordInOpt, "metadata")
|
|
569
564
|
|
|
570
565
|
expect(field.type).toBe("optional")
|
|
571
|
-
|
|
566
|
+
// Validate inner by resolving a record
|
|
567
|
+
const metaResolved = field.resolve([{ name: "x", value: BigInt(1) }])
|
|
568
|
+
expect((metaResolved.value as ResolvedNode).type).toBe("record")
|
|
572
569
|
})
|
|
573
570
|
|
|
574
571
|
it("should handle nested optional", () => {
|
|
@@ -577,13 +574,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
577
574
|
const field = visitor.visitOpt(optType, innerOpt, "maybeNumber")
|
|
578
575
|
|
|
579
576
|
expect(field.type).toBe("optional")
|
|
580
|
-
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
throw new Error("Inner field is not optional")
|
|
586
|
-
}
|
|
577
|
+
// Validate nested optional by resolving a nested array
|
|
578
|
+
const nestedResolved = field.resolve([[BigInt(1)]])
|
|
579
|
+
expect((nestedResolved.value as ResolvedNode).type).toBe("optional")
|
|
580
|
+
const innerResolved = nestedResolved.value as OptionalNode
|
|
581
|
+
expect((innerResolved.value as ResolvedNode).type).toBe("number")
|
|
587
582
|
})
|
|
588
583
|
})
|
|
589
584
|
|
|
@@ -595,11 +590,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
595
590
|
expect(field.type).toBe("vector")
|
|
596
591
|
expect(field.candidType).toBe("vec")
|
|
597
592
|
expect(field.displayType).toBe("array")
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
593
|
+
// Validate items by resolving
|
|
594
|
+
const vecResolved = field.resolve(["a", "b", "c"]) as VectorNode
|
|
595
|
+
expect(vecResolved.items).toHaveLength(3)
|
|
596
|
+
expect(vecResolved.items[0].value).toBe("a")
|
|
603
597
|
})
|
|
604
598
|
|
|
605
599
|
it("should handle vector of records", () => {
|
|
@@ -611,11 +605,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
611
605
|
const field = visitor.visitVec(vecType, recType, "items")
|
|
612
606
|
|
|
613
607
|
expect(field.type).toBe("vector")
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
608
|
+
// Validate by resolving
|
|
609
|
+
const itemsResolved = field.resolve([
|
|
610
|
+
{ id: BigInt(1), name: "x" },
|
|
611
|
+
]) as VectorNode
|
|
612
|
+
expect(itemsResolved.items[0].type).toBe("record")
|
|
619
613
|
})
|
|
620
614
|
|
|
621
615
|
it("should handle blob (vec nat8)", () => {
|
|
@@ -625,11 +619,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
625
619
|
expect(field.type).toBe("blob")
|
|
626
620
|
expect(field.candidType).toBe("blob")
|
|
627
621
|
expect(field.displayType).toBe("string") // Blob → hex string
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
622
|
+
// Validate by resolving a Uint8Array
|
|
623
|
+
const blobResolved = field.resolve(
|
|
624
|
+
new Uint8Array([0x12, 0x34, 0xab, 0xcd])
|
|
625
|
+
)
|
|
626
|
+
expect(blobResolved.value).toBe("1234abcd")
|
|
633
627
|
})
|
|
634
628
|
|
|
635
629
|
it("should handle nested vectors", () => {
|
|
@@ -638,11 +632,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
638
632
|
const field = visitor.visitVec(nestedVecType, innerVec, "matrix")
|
|
639
633
|
|
|
640
634
|
expect(field.type).toBe("vector")
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
throw new Error("Field is not a vector")
|
|
645
|
-
}
|
|
635
|
+
// Validate nested items via resolve
|
|
636
|
+
const nestedResolved = field.resolve([[BigInt(1)]]) as VectorNode
|
|
637
|
+
expect(nestedResolved.items[0].type).toBe("vector")
|
|
646
638
|
})
|
|
647
639
|
|
|
648
640
|
it("should handle vec of tuples (Map-like)", () => {
|
|
@@ -652,13 +644,15 @@ describe("ResultFieldVisitor", () => {
|
|
|
652
644
|
mapType,
|
|
653
645
|
tupleType,
|
|
654
646
|
"metadata"
|
|
655
|
-
) as
|
|
647
|
+
) as VectorNode
|
|
656
648
|
|
|
657
649
|
expect(field.type).toBe("vector")
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
650
|
+
// Validate by resolving a tuple item
|
|
651
|
+
const vecTupleResolved = field.resolve([["a", BigInt(1)]])
|
|
652
|
+
expect(vecTupleResolved.items[0].type).toBe("tuple")
|
|
653
|
+
const item = vecTupleResolved.items[0] as TupleNode
|
|
654
|
+
if (item.type === "tuple") {
|
|
655
|
+
expect(item.items).toHaveLength(2)
|
|
662
656
|
} else {
|
|
663
657
|
throw new Error("Item field is not tuple")
|
|
664
658
|
}
|
|
@@ -693,17 +687,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
693
687
|
expect(field.type).toBe("recursive")
|
|
694
688
|
expect(field.candidType).toBe("rec")
|
|
695
689
|
expect(field.displayType).toBe("recursive")
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
const extracted = field.extract()
|
|
701
|
-
if (extracted.type !== "variant") {
|
|
702
|
-
throw new Error("Extracted field is not variant")
|
|
703
|
-
}
|
|
704
|
-
expect(extracted.type).toBe("variant")
|
|
705
|
-
expect(extracted.options).toContain("Leaf")
|
|
706
|
-
expect(extracted.options).toContain("Node")
|
|
690
|
+
// Resolve to inspect inner schema
|
|
691
|
+
const treeResolved = field.resolve({ Leaf: BigInt(1) }) as RecursiveNode
|
|
692
|
+
expect(treeResolved.inner.type).toBe("variant")
|
|
693
|
+
expect((treeResolved.inner as VariantNode).selected).toBe("Leaf")
|
|
707
694
|
})
|
|
708
695
|
|
|
709
696
|
it("should handle recursive linked list", () => {
|
|
@@ -732,11 +719,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
732
719
|
|
|
733
720
|
expect(field.type).toBe("recursive")
|
|
734
721
|
|
|
735
|
-
const
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
}
|
|
739
|
-
expect(extracted.options).toEqual(["Nil", "Cons"])
|
|
722
|
+
const listResolved = field.resolve({ Nil: null }) as RecursiveNode
|
|
723
|
+
expect(listResolved.inner.type).toBe("variant")
|
|
724
|
+
expect((listResolved.inner as VariantNode).selected).toBe("Nil")
|
|
740
725
|
})
|
|
741
726
|
})
|
|
742
727
|
|
|
@@ -752,11 +737,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
752
737
|
expect(meta.functionType).toBe("query")
|
|
753
738
|
expect(meta.functionName).toBe("get_balance")
|
|
754
739
|
expect(meta.returnCount).toBe(1)
|
|
755
|
-
expect(meta.
|
|
740
|
+
expect(meta.returns).toHaveLength(1)
|
|
756
741
|
|
|
757
|
-
expect(meta.
|
|
742
|
+
expect(meta.returns).toHaveLength(1)
|
|
758
743
|
|
|
759
|
-
const returnField = meta.
|
|
744
|
+
const returnField = meta.returns[0]
|
|
760
745
|
if (returnField.type === "number") {
|
|
761
746
|
expect(returnField.candidType).toBe("nat")
|
|
762
747
|
expect(returnField.displayType).toBe("string")
|
|
@@ -786,7 +771,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
786
771
|
expect(meta.functionType).toBe("update")
|
|
787
772
|
expect(meta.returnCount).toBe(1)
|
|
788
773
|
|
|
789
|
-
const resultField = meta.
|
|
774
|
+
const resultField = meta.returns[0]
|
|
790
775
|
if (resultField.type === "variant") {
|
|
791
776
|
expect(resultField.displayType).toBe("result")
|
|
792
777
|
} else {
|
|
@@ -799,10 +784,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
799
784
|
const meta = visitor.visitFunc(funcType, "get_info")
|
|
800
785
|
|
|
801
786
|
expect(meta.returnCount).toBe(3)
|
|
802
|
-
expect(meta.
|
|
803
|
-
expect(meta.
|
|
804
|
-
expect(meta.
|
|
805
|
-
expect(meta.
|
|
787
|
+
expect(meta.returns).toHaveLength(3)
|
|
788
|
+
expect(meta.returns[0].type).toBe("text")
|
|
789
|
+
expect(meta.returns[1].type).toBe("number")
|
|
790
|
+
expect(meta.returns[2].type).toBe("boolean")
|
|
806
791
|
})
|
|
807
792
|
|
|
808
793
|
it("should handle function with no returns", () => {
|
|
@@ -810,7 +795,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
810
795
|
const meta = visitor.visitFunc(funcType, "log")
|
|
811
796
|
|
|
812
797
|
expect(meta.returnCount).toBe(0)
|
|
813
|
-
expect(meta.
|
|
798
|
+
expect(meta.returns).toHaveLength(0)
|
|
814
799
|
})
|
|
815
800
|
})
|
|
816
801
|
|
|
@@ -852,8 +837,8 @@ describe("ResultFieldVisitor", () => {
|
|
|
852
837
|
const getBalanceMeta = serviceMeta["get_balance"]
|
|
853
838
|
expect(getBalanceMeta.functionType).toBe("query")
|
|
854
839
|
expect(getBalanceMeta.returnCount).toBe(1)
|
|
855
|
-
expect(getBalanceMeta.
|
|
856
|
-
const balanceField = getBalanceMeta.
|
|
840
|
+
expect(getBalanceMeta.returns[0].type).toBe("number")
|
|
841
|
+
const balanceField = getBalanceMeta.returns[0]
|
|
857
842
|
if (balanceField.type === "number") {
|
|
858
843
|
expect(balanceField.displayType).toBe("string")
|
|
859
844
|
} else {
|
|
@@ -867,7 +852,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
867
852
|
// Check get_metadata
|
|
868
853
|
const getMetadataMeta = serviceMeta["get_metadata"]
|
|
869
854
|
expect(getMetadataMeta.returnCount).toBe(1)
|
|
870
|
-
expect(getMetadataMeta.
|
|
855
|
+
expect(getMetadataMeta.returns[0].type).toBe("vector")
|
|
871
856
|
})
|
|
872
857
|
})
|
|
873
858
|
|
|
@@ -892,7 +877,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
892
877
|
expect(meta.functionType).toBe("query")
|
|
893
878
|
expect(meta.returnCount).toBe(1)
|
|
894
879
|
|
|
895
|
-
const balanceField = meta.
|
|
880
|
+
const balanceField = meta.returns[0]
|
|
896
881
|
if (balanceField.type === "number") {
|
|
897
882
|
expect(balanceField.candidType).toBe("nat")
|
|
898
883
|
expect(balanceField.displayType).toBe("string")
|
|
@@ -942,23 +927,28 @@ describe("ResultFieldVisitor", () => {
|
|
|
942
927
|
|
|
943
928
|
expect(field.displayType).toBe("result")
|
|
944
929
|
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
if (!okField || okField.type !== "number") {
|
|
930
|
+
const okResolved = field.resolve({ Ok: BigInt(123) })
|
|
931
|
+
if ((okResolved.selectedOption as ResolvedNode).type !== "number") {
|
|
948
932
|
throw new Error("Ok field is not number")
|
|
949
933
|
}
|
|
934
|
+
expect((okResolved.selectedOption as ResolvedNode).candidType).toBe("nat")
|
|
935
|
+
expect((okResolved.selectedOption as ResolvedNode).displayType).toBe(
|
|
936
|
+
"string"
|
|
937
|
+
)
|
|
950
938
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
expect(
|
|
960
|
-
|
|
961
|
-
|
|
939
|
+
const errResolved = field.resolve({
|
|
940
|
+
Err: { InsufficientFunds: { balance: BigInt(0) } },
|
|
941
|
+
})
|
|
942
|
+
const innerErr = errResolved.selectedOption as ResolvedNode
|
|
943
|
+
expect(innerErr.type).toBe("variant")
|
|
944
|
+
const insufficient = (innerErr as any).resolve({
|
|
945
|
+
InsufficientFunds: { balance: BigInt(0) },
|
|
946
|
+
})
|
|
947
|
+
expect(insufficient.selected).toBe("InsufficientFunds")
|
|
948
|
+
const generic = (innerErr as any).resolve({
|
|
949
|
+
GenericError: { error_code: BigInt(1), message: "err" },
|
|
950
|
+
})
|
|
951
|
+
expect(generic.selected).toBe("GenericError")
|
|
962
952
|
})
|
|
963
953
|
|
|
964
954
|
it("should handle SNS canister status return", () => {
|
|
@@ -1011,45 +1001,46 @@ describe("ResultFieldVisitor", () => {
|
|
|
1011
1001
|
expect(field.type).toBe("record")
|
|
1012
1002
|
|
|
1013
1003
|
// Check status variant
|
|
1014
|
-
const statusField = field.fields
|
|
1004
|
+
const statusField = field.fields["status"] as VariantNode
|
|
1015
1005
|
if (!statusField || statusField.type !== "variant") {
|
|
1016
|
-
throw new Error("Status field
|
|
1006
|
+
throw new Error("Status field not found or not variant")
|
|
1017
1007
|
}
|
|
1018
1008
|
expect(statusField.type).toBe("variant")
|
|
1019
|
-
expect(statusField.
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
expect(
|
|
1009
|
+
expect(statusField.displayType).toBe("variant")
|
|
1010
|
+
// Validate via resolving options
|
|
1011
|
+
const statusResolved = statusField.resolve({ running: null })
|
|
1012
|
+
expect(statusResolved.selected).toBe("running")
|
|
1023
1013
|
|
|
1024
1014
|
// Check settings record
|
|
1025
|
-
const settingsField = field.fields
|
|
1015
|
+
const settingsField = field.fields["settings"] as RecordNode
|
|
1026
1016
|
if (!settingsField || settingsField.type !== "record") {
|
|
1027
|
-
throw new Error("Settings field
|
|
1017
|
+
throw new Error("Settings field not found or not record")
|
|
1028
1018
|
}
|
|
1029
1019
|
expect(settingsField.type).toBe("record")
|
|
1020
|
+
expect(settingsField.displayType).toBe("object")
|
|
1030
1021
|
|
|
1031
|
-
const controllersField = settingsField.fields
|
|
1032
|
-
(f) => f.label === "controllers"
|
|
1033
|
-
)
|
|
1022
|
+
const controllersField = settingsField.fields["controllers"] as VectorNode
|
|
1034
1023
|
if (!controllersField || controllersField.type !== "vector") {
|
|
1035
|
-
throw new Error("Controllers field
|
|
1024
|
+
throw new Error("Controllers field not found or not vector")
|
|
1036
1025
|
}
|
|
1037
1026
|
expect(controllersField.type).toBe("vector")
|
|
1038
|
-
|
|
1027
|
+
// Validate item type via resolve
|
|
1028
|
+
const controllersResolved = controllersField.resolve(["aaaaa-aa"])
|
|
1029
|
+
expect(controllersResolved.items[0].type).toBe("principal")
|
|
1039
1030
|
|
|
1040
1031
|
// Check cycles - should detect special format
|
|
1041
|
-
const cyclesField = field.fields
|
|
1032
|
+
const cyclesField = field.fields["cycles"] as NumberNode
|
|
1042
1033
|
if (!cyclesField || cyclesField.type !== "number") {
|
|
1043
|
-
throw new Error("Cycles field
|
|
1034
|
+
throw new Error("Cycles field not found or not number")
|
|
1044
1035
|
}
|
|
1045
|
-
expect(cyclesField.
|
|
1036
|
+
expect(cyclesField.format).toBe("cycle")
|
|
1046
1037
|
|
|
1047
1038
|
// Check module_hash - optional blob
|
|
1048
|
-
const moduleHashField = field.fields
|
|
1049
|
-
(f) => f.label === "module_hash"
|
|
1050
|
-
) as OptionalResultField
|
|
1039
|
+
const moduleHashField = field.fields["module_hash"] as OptionalNode
|
|
1051
1040
|
expect(moduleHashField.type).toBe("optional")
|
|
1052
|
-
|
|
1041
|
+
// Validate via resolving a sample blob
|
|
1042
|
+
const moduleHashResolved = moduleHashField.resolve([new Uint8Array([1])])
|
|
1043
|
+
expect((moduleHashResolved.value as ResolvedNode).type).toBe("blob")
|
|
1053
1044
|
})
|
|
1054
1045
|
|
|
1055
1046
|
it("should handle complex governance proposal types", () => {
|
|
@@ -1114,12 +1105,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
1114
1105
|
)
|
|
1115
1106
|
|
|
1116
1107
|
expect(field.type).toBe("record")
|
|
1117
|
-
expect(field.fields
|
|
1108
|
+
expect(Object.keys(field.fields)).toHaveLength(12)
|
|
1118
1109
|
|
|
1119
1110
|
// Check timestamp field (note: the label pattern matching may not match "proposal_timestamp_seconds")
|
|
1120
|
-
const timestampField = field.fields
|
|
1121
|
-
(f) => f.label === "proposal_timestamp_seconds"
|
|
1122
|
-
)
|
|
1111
|
+
const timestampField = field.fields["proposal_timestamp_seconds"]
|
|
1123
1112
|
if (!timestampField || timestampField.type !== "number") {
|
|
1124
1113
|
throw new Error("Timestamp field not found or not number")
|
|
1125
1114
|
}
|
|
@@ -1127,20 +1116,23 @@ describe("ResultFieldVisitor", () => {
|
|
|
1127
1116
|
expect(timestampField.displayType).toBe("string") // nat64 → string
|
|
1128
1117
|
|
|
1129
1118
|
// Check ballots - vec of tuples
|
|
1130
|
-
const ballotsField = field.fields
|
|
1119
|
+
const ballotsField = field.fields["ballots"]
|
|
1131
1120
|
if (!ballotsField || ballotsField.type !== "vector") {
|
|
1132
1121
|
throw new Error("Ballots field not found or not vector")
|
|
1133
1122
|
}
|
|
1134
1123
|
expect(ballotsField.type).toBe("vector")
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1124
|
+
// Validate via resolve
|
|
1125
|
+
const ballotsResolved = ballotsField.resolve([
|
|
1126
|
+
[BigInt(1), { vote: 1, voting_power: BigInt(2) }],
|
|
1127
|
+
]) as TupleNode
|
|
1128
|
+
expect(ballotsResolved.items).toHaveLength(1)
|
|
1129
|
+
const ballotTuple = ballotsResolved.items[0] as TupleNode
|
|
1138
1130
|
if (ballotTuple.type !== "tuple") {
|
|
1139
1131
|
throw new Error("Ballot item is not tuple")
|
|
1140
1132
|
}
|
|
1141
|
-
expect(ballotTuple.
|
|
1142
|
-
expect(ballotTuple.
|
|
1143
|
-
expect(ballotTuple.
|
|
1133
|
+
expect(ballotTuple.items).toHaveLength(2)
|
|
1134
|
+
expect(ballotTuple.items[0].type).toBe("number") // nat64
|
|
1135
|
+
expect(ballotTuple.items[1].type).toBe("record") // ballot record
|
|
1144
1136
|
})
|
|
1145
1137
|
})
|
|
1146
1138
|
|
|
@@ -1179,7 +1171,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1179
1171
|
if (typeof field === "object" && "displayType" in field) {
|
|
1180
1172
|
expect(field.displayType).toBe(expectedDisplay)
|
|
1181
1173
|
} else {
|
|
1182
|
-
throw new Error("Expected
|
|
1174
|
+
throw new Error("Expected as ResultNode")
|
|
1183
1175
|
}
|
|
1184
1176
|
})
|
|
1185
1177
|
})
|
|
@@ -1194,40 +1186,30 @@ describe("ResultFieldVisitor", () => {
|
|
|
1194
1186
|
it("should resolve text field with value", () => {
|
|
1195
1187
|
const field = visitor.visitText(IDL.Text, "message")
|
|
1196
1188
|
const resolved = field.resolve("Hello World")
|
|
1197
|
-
|
|
1198
|
-
expect(resolved.field).toBe(field)
|
|
1199
1189
|
expect(resolved.value).toBe("Hello World")
|
|
1200
1190
|
})
|
|
1201
1191
|
|
|
1202
1192
|
it("should resolve number field with value", () => {
|
|
1203
1193
|
const field = visitor.visitNat(IDL.Nat, "amount")
|
|
1204
1194
|
const resolved = field.resolve(BigInt(1000000))
|
|
1205
|
-
|
|
1206
|
-
expect(resolved.field).toBe(field)
|
|
1207
1195
|
expect(resolved.value).toBe("1000000")
|
|
1208
1196
|
})
|
|
1209
1197
|
|
|
1210
1198
|
it("should resolve boolean field with value", () => {
|
|
1211
1199
|
const field = visitor.visitBool(IDL.Bool, "active")
|
|
1212
1200
|
const resolved = field.resolve(true)
|
|
1213
|
-
|
|
1214
|
-
expect(resolved.field).toBe(field)
|
|
1215
1201
|
expect(resolved.value).toBe(true)
|
|
1216
1202
|
})
|
|
1217
1203
|
|
|
1218
1204
|
it("should resolve null field", () => {
|
|
1219
1205
|
const field = visitor.visitNull(IDL.Null, "empty")
|
|
1220
1206
|
const resolved = field.resolve(null)
|
|
1221
|
-
|
|
1222
|
-
expect(resolved.field).toBe(field)
|
|
1223
1207
|
expect(resolved.value).toBe(null)
|
|
1224
1208
|
})
|
|
1225
1209
|
|
|
1226
1210
|
it("should resolve principal field with string value", () => {
|
|
1227
1211
|
const field = visitor.visitPrincipal(IDL.Principal, "owner")
|
|
1228
1212
|
const resolved = field.resolve("aaaaa-aa")
|
|
1229
|
-
|
|
1230
|
-
expect(resolved.field).toBe(field)
|
|
1231
1213
|
expect(resolved.value).toBe("aaaaa-aa")
|
|
1232
1214
|
})
|
|
1233
1215
|
})
|
|
@@ -1255,14 +1237,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
1255
1237
|
active: true,
|
|
1256
1238
|
})
|
|
1257
1239
|
|
|
1258
|
-
expect(resolved.
|
|
1259
|
-
const value = resolved.
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
expect(value.name.value).toBe("Alice")
|
|
1264
|
-
expect(value.age.value).toBe(30)
|
|
1265
|
-
expect(value.active.value).toBe(true)
|
|
1240
|
+
expect(resolved.type).toBe(field.type)
|
|
1241
|
+
const value = resolved.fields as Record<string, ResolvedNode>
|
|
1242
|
+
expect(value["name"].value).toBe("Alice")
|
|
1243
|
+
expect(value["age"].value).toBe(30)
|
|
1244
|
+
expect(value["active"].value).toBe(true)
|
|
1266
1245
|
})
|
|
1267
1246
|
|
|
1268
1247
|
it("should handle null record value", () => {
|
|
@@ -1273,8 +1252,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
1273
1252
|
"user"
|
|
1274
1253
|
)
|
|
1275
1254
|
|
|
1276
|
-
|
|
1277
|
-
|
|
1255
|
+
expect(() => field.resolve(null)).toThrow(
|
|
1256
|
+
"Expected record for field user, but got null"
|
|
1257
|
+
)
|
|
1278
1258
|
})
|
|
1279
1259
|
})
|
|
1280
1260
|
|
|
@@ -1294,13 +1274,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
1294
1274
|
)
|
|
1295
1275
|
|
|
1296
1276
|
const resolved = field.resolve({ Ok: "Success" })
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
}
|
|
1302
|
-
expect(value.option).toBe("Ok")
|
|
1303
|
-
expect(value.value.value).toBe("Success")
|
|
1277
|
+
expect(resolved.type).toBe(field.type)
|
|
1278
|
+
expect(resolved.selected).toBe("Ok")
|
|
1279
|
+
const data = resolved.selectedOption as ResolvedNode
|
|
1280
|
+
expect(data.value).toBe("Success")
|
|
1304
1281
|
})
|
|
1305
1282
|
|
|
1306
1283
|
it("should resolve variant with Err option", () => {
|
|
@@ -1319,12 +1296,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
1319
1296
|
|
|
1320
1297
|
const resolved = field.resolve({ Err: "Something went wrong" })
|
|
1321
1298
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
}
|
|
1326
|
-
expect(value.option).toBe("Err")
|
|
1327
|
-
expect(value.value.value).toBe("Something went wrong")
|
|
1299
|
+
expect(resolved.selected).toBe("Err")
|
|
1300
|
+
const data = resolved.selectedOption as ResolvedNode
|
|
1301
|
+
expect(data.value).toBe("Something went wrong")
|
|
1328
1302
|
})
|
|
1329
1303
|
|
|
1330
1304
|
it("should handle null variant value", () => {
|
|
@@ -1338,8 +1312,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
1338
1312
|
"choice"
|
|
1339
1313
|
)
|
|
1340
1314
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1315
|
+
expect(() => field.resolve(null)).toThrow(
|
|
1316
|
+
"Expected variant for field choice, but got null"
|
|
1317
|
+
)
|
|
1343
1318
|
})
|
|
1344
1319
|
})
|
|
1345
1320
|
|
|
@@ -1354,11 +1329,8 @@ describe("ResultFieldVisitor", () => {
|
|
|
1354
1329
|
|
|
1355
1330
|
const resolved = field.resolve(["hello", 123n, true])
|
|
1356
1331
|
|
|
1357
|
-
expect(resolved.
|
|
1358
|
-
const value = resolved.
|
|
1359
|
-
field: ResultField
|
|
1360
|
-
value: unknown
|
|
1361
|
-
}>
|
|
1332
|
+
expect(resolved.type).toBe(field.type)
|
|
1333
|
+
const value = resolved.items as ResolvedNode[]
|
|
1362
1334
|
expect(value).toHaveLength(3)
|
|
1363
1335
|
expect(value[0].value).toBe("hello")
|
|
1364
1336
|
expect(value[1].value).toBe("123")
|
|
@@ -1369,8 +1341,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
1369
1341
|
const tupleType = IDL.Tuple(IDL.Text, IDL.Nat)
|
|
1370
1342
|
const field = visitor.visitTuple(tupleType, [IDL.Text, IDL.Nat], "pair")
|
|
1371
1343
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1344
|
+
expect(() => field.resolve(null)).toThrow(
|
|
1345
|
+
"Expected tuple for field pair, but got null"
|
|
1346
|
+
)
|
|
1374
1347
|
})
|
|
1375
1348
|
})
|
|
1376
1349
|
|
|
@@ -1381,8 +1354,8 @@ describe("ResultFieldVisitor", () => {
|
|
|
1381
1354
|
|
|
1382
1355
|
const resolved = field.resolve(["Bob"])
|
|
1383
1356
|
|
|
1384
|
-
expect(resolved.
|
|
1385
|
-
const inner = resolved.value as
|
|
1357
|
+
expect(resolved.type).toBe(field.type)
|
|
1358
|
+
const inner = resolved.value as ResolvedNode
|
|
1386
1359
|
expect(inner.value).toBe("Bob")
|
|
1387
1360
|
})
|
|
1388
1361
|
|
|
@@ -1391,8 +1364,6 @@ describe("ResultFieldVisitor", () => {
|
|
|
1391
1364
|
const field = visitor.visitOpt(optType, IDL.Text, "nickname")
|
|
1392
1365
|
|
|
1393
1366
|
const resolved = field.resolve(null)
|
|
1394
|
-
|
|
1395
|
-
expect(resolved.field).toBe(field)
|
|
1396
1367
|
expect(resolved.value).toBe(null)
|
|
1397
1368
|
})
|
|
1398
1369
|
})
|
|
@@ -1402,13 +1373,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
1402
1373
|
const vecType = IDL.Vec(IDL.Text)
|
|
1403
1374
|
const field = visitor.visitVec(vecType, IDL.Text, "tags")
|
|
1404
1375
|
|
|
1405
|
-
const resolved = field.resolve(["a", "b", "c"])
|
|
1376
|
+
const resolved = field.resolve(["a", "b", "c"]) as VectorNode
|
|
1406
1377
|
|
|
1407
|
-
expect(resolved.
|
|
1408
|
-
const value = resolved.
|
|
1409
|
-
field: ResultField
|
|
1410
|
-
value: unknown
|
|
1411
|
-
}>
|
|
1378
|
+
expect(resolved.type).toBe(field.type)
|
|
1379
|
+
const value = resolved.items as ResolvedNode[]
|
|
1412
1380
|
expect(value).toHaveLength(3)
|
|
1413
1381
|
expect(value[0].value).toBe("a")
|
|
1414
1382
|
expect(value[1].value).toBe("b")
|
|
@@ -1419,12 +1387,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
1419
1387
|
const vecType = IDL.Vec(IDL.Nat)
|
|
1420
1388
|
const field = visitor.visitVec(vecType, IDL.Nat, "numbers")
|
|
1421
1389
|
|
|
1422
|
-
const resolved = field.resolve([])
|
|
1390
|
+
const resolved = field.resolve([]) as VectorNode
|
|
1391
|
+
|
|
1392
|
+
expect(resolved.type).toBe(field.type)
|
|
1423
1393
|
|
|
1424
|
-
const value = resolved.
|
|
1425
|
-
field: ResultField
|
|
1426
|
-
value: unknown
|
|
1427
|
-
}>
|
|
1394
|
+
const value = resolved.items as ResolvedNode[]
|
|
1428
1395
|
expect(value).toHaveLength(0)
|
|
1429
1396
|
})
|
|
1430
1397
|
|
|
@@ -1432,8 +1399,9 @@ describe("ResultFieldVisitor", () => {
|
|
|
1432
1399
|
const vecType = IDL.Vec(IDL.Text)
|
|
1433
1400
|
const field = visitor.visitVec(vecType, IDL.Text, "items")
|
|
1434
1401
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1402
|
+
expect(() => field.resolve(null)).toThrow(
|
|
1403
|
+
"Expected vector for field items, but got null"
|
|
1404
|
+
)
|
|
1437
1405
|
})
|
|
1438
1406
|
})
|
|
1439
1407
|
|
|
@@ -1444,7 +1412,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1444
1412
|
|
|
1445
1413
|
const resolved = field.resolve(new Uint8Array([0x12, 0x34, 0xab, 0xcd]))
|
|
1446
1414
|
|
|
1447
|
-
expect(resolved.
|
|
1415
|
+
expect(resolved.type).toBe(field.type)
|
|
1448
1416
|
expect(resolved.value).toBe("1234abcd")
|
|
1449
1417
|
})
|
|
1450
1418
|
})
|
|
@@ -1475,7 +1443,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1475
1443
|
})
|
|
1476
1444
|
|
|
1477
1445
|
// The recursive type should delegate to its inner record type
|
|
1478
|
-
expect(resolved.
|
|
1446
|
+
expect(resolved.type).toBe("recursive")
|
|
1479
1447
|
})
|
|
1480
1448
|
})
|
|
1481
1449
|
|
|
@@ -1515,29 +1483,24 @@ describe("ResultFieldVisitor", () => {
|
|
|
1515
1483
|
},
|
|
1516
1484
|
})
|
|
1517
1485
|
|
|
1518
|
-
const value = resolved.
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
string,
|
|
1528
|
-
{ field: ResultField; value: unknown }
|
|
1529
|
-
>
|
|
1530
|
-
expect(profileValue.name.value).toBe("Alice")
|
|
1531
|
-
expect(profileValue.verified.value).toBe(true)
|
|
1486
|
+
const value = resolved.fields as Record<string, ResolvedNode>
|
|
1487
|
+
const userNode = value.user as RecordNode
|
|
1488
|
+
if (userNode.type !== "record") {
|
|
1489
|
+
throw new Error("User node is not a record")
|
|
1490
|
+
}
|
|
1491
|
+
const profileNode = userNode.fields["profile"] as RecordNode
|
|
1492
|
+
const profileFields = profileNode.fields as Record<string, ResolvedNode>
|
|
1493
|
+
expect(profileFields["name"].value).toBe("Alice")
|
|
1494
|
+
expect(profileFields["verified"].value).toBe(true)
|
|
1532
1495
|
})
|
|
1533
1496
|
})
|
|
1534
1497
|
})
|
|
1535
1498
|
|
|
1536
1499
|
// ════════════════════════════════════════════════════════════════════════
|
|
1537
|
-
//
|
|
1500
|
+
// resolve() Method Tests
|
|
1538
1501
|
// ════════════════════════════════════════════════════════════════════════
|
|
1539
1502
|
|
|
1540
|
-
describe("
|
|
1503
|
+
describe("resolve() Method", () => {
|
|
1541
1504
|
it("should generate metadata for single return value", () => {
|
|
1542
1505
|
const service = IDL.Service({
|
|
1543
1506
|
getName: IDL.Func([], [IDL.Text], ["query"]),
|
|
@@ -1548,13 +1511,13 @@ describe("ResultFieldVisitor", () => {
|
|
|
1548
1511
|
)
|
|
1549
1512
|
const methodMeta = serviceMeta["getName"]
|
|
1550
1513
|
|
|
1551
|
-
const result = methodMeta.
|
|
1514
|
+
const result = methodMeta.resolve("Alice")
|
|
1552
1515
|
|
|
1553
1516
|
expect(result.functionName).toBe("getName")
|
|
1554
1517
|
expect(result.functionType).toBe("query")
|
|
1555
1518
|
expect(result.results).toHaveLength(1)
|
|
1556
1519
|
expect(result.results[0].value).toBe("Alice")
|
|
1557
|
-
expect(result.results[0].
|
|
1520
|
+
expect(result.results[0].type).toBe("text")
|
|
1558
1521
|
})
|
|
1559
1522
|
|
|
1560
1523
|
it("should generate metadata for multiple return values", () => {
|
|
@@ -1567,18 +1530,14 @@ describe("ResultFieldVisitor", () => {
|
|
|
1567
1530
|
)
|
|
1568
1531
|
const methodMeta = serviceMeta["getStats"]
|
|
1569
1532
|
|
|
1570
|
-
const result = methodMeta.
|
|
1571
|
-
BigInt(100),
|
|
1572
|
-
BigInt(200),
|
|
1573
|
-
"active",
|
|
1574
|
-
])
|
|
1533
|
+
const result = methodMeta.resolve([BigInt(100), BigInt(200), "active"])
|
|
1575
1534
|
|
|
1576
1535
|
expect(result.results).toHaveLength(3)
|
|
1577
1536
|
expect(result.results[0].value).toBe("100")
|
|
1578
|
-
expect(result.results[0].
|
|
1537
|
+
expect(result.results[0].type).toBe("number")
|
|
1579
1538
|
expect(result.results[1].value).toBe("200")
|
|
1580
1539
|
expect(result.results[2].value).toBe("active")
|
|
1581
|
-
expect(result.results[2].
|
|
1540
|
+
expect(result.results[2].type).toBe("text")
|
|
1582
1541
|
})
|
|
1583
1542
|
|
|
1584
1543
|
it("should generate metadata for record return value", () => {
|
|
@@ -1595,22 +1554,19 @@ describe("ResultFieldVisitor", () => {
|
|
|
1595
1554
|
)
|
|
1596
1555
|
const methodMeta = serviceMeta["getUser"]
|
|
1597
1556
|
|
|
1598
|
-
const result = methodMeta.
|
|
1557
|
+
const result = methodMeta.resolve({
|
|
1599
1558
|
name: "Bob",
|
|
1600
1559
|
balance: BigInt(1000),
|
|
1601
1560
|
})
|
|
1602
1561
|
|
|
1603
1562
|
expect(result.results).toHaveLength(1)
|
|
1604
|
-
expect(result.results[0].
|
|
1563
|
+
expect(result.results[0].type).toBe("record")
|
|
1605
1564
|
|
|
1606
|
-
const
|
|
1607
|
-
if (
|
|
1608
|
-
throw new Error("Expected record
|
|
1565
|
+
const recordNode = result.results[0] as RecordNode
|
|
1566
|
+
if (recordNode.type !== "record") {
|
|
1567
|
+
throw new Error("Expected record node")
|
|
1609
1568
|
}
|
|
1610
|
-
const val =
|
|
1611
|
-
string,
|
|
1612
|
-
{ field: ResultField; value: unknown }
|
|
1613
|
-
>
|
|
1569
|
+
const val = recordNode.fields as Record<string, ResolvedNode>
|
|
1614
1570
|
expect(val.name.value).toBe("Bob")
|
|
1615
1571
|
expect(val.balance.value).toBe("1000")
|
|
1616
1572
|
})
|
|
@@ -1630,31 +1586,29 @@ describe("ResultFieldVisitor", () => {
|
|
|
1630
1586
|
const methodMeta = serviceMeta["transfer"]
|
|
1631
1587
|
|
|
1632
1588
|
// Test Ok case
|
|
1633
|
-
const okResult = methodMeta.
|
|
1634
|
-
expect(okResult.results[0].
|
|
1635
|
-
if (okResult.results[0].
|
|
1636
|
-
expect(okResult.results[0].
|
|
1589
|
+
const okResult = methodMeta.resolve({ Ok: BigInt(12345) })
|
|
1590
|
+
expect(okResult.results[0].type).toBe("variant")
|
|
1591
|
+
if (okResult.results[0].type === "variant") {
|
|
1592
|
+
expect(okResult.results[0].displayType).toBe("result")
|
|
1637
1593
|
} else {
|
|
1638
1594
|
throw new Error("Expected variant field")
|
|
1639
1595
|
}
|
|
1640
1596
|
|
|
1641
|
-
const okValue = okResult.results[0]
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
expect(okValue.value.value).toBe("12345")
|
|
1597
|
+
const okValue = okResult.results[0] as ResolvedNode
|
|
1598
|
+
expect((okValue as any).selected).toBe("Ok")
|
|
1599
|
+
expect(((okValue as any).selectedOption as ResolvedNode).value).toBe(
|
|
1600
|
+
"12345"
|
|
1601
|
+
)
|
|
1647
1602
|
|
|
1648
1603
|
// Test Err case
|
|
1649
|
-
const errResult = methodMeta.
|
|
1604
|
+
const errResult = methodMeta.resolve({
|
|
1650
1605
|
Err: "Insufficient funds",
|
|
1651
1606
|
})
|
|
1652
|
-
const errValue = errResult.results[0]
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
expect(errValue.value.value).toBe("Insufficient funds")
|
|
1607
|
+
const errValue = errResult.results[0] as ResolvedNode
|
|
1608
|
+
expect((errValue as any).selected).toBe("Err")
|
|
1609
|
+
expect(((errValue as any).selectedOption as ResolvedNode).value).toBe(
|
|
1610
|
+
"Insufficient funds"
|
|
1611
|
+
)
|
|
1658
1612
|
})
|
|
1659
1613
|
|
|
1660
1614
|
it("should generate metadata for optional return value", () => {
|
|
@@ -1668,16 +1622,13 @@ describe("ResultFieldVisitor", () => {
|
|
|
1668
1622
|
const methodMeta = serviceMeta["findUser"]
|
|
1669
1623
|
|
|
1670
1624
|
// Test with value - Optional is [value]
|
|
1671
|
-
const foundResult = methodMeta.
|
|
1672
|
-
expect(foundResult.results[0].
|
|
1673
|
-
const foundInner = foundResult.results[0]
|
|
1674
|
-
|
|
1675
|
-
value: unknown
|
|
1676
|
-
}
|
|
1677
|
-
expect(foundInner.value).toBe("Alice")
|
|
1625
|
+
const foundResult = methodMeta.resolve(["Alice"])
|
|
1626
|
+
expect(foundResult.results[0].type).toBe("optional")
|
|
1627
|
+
const foundInner = foundResult.results[0] as OptionalNode
|
|
1628
|
+
expect(foundInner.value?.value).toBe("Alice")
|
|
1678
1629
|
|
|
1679
1630
|
// Test with null - optional is []
|
|
1680
|
-
const notFoundResult = methodMeta.
|
|
1631
|
+
const notFoundResult = methodMeta.resolve([])
|
|
1681
1632
|
expect(notFoundResult.results[0].value).toBe(null)
|
|
1682
1633
|
})
|
|
1683
1634
|
|
|
@@ -1691,17 +1642,15 @@ describe("ResultFieldVisitor", () => {
|
|
|
1691
1642
|
)
|
|
1692
1643
|
const methodMeta = serviceMeta["getItems"]
|
|
1693
1644
|
|
|
1694
|
-
const result = methodMeta.
|
|
1645
|
+
const result = methodMeta.resolve(["item1", "item2", "item3"])
|
|
1695
1646
|
|
|
1696
|
-
expect(result.results[0].
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
expect(
|
|
1702
|
-
expect(
|
|
1703
|
-
expect(vecValue[1].value).toBe("item2")
|
|
1704
|
-
expect(vecValue[2].value).toBe("item3")
|
|
1647
|
+
expect(result.results[0].type).toBe("vector")
|
|
1648
|
+
const vecNode = result.results[0] as ResolvedNode
|
|
1649
|
+
const vecItems = (vecNode as any).items as ResolvedNode[]
|
|
1650
|
+
expect(vecItems).toHaveLength(3)
|
|
1651
|
+
expect(vecItems[0].value).toBe("item1")
|
|
1652
|
+
expect(vecItems[1].value).toBe("item2")
|
|
1653
|
+
expect(vecItems[2].value).toBe("item3")
|
|
1705
1654
|
})
|
|
1706
1655
|
|
|
1707
1656
|
it("should generate metadata for update function", () => {
|
|
@@ -1717,7 +1666,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1717
1666
|
expect(methodMeta.functionType).toBe("update")
|
|
1718
1667
|
|
|
1719
1668
|
const rawData = [true]
|
|
1720
|
-
const result = methodMeta.
|
|
1669
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1721
1670
|
|
|
1722
1671
|
expect(result.functionType).toBe("update")
|
|
1723
1672
|
expect(result.functionName).toBe("setName")
|
|
@@ -1750,7 +1699,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1750
1699
|
const methodMeta = serviceMeta["icrc1_transfer"]
|
|
1751
1700
|
|
|
1752
1701
|
// Test successful transfer
|
|
1753
|
-
const successResult = methodMeta.
|
|
1702
|
+
const successResult = methodMeta.resolve({ Ok: BigInt(1000) })
|
|
1754
1703
|
console.log(
|
|
1755
1704
|
"🚀 ~ result:",
|
|
1756
1705
|
JSON.stringify(
|
|
@@ -1760,28 +1709,24 @@ describe("ResultFieldVisitor", () => {
|
|
|
1760
1709
|
)
|
|
1761
1710
|
)
|
|
1762
1711
|
|
|
1763
|
-
const successValue = successResult.results[0]
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
expect(successValue.value.value).toBe("1000")
|
|
1712
|
+
const successValue = successResult.results[0] as ResolvedNode
|
|
1713
|
+
expect((successValue as any).selected).toBe("Ok")
|
|
1714
|
+
expect(((successValue as any).selectedOption as ResolvedNode).value).toBe(
|
|
1715
|
+
"1000"
|
|
1716
|
+
)
|
|
1769
1717
|
|
|
1770
1718
|
// Test error case
|
|
1771
|
-
const errorResult = methodMeta.
|
|
1719
|
+
const errorResult = methodMeta.resolve({
|
|
1772
1720
|
Err: { InsufficientFunds: { balance: BigInt(50) } },
|
|
1773
1721
|
})
|
|
1774
|
-
const errorValue = errorResult.results[0]
|
|
1775
|
-
|
|
1776
|
-
value: { field: ResultField; value: unknown }
|
|
1777
|
-
}
|
|
1778
|
-
expect(errorValue.option).toBe("Err")
|
|
1722
|
+
const errorValue = errorResult.results[0] as ResolvedNode
|
|
1723
|
+
expect((errorValue as any).selected).toBe("Err")
|
|
1779
1724
|
|
|
1780
|
-
const val = errorValue.
|
|
1781
|
-
if (typeof val !== "object" || val === null || !("
|
|
1725
|
+
const val = (errorValue as any).selectedOption as ResolvedNode
|
|
1726
|
+
if (typeof val !== "object" || val === null || !("selected" in val)) {
|
|
1782
1727
|
throw new Error("Expected variant value object")
|
|
1783
1728
|
}
|
|
1784
|
-
expect(val.
|
|
1729
|
+
expect((val as any).selected).toBe("InsufficientFunds")
|
|
1785
1730
|
})
|
|
1786
1731
|
|
|
1787
1732
|
it("should handle empty return", () => {
|
|
@@ -1796,16 +1741,16 @@ describe("ResultFieldVisitor", () => {
|
|
|
1796
1741
|
|
|
1797
1742
|
expect(methodMeta.returnCount).toBe(0)
|
|
1798
1743
|
|
|
1799
|
-
const result = methodMeta.
|
|
1744
|
+
const result = methodMeta.resolve([])
|
|
1800
1745
|
expect(result.results).toHaveLength(0)
|
|
1801
1746
|
})
|
|
1802
1747
|
})
|
|
1803
1748
|
|
|
1804
1749
|
// ════════════════════════════════════════════════════════════════════════════
|
|
1805
|
-
//
|
|
1750
|
+
// resolve() Method Tests
|
|
1806
1751
|
// ════════════════════════════════════════════════════════════════════════════
|
|
1807
1752
|
|
|
1808
|
-
describe("
|
|
1753
|
+
describe("resolve() Method", () => {
|
|
1809
1754
|
it("should include both raw and display values for single return", () => {
|
|
1810
1755
|
const service = IDL.Service({
|
|
1811
1756
|
getBalance: IDL.Func([], [IDL.Nat], ["query"]),
|
|
@@ -1819,7 +1764,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1819
1764
|
// Simulate raw BigInt and display string
|
|
1820
1765
|
const rawData = [BigInt(1000000)]
|
|
1821
1766
|
|
|
1822
|
-
const result = methodMeta.
|
|
1767
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1823
1768
|
|
|
1824
1769
|
expect(result.functionName).toBe("getBalance")
|
|
1825
1770
|
expect(result.functionType).toBe("query")
|
|
@@ -1827,7 +1772,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1827
1772
|
expect(result.results[0].raw).toBe(BigInt(1000000))
|
|
1828
1773
|
expect(result.results[0].value).toBe("1000000")
|
|
1829
1774
|
expect(result.results[0].raw).toBe(BigInt(1000000))
|
|
1830
|
-
expect(result.results[0].
|
|
1775
|
+
expect(result.results[0].type).toBe("number")
|
|
1831
1776
|
})
|
|
1832
1777
|
|
|
1833
1778
|
it("should include both raw and display values for multiple returns", () => {
|
|
@@ -1843,14 +1788,14 @@ describe("ResultFieldVisitor", () => {
|
|
|
1843
1788
|
// Use BigInt with string to safe safe integer
|
|
1844
1789
|
const rawData = [BigInt("9007199254740993"), "active", true]
|
|
1845
1790
|
|
|
1846
|
-
const result = methodMeta.
|
|
1791
|
+
const result = methodMeta.resolve(rawData)
|
|
1847
1792
|
|
|
1848
1793
|
expect(result.results).toHaveLength(3)
|
|
1849
1794
|
|
|
1850
1795
|
// nat64 → string display, BigInt raw
|
|
1851
1796
|
expect(result.results[0].value).toBe("9007199254740993")
|
|
1852
1797
|
expect(result.results[0].raw).toBe(BigInt("9007199254740993"))
|
|
1853
|
-
expect(result.results[0].
|
|
1798
|
+
expect(result.results[0].candidType).toBe("nat64")
|
|
1854
1799
|
|
|
1855
1800
|
// text → same for both
|
|
1856
1801
|
expect(result.results[1].value).toBe("active")
|
|
@@ -1876,21 +1821,18 @@ describe("ResultFieldVisitor", () => {
|
|
|
1876
1821
|
const methodMeta = serviceMeta["getUser"]
|
|
1877
1822
|
|
|
1878
1823
|
const rawData = [{ name: "Alice", balance: BigInt(500) }]
|
|
1879
|
-
const result = methodMeta.
|
|
1824
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1880
1825
|
|
|
1881
1826
|
expect(result.results[0].raw).toEqual({
|
|
1882
1827
|
name: "Alice",
|
|
1883
1828
|
balance: BigInt(500),
|
|
1884
1829
|
})
|
|
1885
1830
|
|
|
1886
|
-
const
|
|
1887
|
-
if (
|
|
1888
|
-
throw new Error("Expected record
|
|
1831
|
+
const recordNode = result.results[0] as RecordNode
|
|
1832
|
+
if (recordNode.type !== "record") {
|
|
1833
|
+
throw new Error("Expected record node")
|
|
1889
1834
|
}
|
|
1890
|
-
const val =
|
|
1891
|
-
string,
|
|
1892
|
-
{ field: ResultField; value: unknown }
|
|
1893
|
-
>
|
|
1835
|
+
const val = recordNode.fields as Record<string, ResolvedNode>
|
|
1894
1836
|
expect(val.name.value).toBe("Alice")
|
|
1895
1837
|
expect(val.balance.value).toBe("500")
|
|
1896
1838
|
})
|
|
@@ -1912,20 +1854,13 @@ describe("ResultFieldVisitor", () => {
|
|
|
1912
1854
|
// Test Ok case with raw BigInt
|
|
1913
1855
|
const rawData = [{ Ok: BigInt(12345) }]
|
|
1914
1856
|
|
|
1915
|
-
const result = methodMeta.
|
|
1857
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1916
1858
|
|
|
1917
1859
|
expect(result.results[0].raw).toEqual({ Ok: BigInt(12345) })
|
|
1918
1860
|
|
|
1919
|
-
const variantValue = result.results[0]
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
variantValue === null ||
|
|
1923
|
-
!("option" in variantValue)
|
|
1924
|
-
) {
|
|
1925
|
-
throw new Error("Expected variant value object")
|
|
1926
|
-
}
|
|
1927
|
-
expect(variantValue.option).toBe("Ok")
|
|
1928
|
-
const innerVal = variantValue.value
|
|
1861
|
+
const variantValue = result.results[0] as ResolvedNode
|
|
1862
|
+
expect((variantValue as any).selected).toBe("Ok")
|
|
1863
|
+
const innerVal = (variantValue as any).selectedOption as ResolvedNode
|
|
1929
1864
|
expect(innerVal.value).toBe("12345")
|
|
1930
1865
|
})
|
|
1931
1866
|
|
|
@@ -1944,11 +1879,11 @@ describe("ResultFieldVisitor", () => {
|
|
|
1944
1879
|
const principal = Principal.fromText("aaaaa-aa")
|
|
1945
1880
|
const rawData = [principal]
|
|
1946
1881
|
|
|
1947
|
-
const result = methodMeta.
|
|
1882
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1948
1883
|
|
|
1949
1884
|
expect(result.results[0].value).toBe("aaaaa-aa")
|
|
1950
1885
|
expect(result.results[0].raw).toBe(principal)
|
|
1951
|
-
expect(result.results[0].
|
|
1886
|
+
expect(result.results[0].type).toBe("principal")
|
|
1952
1887
|
})
|
|
1953
1888
|
|
|
1954
1889
|
it("should handle vector with raw and display values", () => {
|
|
@@ -1963,12 +1898,10 @@ describe("ResultFieldVisitor", () => {
|
|
|
1963
1898
|
|
|
1964
1899
|
const rawData = [[BigInt(100), BigInt(200), BigInt(300)]]
|
|
1965
1900
|
|
|
1966
|
-
const result = methodMeta.
|
|
1901
|
+
const result = methodMeta.resolve(rawData[0])
|
|
1967
1902
|
|
|
1968
|
-
const
|
|
1969
|
-
|
|
1970
|
-
throw new Error("Expected vector value array")
|
|
1971
|
-
}
|
|
1903
|
+
const vecNode = result.results[0] as ResolvedNode
|
|
1904
|
+
const vecValue = (vecNode as any).items as ResolvedNode[]
|
|
1972
1905
|
expect(vecValue).toHaveLength(3)
|
|
1973
1906
|
expect(vecValue[0].value).toBe("100")
|
|
1974
1907
|
expect(vecValue[1].value).toBe("200")
|
|
@@ -1988,7 +1921,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
1988
1921
|
// Test with value - Optional is [value]
|
|
1989
1922
|
const rawDataWithValue = [[BigInt(999)]]
|
|
1990
1923
|
|
|
1991
|
-
const resultWithValue = methodMeta.
|
|
1924
|
+
const resultWithValue = methodMeta.resolve(rawDataWithValue[0])
|
|
1992
1925
|
|
|
1993
1926
|
expect(resultWithValue.results[0].raw).toEqual([BigInt(999)])
|
|
1994
1927
|
const innerValue = resultWithValue.results[0].value
|
|
@@ -2004,7 +1937,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
2004
1937
|
// Test with null - Optional is []
|
|
2005
1938
|
const rawDataNull = [[]]
|
|
2006
1939
|
|
|
2007
|
-
const resultNull = methodMeta.
|
|
1940
|
+
const resultNull = methodMeta.resolve(rawDataNull[0])
|
|
2008
1941
|
expect(resultNull.results[0].raw).toEqual([])
|
|
2009
1942
|
expect(resultNull.results[0].value).toBe(null)
|
|
2010
1943
|
})
|
|
@@ -2019,7 +1952,7 @@ describe("ResultFieldVisitor", () => {
|
|
|
2019
1952
|
)
|
|
2020
1953
|
const methodMeta = serviceMeta["doNothing"]
|
|
2021
1954
|
|
|
2022
|
-
const result = methodMeta.
|
|
1955
|
+
const result = methodMeta.resolve([])
|
|
2023
1956
|
|
|
2024
1957
|
expect(result.results).toHaveLength(0)
|
|
2025
1958
|
})
|