@webiny/app-admin 6.5.0-beta.2 → 6.5.0-beta.4
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/features/formModel/Field.d.ts +7 -1
- package/features/formModel/Field.js +13 -5
- package/features/formModel/Field.js.map +1 -1
- package/features/formModel/FieldBuilder.test.js +12 -0
- package/features/formModel/FieldBuilder.test.js.map +1 -1
- package/features/formModel/FormErrors.js +1 -1
- package/features/formModel/FormErrors.js.map +1 -1
- package/features/formModel/FormModel.d.ts +1 -0
- package/features/formModel/FormModel.js +17 -0
- package/features/formModel/FormModel.js.map +1 -1
- package/features/formModel/FormModel.test.js +339 -0
- package/features/formModel/FormModel.test.js.map +1 -1
- package/features/formModel/ObjectField.d.ts +9 -1
- package/features/formModel/ObjectField.js +26 -17
- package/features/formModel/ObjectField.js.map +1 -1
- package/features/formModel/abstractions.d.ts +14 -1
- package/features/formModel/abstractions.js.map +1 -1
- package/features/formModel/fieldTypes/DateTimeFieldType.d.ts +2 -0
- package/features/formModel/fieldTypes/DateTimeFieldType.js +14 -11
- package/features/formModel/fieldTypes/DateTimeFieldType.js.map +1 -1
- package/package.json +19 -19
|
@@ -4349,6 +4349,345 @@ describe("FormModel", ()=>{
|
|
|
4349
4349
|
expect(form.field("wrapper.editable").disabled).toBe(false);
|
|
4350
4350
|
});
|
|
4351
4351
|
});
|
|
4352
|
+
describe("$. static references in rules inside list items", ()=>{
|
|
4353
|
+
const hideWhen = (target, operator, value)=>[
|
|
4354
|
+
{
|
|
4355
|
+
type: "condition",
|
|
4356
|
+
target,
|
|
4357
|
+
operator,
|
|
4358
|
+
value,
|
|
4359
|
+
action: "hide"
|
|
4360
|
+
}
|
|
4361
|
+
];
|
|
4362
|
+
const itemChild = (form, listPath, index, name)=>{
|
|
4363
|
+
const list = form.field(listPath);
|
|
4364
|
+
const child = list.items[index]?.children.get(name);
|
|
4365
|
+
if (!child) throw new Error(`No child "${name}" on item ${index} of "${listPath}".`);
|
|
4366
|
+
return child;
|
|
4367
|
+
};
|
|
4368
|
+
it("resolves $. against the owning item of an object list", ()=>{
|
|
4369
|
+
const form = createForm({
|
|
4370
|
+
fields: (fields)=>({
|
|
4371
|
+
links: fields.object().list().renderer("passthrough").fields((f)=>({
|
|
4372
|
+
style: f.text(),
|
|
4373
|
+
url: f.text().rules(hideWhen("$.style", "==", "initiative")),
|
|
4374
|
+
customUrls: f.text().rules(hideWhen("$.style", "!=", "initiative"))
|
|
4375
|
+
}))
|
|
4376
|
+
})
|
|
4377
|
+
});
|
|
4378
|
+
form.setData({
|
|
4379
|
+
links: [
|
|
4380
|
+
{
|
|
4381
|
+
style: "initiative"
|
|
4382
|
+
},
|
|
4383
|
+
{
|
|
4384
|
+
style: "standard"
|
|
4385
|
+
}
|
|
4386
|
+
]
|
|
4387
|
+
});
|
|
4388
|
+
expect(itemChild(form, "links", 0, "url").visible).toBe(false);
|
|
4389
|
+
expect(itemChild(form, "links", 0, "customUrls").visible).toBe(true);
|
|
4390
|
+
expect(itemChild(form, "links", 1, "url").visible).toBe(true);
|
|
4391
|
+
expect(itemChild(form, "links", 1, "customUrls").visible).toBe(false);
|
|
4392
|
+
itemChild(form, "links", 1, "style").setValue("initiative");
|
|
4393
|
+
expect(itemChild(form, "links", 1, "url").visible).toBe(false);
|
|
4394
|
+
expect(itemChild(form, "links", 1, "customUrls").visible).toBe(true);
|
|
4395
|
+
});
|
|
4396
|
+
it("resolves $. for items added with addItem()", ()=>{
|
|
4397
|
+
const form = createForm({
|
|
4398
|
+
fields: (fields)=>({
|
|
4399
|
+
links: fields.object().list().renderer("passthrough").fields((f)=>({
|
|
4400
|
+
locked: f.boolean(),
|
|
4401
|
+
label: f.text().rules([
|
|
4402
|
+
{
|
|
4403
|
+
type: "condition",
|
|
4404
|
+
target: "$.locked",
|
|
4405
|
+
operator: "==",
|
|
4406
|
+
value: true,
|
|
4407
|
+
action: "disable"
|
|
4408
|
+
}
|
|
4409
|
+
])
|
|
4410
|
+
}))
|
|
4411
|
+
})
|
|
4412
|
+
});
|
|
4413
|
+
form.field("links").addItem();
|
|
4414
|
+
expect(itemChild(form, "links", 0, "label").disabled).toBe(false);
|
|
4415
|
+
itemChild(form, "links", 0, "locked").setValue(true);
|
|
4416
|
+
expect(itemChild(form, "links", 0, "label").disabled).toBe(true);
|
|
4417
|
+
});
|
|
4418
|
+
it("keeps resolving against the owning item after reorder and removal", ()=>{
|
|
4419
|
+
const form = createForm({
|
|
4420
|
+
fields: (fields)=>({
|
|
4421
|
+
links: fields.object().list().renderer("passthrough").fields((f)=>({
|
|
4422
|
+
style: f.text(),
|
|
4423
|
+
url: f.text().rules(hideWhen("$.style", "==", "initiative"))
|
|
4424
|
+
}))
|
|
4425
|
+
})
|
|
4426
|
+
});
|
|
4427
|
+
form.setData({
|
|
4428
|
+
links: [
|
|
4429
|
+
{
|
|
4430
|
+
style: "initiative"
|
|
4431
|
+
},
|
|
4432
|
+
{
|
|
4433
|
+
style: "standard"
|
|
4434
|
+
}
|
|
4435
|
+
]
|
|
4436
|
+
});
|
|
4437
|
+
const list = form.field("links");
|
|
4438
|
+
const firstUrl = itemChild(form, "links", 0, "url");
|
|
4439
|
+
const secondUrl = itemChild(form, "links", 1, "url");
|
|
4440
|
+
list.moveItem(0, 1);
|
|
4441
|
+
expect(firstUrl.visible).toBe(false);
|
|
4442
|
+
expect(secondUrl.visible).toBe(true);
|
|
4443
|
+
list.removeItem(0);
|
|
4444
|
+
expect(firstUrl.visible).toBe(false);
|
|
4445
|
+
});
|
|
4446
|
+
it("field.parent() resolves siblings of the owning item in callbacks", ()=>{
|
|
4447
|
+
const form = createForm({
|
|
4448
|
+
fields: (fields)=>({
|
|
4449
|
+
links: fields.object().list().renderer("passthrough").fields((f)=>({
|
|
4450
|
+
style: f.text(),
|
|
4451
|
+
url: f.text().hiddenWhen(({ field })=>"initiative" === field.parent().field("style").getValue())
|
|
4452
|
+
}))
|
|
4453
|
+
})
|
|
4454
|
+
});
|
|
4455
|
+
form.setData({
|
|
4456
|
+
links: [
|
|
4457
|
+
{
|
|
4458
|
+
style: "initiative"
|
|
4459
|
+
},
|
|
4460
|
+
{
|
|
4461
|
+
style: "standard"
|
|
4462
|
+
}
|
|
4463
|
+
]
|
|
4464
|
+
});
|
|
4465
|
+
expect(itemChild(form, "links", 0, "url").visible).toBe(false);
|
|
4466
|
+
expect(itemChild(form, "links", 1, "url").visible).toBe(true);
|
|
4467
|
+
});
|
|
4468
|
+
describe("dynamic zone shaped templated list", ()=>{
|
|
4469
|
+
const createBlocksForm = ()=>createForm({
|
|
4470
|
+
fields: (fields)=>({
|
|
4471
|
+
blocks: fields.object().list().renderer("passthrough").template("heroBlock", (t)=>{
|
|
4472
|
+
t.label("Hero").fields((f)=>({
|
|
4473
|
+
_id: f.text().hidden(),
|
|
4474
|
+
ctaStyle: f.text(),
|
|
4475
|
+
ctaUrl: f.text().rules(hideWhen("$.ctaStyle", "==", "initiative")),
|
|
4476
|
+
customUrls: f.text().rules(hideWhen("$.ctaStyle", "!=", "initiative"))
|
|
4477
|
+
}));
|
|
4478
|
+
}).template("richTextBlock", (t)=>{
|
|
4479
|
+
t.label("Rich Text").fields((f)=>({
|
|
4480
|
+
_id: f.text().hidden(),
|
|
4481
|
+
headerStyle: f.text().defaultValue("manual"),
|
|
4482
|
+
header: f.text().rules(hideWhen("$.headerStyle", "!=", "manual")),
|
|
4483
|
+
headingGroupRef: f.text().rules(hideWhen("$.headerStyle", "!=", "reference"))
|
|
4484
|
+
}));
|
|
4485
|
+
}).template("classesBlock", (t)=>{
|
|
4486
|
+
t.label("Classes").fields((f)=>({
|
|
4487
|
+
_id: f.text().hidden(),
|
|
4488
|
+
classes: f.object().list().renderer("passthrough").fields((c)=>({
|
|
4489
|
+
customCTA: c.boolean(),
|
|
4490
|
+
customCTALabel: c.text().rules(hideWhen("$.customCTA", "!=", true))
|
|
4491
|
+
}))
|
|
4492
|
+
}));
|
|
4493
|
+
})
|
|
4494
|
+
})
|
|
4495
|
+
});
|
|
4496
|
+
it("resolves $. against the owning template item", ()=>{
|
|
4497
|
+
const form = createBlocksForm();
|
|
4498
|
+
form.setData({
|
|
4499
|
+
blocks: [
|
|
4500
|
+
{
|
|
4501
|
+
_templateId: "heroBlock",
|
|
4502
|
+
_id: "hero1",
|
|
4503
|
+
ctaStyle: "initiative"
|
|
4504
|
+
},
|
|
4505
|
+
{
|
|
4506
|
+
_templateId: "heroBlock",
|
|
4507
|
+
_id: "hero2",
|
|
4508
|
+
ctaStyle: "standard"
|
|
4509
|
+
}
|
|
4510
|
+
]
|
|
4511
|
+
});
|
|
4512
|
+
expect(itemChild(form, "blocks", 0, "ctaUrl").visible).toBe(false);
|
|
4513
|
+
expect(itemChild(form, "blocks", 0, "customUrls").visible).toBe(true);
|
|
4514
|
+
expect(itemChild(form, "blocks", 1, "ctaUrl").visible).toBe(true);
|
|
4515
|
+
expect(itemChild(form, "blocks", 1, "customUrls").visible).toBe(false);
|
|
4516
|
+
});
|
|
4517
|
+
it("re-evaluates when the referenced sibling changes", ()=>{
|
|
4518
|
+
const form = createBlocksForm();
|
|
4519
|
+
form.setData({
|
|
4520
|
+
blocks: [
|
|
4521
|
+
{
|
|
4522
|
+
_templateId: "richTextBlock",
|
|
4523
|
+
_id: "rt1",
|
|
4524
|
+
headerStyle: "manual"
|
|
4525
|
+
}
|
|
4526
|
+
]
|
|
4527
|
+
});
|
|
4528
|
+
expect(itemChild(form, "blocks", 0, "header").visible).toBe(true);
|
|
4529
|
+
expect(itemChild(form, "blocks", 0, "headingGroupRef").visible).toBe(false);
|
|
4530
|
+
itemChild(form, "blocks", 0, "headerStyle").setValue("reference");
|
|
4531
|
+
expect(itemChild(form, "blocks", 0, "header").visible).toBe(false);
|
|
4532
|
+
expect(itemChild(form, "blocks", 0, "headingGroupRef").visible).toBe(true);
|
|
4533
|
+
});
|
|
4534
|
+
it("resolves $. inside an object list nested in a template item", ()=>{
|
|
4535
|
+
const form = createBlocksForm();
|
|
4536
|
+
form.setData({
|
|
4537
|
+
blocks: [
|
|
4538
|
+
{
|
|
4539
|
+
_templateId: "classesBlock",
|
|
4540
|
+
_id: "classes1",
|
|
4541
|
+
classes: [
|
|
4542
|
+
{
|
|
4543
|
+
customCTA: true
|
|
4544
|
+
},
|
|
4545
|
+
{
|
|
4546
|
+
customCTA: false
|
|
4547
|
+
}
|
|
4548
|
+
]
|
|
4549
|
+
}
|
|
4550
|
+
]
|
|
4551
|
+
});
|
|
4552
|
+
const classes = itemChild(form, "blocks", 0, "classes");
|
|
4553
|
+
const classItem = (index, name)=>classes.items[index].children.get(name);
|
|
4554
|
+
expect(classItem(0, "customCTALabel").visible).toBe(true);
|
|
4555
|
+
expect(classItem(1, "customCTALabel").visible).toBe(false);
|
|
4556
|
+
classItem(1, "customCTA").setValue(true);
|
|
4557
|
+
expect(classItem(1, "customCTALabel").visible).toBe(true);
|
|
4558
|
+
});
|
|
4559
|
+
});
|
|
4560
|
+
});
|
|
4561
|
+
describe("setErrors", ()=>{
|
|
4562
|
+
const createProductForm = ()=>createForm({
|
|
4563
|
+
fields: (fields)=>({
|
|
4564
|
+
sku: fields.text().label("SKU"),
|
|
4565
|
+
variants: fields.object().list().label("Variants").fields((f)=>({
|
|
4566
|
+
code: f.text().label("Code")
|
|
4567
|
+
}))
|
|
4568
|
+
})
|
|
4569
|
+
});
|
|
4570
|
+
it("assigns an error to the field at its path and lists it in form errors", ()=>{
|
|
4571
|
+
const form = createProductForm();
|
|
4572
|
+
form.setErrors([
|
|
4573
|
+
{
|
|
4574
|
+
path: "sku",
|
|
4575
|
+
message: "Value must be unique."
|
|
4576
|
+
}
|
|
4577
|
+
]);
|
|
4578
|
+
expect(form.field("sku").vm.validation).toMatchObject({
|
|
4579
|
+
isValid: false,
|
|
4580
|
+
message: "Value must be unique."
|
|
4581
|
+
});
|
|
4582
|
+
expect(form.vm.hasErrors).toBe(true);
|
|
4583
|
+
expect(form.errors).toEqual([
|
|
4584
|
+
{
|
|
4585
|
+
path: "sku",
|
|
4586
|
+
label: "SKU",
|
|
4587
|
+
breadcrumb: [
|
|
4588
|
+
"SKU"
|
|
4589
|
+
],
|
|
4590
|
+
message: "Value must be unique."
|
|
4591
|
+
}
|
|
4592
|
+
]);
|
|
4593
|
+
});
|
|
4594
|
+
it("resolves paths into list items", ()=>{
|
|
4595
|
+
const form = createProductForm();
|
|
4596
|
+
form.setData({
|
|
4597
|
+
variants: [
|
|
4598
|
+
{
|
|
4599
|
+
code: "a"
|
|
4600
|
+
},
|
|
4601
|
+
{
|
|
4602
|
+
code: "b"
|
|
4603
|
+
}
|
|
4604
|
+
]
|
|
4605
|
+
});
|
|
4606
|
+
form.setErrors([
|
|
4607
|
+
{
|
|
4608
|
+
path: "variants.1.code",
|
|
4609
|
+
message: "Invalid code."
|
|
4610
|
+
}
|
|
4611
|
+
]);
|
|
4612
|
+
const list = form.field("variants");
|
|
4613
|
+
expect(list.items[1].children.get("code").vm.validation.isValid).toBe(false);
|
|
4614
|
+
expect(list.items[0].children.get("code").vm.validation.isValid).not.toBe(false);
|
|
4615
|
+
expect(form.errors).toEqual([
|
|
4616
|
+
expect.objectContaining({
|
|
4617
|
+
path: "variants.1.code",
|
|
4618
|
+
breadcrumb: [
|
|
4619
|
+
"Variants",
|
|
4620
|
+
"Code"
|
|
4621
|
+
]
|
|
4622
|
+
})
|
|
4623
|
+
]);
|
|
4624
|
+
});
|
|
4625
|
+
it("keeps errors without a matching field as form-level errors", ()=>{
|
|
4626
|
+
const form = createProductForm();
|
|
4627
|
+
form.setErrors([
|
|
4628
|
+
{
|
|
4629
|
+
path: "",
|
|
4630
|
+
message: "Could not update entry."
|
|
4631
|
+
},
|
|
4632
|
+
{
|
|
4633
|
+
path: "unknown.field",
|
|
4634
|
+
message: "Something is wrong."
|
|
4635
|
+
}
|
|
4636
|
+
]);
|
|
4637
|
+
expect(form.errors).toEqual([
|
|
4638
|
+
{
|
|
4639
|
+
path: "",
|
|
4640
|
+
message: "Could not update entry."
|
|
4641
|
+
},
|
|
4642
|
+
{
|
|
4643
|
+
path: "unknown.field",
|
|
4644
|
+
message: "Something is wrong."
|
|
4645
|
+
}
|
|
4646
|
+
]);
|
|
4647
|
+
expect(form.isValid).toBe(false);
|
|
4648
|
+
});
|
|
4649
|
+
it("bumps submitCount so FormErrors scrolls into view", ()=>{
|
|
4650
|
+
const form = createProductForm();
|
|
4651
|
+
const before = form.submitCount;
|
|
4652
|
+
form.setErrors([
|
|
4653
|
+
{
|
|
4654
|
+
path: "sku",
|
|
4655
|
+
message: "Value must be unique."
|
|
4656
|
+
}
|
|
4657
|
+
]);
|
|
4658
|
+
expect(form.submitCount).toBe(before + 1);
|
|
4659
|
+
});
|
|
4660
|
+
it("is cleared by the next validate()", async ()=>{
|
|
4661
|
+
const form = createProductForm();
|
|
4662
|
+
form.setErrors([
|
|
4663
|
+
{
|
|
4664
|
+
path: "sku",
|
|
4665
|
+
message: "Value must be unique."
|
|
4666
|
+
},
|
|
4667
|
+
{
|
|
4668
|
+
path: "",
|
|
4669
|
+
message: "Could not update entry."
|
|
4670
|
+
}
|
|
4671
|
+
]);
|
|
4672
|
+
await form.validate();
|
|
4673
|
+
expect(form.errors).toEqual([]);
|
|
4674
|
+
expect(form.field("sku").vm.validation.isValid).not.toBe(false);
|
|
4675
|
+
});
|
|
4676
|
+
it("is cleared by setData()", ()=>{
|
|
4677
|
+
const form = createProductForm();
|
|
4678
|
+
form.setErrors([
|
|
4679
|
+
{
|
|
4680
|
+
path: "",
|
|
4681
|
+
message: "Could not update entry."
|
|
4682
|
+
}
|
|
4683
|
+
]);
|
|
4684
|
+
form.setData({
|
|
4685
|
+
sku: "ABC"
|
|
4686
|
+
});
|
|
4687
|
+
expect(form.errors).toEqual([]);
|
|
4688
|
+
expect(form.vm.hasErrors).toBe(false);
|
|
4689
|
+
});
|
|
4690
|
+
});
|
|
4352
4691
|
});
|
|
4353
4692
|
|
|
4354
4693
|
//# sourceMappingURL=FormModel.test.js.map
|