xmlui 0.10.13 → 0.10.14

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.
Files changed (186) hide show
  1. package/dist/lib/{index-Db5iQkFp.mjs → index-779mp2Bm.mjs} +943 -736
  2. package/dist/lib/index.css +1 -1
  3. package/dist/lib/{initMock-B9LtmFJG.mjs → initMock-CAXdczCj.mjs} +1 -1
  4. package/dist/lib/xmlui.d.ts +16 -1
  5. package/dist/lib/xmlui.mjs +33 -32
  6. package/dist/metadata/{collectedComponentMetadata-BN8eg9Gr.mjs → collectedComponentMetadata-7DFXlw-J.mjs} +15057 -14865
  7. package/dist/metadata/{initMock-J7pN8owj.mjs → initMock-AFWEftc6.mjs} +1 -1
  8. package/dist/metadata/style.css +1 -1
  9. package/dist/metadata/xmlui-metadata.mjs +1 -1
  10. package/dist/metadata/xmlui-metadata.umd.js +3 -3
  11. package/dist/scripts/bin/build-lib.js +21 -13
  12. package/dist/scripts/bin/viteConfig.js +3 -1
  13. package/dist/scripts/package.json +1 -1
  14. package/dist/scripts/src/abstractions/scripting/Token.js +2 -0
  15. package/dist/scripts/src/abstractions/scripting/TryScope.js +2 -0
  16. package/dist/scripts/src/abstractions/scripting/modules.js +2 -0
  17. package/dist/scripts/src/components/APICall/APICall.spec.js +910 -0
  18. package/dist/scripts/src/components/Accordion/Accordion.spec.js +969 -0
  19. package/dist/scripts/src/components/Animation/Animation.js +50 -0
  20. package/dist/scripts/src/components/App/App.spec.js +219 -0
  21. package/dist/scripts/src/components/AppHeader/AppHeader.spec.js +169 -0
  22. package/dist/scripts/src/components/AppState/AppState.spec.js +268 -0
  23. package/dist/scripts/src/components/AutoComplete/AutoComplete.spec.js +383 -0
  24. package/dist/scripts/src/components/Avatar/Avatar.spec.js +1543 -0
  25. package/dist/scripts/src/components/Backdrop/Backdrop.spec.js +131 -0
  26. package/dist/scripts/src/components/Badge/Badge.spec.js +2214 -0
  27. package/dist/scripts/src/components/Bookmark/Bookmark.spec.js +230 -0
  28. package/dist/scripts/src/components/Breakout/Breakout.spec.js +56 -0
  29. package/dist/scripts/src/components/Button/Button-style.spec.js +274 -0
  30. package/dist/scripts/src/components/Button/Button.spec.js +454 -0
  31. package/dist/scripts/src/components/Card/Card.spec.js +150 -0
  32. package/dist/scripts/src/components/Carousel/Carousel.spec.js +343 -0
  33. package/dist/scripts/src/components/Carousel/CarouselNative.js +2 -2
  34. package/dist/scripts/src/components/ChangeListener/ChangeListener.spec.js +169 -0
  35. package/dist/scripts/src/components/Charts/AreaChart/AreaChart.spec.js +999 -0
  36. package/dist/scripts/src/components/Charts/BarChart/BarChart.spec.js +597 -0
  37. package/dist/scripts/src/components/Charts/DonutChart/DonutChart.spec.js +608 -0
  38. package/dist/scripts/src/components/Charts/LabelList/LabelList.spec.js +539 -0
  39. package/dist/scripts/src/components/Charts/Legend/Legend.spec.js +558 -0
  40. package/dist/scripts/src/components/Charts/LineChart/LineChart.spec.js +450 -0
  41. package/dist/scripts/src/components/Charts/PieChart/PieChart.spec.js +584 -0
  42. package/dist/scripts/src/components/Charts/RadarChart/RadarChart.spec.js +571 -0
  43. package/dist/scripts/src/components/Charts/Tooltip/TooltipContent.spec.js +449 -0
  44. package/dist/scripts/src/components/Checkbox/Checkbox.spec.js +964 -0
  45. package/dist/scripts/src/components/CodeBlock/CodeBlock.spec.js +196 -0
  46. package/dist/scripts/src/components/ColorPicker/ColorPicker.spec.js +283 -0
  47. package/dist/scripts/src/components/ColorPicker/ColorPickerNative.js +9 -26
  48. package/dist/scripts/src/components/Column/doc-resources/list-component-data.js +53 -0
  49. package/dist/scripts/src/components/ComponentProvider.js +6 -2
  50. package/dist/scripts/src/components/ContentSeparator/ContentSeparator.spec.js +338 -0
  51. package/dist/scripts/src/components/DateInput/DateInput.spec.js +918 -0
  52. package/dist/scripts/src/components/DatePicker/DatePicker.spec.js +362 -0
  53. package/dist/scripts/src/components/DatePicker/DatePickerNative.js +3 -3
  54. package/dist/scripts/src/components/DropdownMenu/DropdownMenu.spec.js +331 -0
  55. package/dist/scripts/src/components/EmojiSelector/EmojiSelector.spec.js +29 -0
  56. package/dist/scripts/src/components/ExpandableItem/ExpandableItem.spec.js +435 -0
  57. package/dist/scripts/src/components/FileInput/FileInput.spec.js +249 -0
  58. package/dist/scripts/src/components/FileUploadDropZone/FileUploadDropZone.spec.js +296 -0
  59. package/dist/scripts/src/components/FlowLayout/FlowLayout.spec.js +518 -0
  60. package/dist/scripts/src/components/Footer/Footer.spec.js +991 -0
  61. package/dist/scripts/src/components/Form/Form.spec.js +1257 -0
  62. package/dist/scripts/src/components/FormItem/FormItem.spec.js +723 -0
  63. package/dist/scripts/src/components/FormSection/FormSection.js +6 -31
  64. package/dist/scripts/src/components/Fragment/Fragment.spec.js +50 -0
  65. package/dist/scripts/src/components/Heading/H1.spec.js +66 -0
  66. package/dist/scripts/src/components/Heading/H2.spec.js +66 -0
  67. package/dist/scripts/src/components/Heading/H3.spec.js +66 -0
  68. package/dist/scripts/src/components/Heading/H4.spec.js +66 -0
  69. package/dist/scripts/src/components/Heading/H5.spec.js +66 -0
  70. package/dist/scripts/src/components/Heading/H6.spec.js +66 -0
  71. package/dist/scripts/src/components/Heading/Heading.spec.js +897 -0
  72. package/dist/scripts/src/components/HtmlTags/HtmlTags.spec.js +69 -0
  73. package/dist/scripts/src/components/IFrame/IFrame.spec.js +527 -0
  74. package/dist/scripts/src/components/Icon/ArrowDropDown.js +11 -0
  75. package/dist/scripts/src/components/Icon/ArrowDropUp.js +11 -0
  76. package/dist/scripts/src/components/Icon/ArrowLeft.js +11 -0
  77. package/dist/scripts/src/components/Icon/ArrowRight.js +11 -0
  78. package/dist/scripts/src/components/Icon/ChevronDownIcon.js +7 -0
  79. package/dist/scripts/src/components/Icon/ChevronUpIcon.js +7 -0
  80. package/dist/scripts/src/components/Icon/Icon.spec.js +527 -0
  81. package/dist/scripts/src/components/Icon/SunIcon.js +10 -0
  82. package/dist/scripts/src/components/Image/Image.js +2 -1
  83. package/dist/scripts/src/components/Image/Image.spec.js +198 -0
  84. package/dist/scripts/src/components/Image/ImageNative.js +30 -2
  85. package/dist/scripts/src/components/Input/InputLabel.js +25 -0
  86. package/dist/scripts/src/components/Input/index.js +5 -0
  87. package/dist/scripts/src/components/Items/Items.spec.js +397 -0
  88. package/dist/scripts/src/components/Link/Link.spec.js +894 -0
  89. package/dist/scripts/src/components/List/List.spec.js +927 -0
  90. package/dist/scripts/src/components/List/doc-resources/list-component-data.js +53 -0
  91. package/dist/scripts/src/components/Markdown/Markdown.spec.js +188 -0
  92. package/dist/scripts/src/components/ModalDialog/ModalDialog.spec.js +162 -0
  93. package/dist/scripts/src/components/NavGroup/NavGroup.spec.js +153 -0
  94. package/dist/scripts/src/components/NavGroup/NavGroupNative.js +2 -2
  95. package/dist/scripts/src/components/NavLink/NavLink.spec.js +864 -0
  96. package/dist/scripts/src/components/NavPanel/NavPanel.spec.js +864 -0
  97. package/dist/scripts/src/components/NoResult/NoResult.spec.js +863 -0
  98. package/dist/scripts/src/components/NumberBox/NumberBox.spec.js +1231 -0
  99. package/dist/scripts/src/components/Option/Option.spec.js +472 -0
  100. package/dist/scripts/src/components/PageMetaTitle/PageMetaTitle.spec.js +80 -0
  101. package/dist/scripts/src/components/Pagination/Pagination.spec.js +1003 -0
  102. package/dist/scripts/src/components/ProfileMenu/ProfileMenu.js +20 -0
  103. package/dist/scripts/src/components/ProgressBar/ProgressBar.spec.js +166 -0
  104. package/dist/scripts/src/components/Queue/Queue.spec.js +626 -0
  105. package/dist/scripts/src/components/RadioGroup/RadioGroup.spec.js +479 -0
  106. package/dist/scripts/src/components/Redirect/Redirect.spec.js +527 -0
  107. package/dist/scripts/src/components/ResponsiveBar/ResponsiveBar.spec.js +76 -0
  108. package/dist/scripts/src/components/Select/Select.spec.js +527 -0
  109. package/dist/scripts/src/components/Slider/Slider.js +2 -0
  110. package/dist/scripts/src/components/Slider/Slider.spec.js +574 -0
  111. package/dist/scripts/src/components/Slider/SliderNative.js +62 -25
  112. package/dist/scripts/src/components/Slot/Slot.spec.js +368 -0
  113. package/dist/scripts/src/components/SpaceFiller/SpaceFiller.spec.js +184 -0
  114. package/dist/scripts/src/components/Spinner/Spinner.spec.js +161 -0
  115. package/dist/scripts/src/components/Splitter/HSplitter.spec.js +104 -0
  116. package/dist/scripts/src/components/Splitter/Splitter.spec.js +543 -0
  117. package/dist/scripts/src/components/Splitter/VSplitter.spec.js +104 -0
  118. package/dist/scripts/src/components/Stack/CHStack.spec.js +86 -0
  119. package/dist/scripts/src/components/Stack/CVStack.spec.js +86 -0
  120. package/dist/scripts/src/components/Stack/HStack.spec.js +67 -0
  121. package/dist/scripts/src/components/Stack/Stack.spec.js +654 -0
  122. package/dist/scripts/src/components/Stack/VStack.spec.js +67 -0
  123. package/dist/scripts/src/components/Switch/Switch.spec.js +829 -0
  124. package/dist/scripts/src/components/Table/Table.spec.js +555 -0
  125. package/dist/scripts/src/components/Table/doc-resources/list-component-data.js +53 -0
  126. package/dist/scripts/src/components/TableOfContents/TableOfContents.spec.js +838 -0
  127. package/dist/scripts/src/components/Tabs/Tabs.spec.js +875 -0
  128. package/dist/scripts/src/components/Text/Text.spec.js +1075 -0
  129. package/dist/scripts/src/components/TextArea/TextArea.spec.js +714 -0
  130. package/dist/scripts/src/components/TextBox/TextBox.spec.js +643 -0
  131. package/dist/scripts/src/components/Theme/Theme.spec.js +124 -0
  132. package/dist/scripts/src/components/TimeInput/TimeInput.spec.js +1122 -0
  133. package/dist/scripts/src/components/Timer/Timer.spec.js +358 -0
  134. package/dist/scripts/src/components/ToneChangerButton/ToneChangerButton.spec.js +414 -0
  135. package/dist/scripts/src/components/ToneSwitch/ToneSwitch.spec.js +89 -0
  136. package/dist/scripts/src/components/Tooltip/Tooltip.spec.js +418 -0
  137. package/dist/scripts/src/components/chart-color-schemes.js +43 -0
  138. package/dist/scripts/src/components-core/CompoundComponent.js +1 -1
  139. package/dist/scripts/src/components-core/RestApiProxy.js +85 -8
  140. package/dist/scripts/src/components-core/devtools/InspectorDialogVisibilityContext.js +8 -0
  141. package/dist/scripts/src/components-core/renderers.js +31 -0
  142. package/dist/scripts/src/components-core/script-runner/simplify-expression.js +386 -0
  143. package/dist/scripts/src/components-core/theming/component-layout-resolver.js +153 -0
  144. package/dist/scripts/src/components-core/theming/parse-layout-props.js +98 -0
  145. package/dist/scripts/src/components-core/theming/themes/solid.js +16 -0
  146. package/dist/scripts/src/components-core/utils/audio-utils.js +83 -0
  147. package/dist/scripts/src/index-standalone.js +61 -0
  148. package/dist/scripts/src/index.js +2 -1
  149. package/dist/scripts/src/language-server/server-common.js +151 -0
  150. package/dist/scripts/src/language-server/server-web-worker.js +47 -0
  151. package/dist/scripts/src/language-server/server.js +42 -0
  152. package/dist/scripts/src/language-server/services/common/docs-generation.js +73 -0
  153. package/dist/scripts/src/language-server/services/common/lsp-utils.js +9 -0
  154. package/dist/scripts/src/language-server/services/common/syntax-node-utilities.js +135 -0
  155. package/dist/scripts/src/language-server/services/completion.js +270 -0
  156. package/dist/scripts/src/language-server/services/diagnostic.js +19 -0
  157. package/dist/scripts/src/language-server/services/format.js +430 -0
  158. package/dist/scripts/src/language-server/services/hover.js +164 -0
  159. package/dist/scripts/src/language-server/xmlui-metadata-generated.mjs +16266 -0
  160. package/dist/scripts/src/logging/xmlui.js +21 -0
  161. package/dist/scripts/src/parsers/common/utils.js +19 -0
  162. package/dist/scripts/src/syntax/monaco/grammar.monacoLanguage.js +286 -0
  163. package/dist/scripts/src/syntax/monaco/index.js +14 -0
  164. package/dist/scripts/src/syntax/monaco/xmlui-dark.js +25 -0
  165. package/dist/scripts/src/syntax/monaco/xmlui-light.js +25 -0
  166. package/dist/scripts/src/syntax/monaco/xmluiscript.monacoLanguage.js +310 -0
  167. package/dist/scripts/src/syntax/textMate/index.js +14 -0
  168. package/dist/scripts/src/syntax/textMate/xmlui-dark.json +631 -0
  169. package/dist/scripts/src/syntax/textMate/xmlui-light.json +565 -0
  170. package/dist/scripts/src/syntax/textMate/xmlui.json +564 -0
  171. package/dist/scripts/src/syntax/textMate/xmlui.tmLanguage.json +341 -0
  172. package/dist/scripts/src/testing/ComponentDrivers.js +1355 -0
  173. package/dist/scripts/src/testing/assertions.js +444 -0
  174. package/dist/scripts/src/testing/component-test-helpers.js +389 -0
  175. package/dist/scripts/src/testing/drivers/DateInputDriver.js +19 -0
  176. package/dist/scripts/src/testing/drivers/ModalDialogDriver.js +10 -0
  177. package/dist/scripts/src/testing/drivers/TimeInputDriver.js +22 -0
  178. package/dist/scripts/src/testing/drivers/TimerDriver.js +64 -0
  179. package/dist/scripts/src/testing/fixtures.js +487 -0
  180. package/dist/scripts/src/testing/infrastructure/TestBed.js +17 -0
  181. package/dist/scripts/src/testing/infrastructure/main.js +9 -0
  182. package/dist/scripts/src/testing/infrastructure/public/mockServiceWorker.js +266 -0
  183. package/dist/scripts/src/testing/themed-app-test-helpers.js +139 -0
  184. package/dist/standalone/xmlui-standalone.es.d.ts +18 -1
  185. package/dist/standalone/xmlui-standalone.umd.js +36 -36
  186. package/package.json +1 -1
@@ -0,0 +1,1257 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const abstractions_1 = require("../abstractions");
13
+ const fixtures_1 = require("../../testing/fixtures");
14
+ // Test data constants
15
+ const errorDisplayInterceptor = {
16
+ initialize: `
17
+ $state.items = {
18
+ [10]: { name: "Smith", id: 10 }
19
+ };
20
+ $state.currentId = 10;
21
+ `,
22
+ operations: {
23
+ "no-validation-error": {
24
+ url: "/no-validation-error",
25
+ method: "post",
26
+ handler: `return true;`,
27
+ },
28
+ "general-validation-error": {
29
+ url: "/general-validation-error",
30
+ method: "post",
31
+ handler: `
32
+ throw Errors.HttpError(404,
33
+ {
34
+ message: "General error message from the backend",
35
+ issues: [
36
+ { message: "Error for the whole form", severity: "error" },
37
+ { message: "Warning for the whole form", severity: "warning" },
38
+ ]
39
+ }
40
+ );
41
+ `,
42
+ },
43
+ "field-validation-error": {
44
+ url: "/field-validation-error",
45
+ method: "post",
46
+ handler: `
47
+ throw Errors.HttpError(404,
48
+ {
49
+ message: "Field error message from the backend",
50
+ issues: [
51
+ { field: "test", message: "Display warning", severity: "warning" },
52
+ ]
53
+ }
54
+ );
55
+ `,
56
+ },
57
+ },
58
+ };
59
+ // =============================================================================
60
+ // BASIC FUNCTIONALITY TESTS
61
+ // =============================================================================
62
+ fixtures_1.test.describe("Basic Functionality", () => {
63
+ (0, fixtures_1.test)("component renders with default props", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
64
+ yield initTestBed(`<Form testId="form"/>`);
65
+ const driver = yield createFormDriver("form");
66
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
67
+ }));
68
+ (0, fixtures_1.test)("component renders with form items", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
69
+ yield initTestBed(`
70
+ <Form>
71
+ <FormItem label="Name" bindTo="name" />
72
+ <FormItem label="Email" bindTo="email" />
73
+ </Form>
74
+ `);
75
+ yield (0, fixtures_1.expect)(page.getByText("Name")).toBeVisible();
76
+ yield (0, fixtures_1.expect)(page.getByText("Email")).toBeVisible();
77
+ }));
78
+ (0, fixtures_1.test)("component renders save and cancel buttons by default", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
79
+ yield initTestBed(`<Form/>`);
80
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Cancel" })).toBeVisible();
81
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Save" })).toBeVisible();
82
+ }));
83
+ (0, fixtures_1.test)("component renders custom button labels", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
84
+ yield initTestBed(`
85
+ <Form cancelLabel="Go Back" saveLabel="Submit"/>
86
+ `);
87
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Go Back" })).toBeVisible();
88
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Submit" })).toBeVisible();
89
+ }));
90
+ (0, fixtures_1.test)("component swaps cancel and save button positions", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
91
+ yield initTestBed(`
92
+ <Form swapCancelAndSave="true"/>
93
+ `);
94
+ const buttons = page.getByRole("button");
95
+ yield (0, fixtures_1.expect)(buttons.first()).toHaveText("Save");
96
+ yield (0, fixtures_1.expect)(buttons.last()).toHaveText("Cancel");
97
+ }));
98
+ // =============================================================================
99
+ // DATA PROPERTY TESTS
100
+ // =============================================================================
101
+ fixtures_1.test.describe("data property", () => {
102
+ (0, fixtures_1.test)("sets initial form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
103
+ yield initTestBed(`
104
+ <Form data="{{ name: 'John', age: 30 }}">
105
+ <FormItem label="Name" bindTo="name" testId="nameField" />
106
+ <FormItem label="Age" bindTo="age" type="integer" testId="ageField" />
107
+ </Form>
108
+ `);
109
+ const nameDriver = yield createFormItemDriver("nameField");
110
+ const nameInput = yield createTextBoxDriver(nameDriver.input);
111
+ const ageDriver = yield createFormItemDriver("ageField");
112
+ const ageInput = yield createTextBoxDriver(ageDriver.input);
113
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("John");
114
+ yield (0, fixtures_1.expect)(ageInput.field).toHaveValue("30");
115
+ }));
116
+ (0, fixtures_1.test)("handles null data gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
117
+ yield initTestBed(`<Form data="{null}" testId="form"/>`);
118
+ const driver = yield createFormDriver("form");
119
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
120
+ }));
121
+ (0, fixtures_1.test)("handles undefined data gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
122
+ yield initTestBed(`<Form data="{undefined}" testId="form"/>`);
123
+ const driver = yield createFormDriver("form");
124
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
125
+ }));
126
+ (0, fixtures_1.test)("handles empty object data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
127
+ yield initTestBed(`<Form data="{{}}" testId="form"/>`);
128
+ const driver = yield createFormDriver("form");
129
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
130
+ }));
131
+ });
132
+ // =============================================================================
133
+ // ITEM LABEL POSITION TESTS
134
+ // =============================================================================
135
+ fixtures_1.test.describe("itemLabelPosition property", () => {
136
+ abstractions_1.labelPositionValues.forEach((position) => {
137
+ (0, fixtures_1.test)(`sets item label position to ${position}`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, }) {
138
+ yield initTestBed(`
139
+ <Form itemLabelPosition="${position}">
140
+ <FormItem label="Test Label" bindTo="test" testId="testField" />
141
+ </Form>
142
+ `);
143
+ const driver = yield createFormItemDriver("testField");
144
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
145
+ }));
146
+ });
147
+ (0, fixtures_1.test)("handles invalid itemLabelPosition gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
148
+ yield initTestBed(`<Form itemLabelPosition="invalid" testId="form"/>`);
149
+ const driver = yield createFormDriver("form");
150
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
151
+ }));
152
+ });
153
+ // =============================================================================
154
+ // ITEM LABEL WIDTH TESTS
155
+ // =============================================================================
156
+ fixtures_1.test.describe("itemLabelWidth property", () => {
157
+ (0, fixtures_1.test)("sets custom label width", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver }) {
158
+ yield initTestBed(`
159
+ <Form itemLabelWidth="200px">
160
+ <FormItem label="Test Label" bindTo="test" testId="testField" />
161
+ </Form>
162
+ `);
163
+ const driver = yield createFormItemDriver("testField");
164
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
165
+ }));
166
+ (0, fixtures_1.test)("handles numeric label width", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver }) {
167
+ yield initTestBed(`
168
+ <Form itemLabelWidth="150">
169
+ <FormItem label="Test Label" bindTo="test" testId="testField" />
170
+ </Form>
171
+ `);
172
+ const driver = yield createFormItemDriver("testField");
173
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
174
+ }));
175
+ (0, fixtures_1.test)("handles invalid label width gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
176
+ yield initTestBed(`<Form itemLabelWidth="invalid" testId="form"/>`);
177
+ const driver = yield createFormDriver("form");
178
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
179
+ }));
180
+ });
181
+ // =============================================================================
182
+ // ITEM LABEL BREAK TESTS
183
+ // =============================================================================
184
+ fixtures_1.test.describe("itemLabelBreak property", () => {
185
+ (0, fixtures_1.test)("enables label line breaking", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver }) {
186
+ yield initTestBed(`
187
+ <Form itemLabelBreak="true">
188
+ <FormItem label="Very Long Label That Should Break" bindTo="test" testId="testField" />
189
+ </Form>
190
+ `);
191
+ const driver = yield createFormItemDriver("testField");
192
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
193
+ }));
194
+ (0, fixtures_1.test)("disables label line breaking", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver }) {
195
+ yield initTestBed(`
196
+ <Form itemLabelBreak="false">
197
+ <FormItem label="Very Long Label That Should Not Break" bindTo="test" testId="testField" />
198
+ </Form>
199
+ `);
200
+ const driver = yield createFormItemDriver("testField");
201
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
202
+ }));
203
+ });
204
+ // =============================================================================
205
+ // ENABLED PROPERTY TESTS
206
+ // =============================================================================
207
+ fixtures_1.test.describe("enabled property", () => {
208
+ (0, fixtures_1.test)("disables save button when enabled is false", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
209
+ yield initTestBed(`
210
+ <Form enabled="false">
211
+ <FormItem label="Test" bindTo="test" />
212
+ </Form>
213
+ `);
214
+ const saveButton = page.getByRole("button", { name: "Save" });
215
+ yield (0, fixtures_1.expect)(saveButton).toBeDisabled();
216
+ }));
217
+ (0, fixtures_1.test)("enables form when enabled is true", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
218
+ yield initTestBed(`
219
+ <Form enabled="true">
220
+ <FormItem label="Test" bindTo="test" />
221
+ </Form>
222
+ `);
223
+ const saveButton = page.getByRole("button", { name: "Save" });
224
+ const cancelButton = page.getByRole("button", { name: "Cancel" });
225
+ yield (0, fixtures_1.expect)(saveButton).toBeEnabled();
226
+ yield (0, fixtures_1.expect)(cancelButton).toBeEnabled();
227
+ }));
228
+ });
229
+ // =============================================================================
230
+ // BUTTON ROW TEMPLATE TESTS
231
+ // =============================================================================
232
+ fixtures_1.test.describe("buttonRowTemplate property", () => {
233
+ (0, fixtures_1.test)("supports custom button row template", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
234
+ yield initTestBed(`
235
+ <Form>
236
+ <FormItem label="Test" bindTo="test" />
237
+ <property name="buttonRowTemplate">
238
+ <Button label="Custom Save" type="submit" />
239
+ <Button label="Custom Cancel" type="button" />
240
+ </property>
241
+ </Form>
242
+ `);
243
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Custom Save" })).toBeVisible();
244
+ yield (0, fixtures_1.expect)(page.getByRole("button", { name: "Custom Cancel" })).toBeVisible();
245
+ }));
246
+ });
247
+ // =============================================================================
248
+ // EVENT TESTS
249
+ // =============================================================================
250
+ fixtures_1.test.describe("Events", () => {
251
+ (0, fixtures_1.test)("onSubmit event fires with form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
252
+ const { testStateDriver } = yield initTestBed(`
253
+ <Form data="{{ name: 'John', email: 'john@example.com' }}" onSubmit="data => testState = data">
254
+ <FormItem label="Name" bindTo="name" />
255
+ <FormItem label="Email" bindTo="email" />
256
+ </Form>
257
+ `);
258
+ yield page.getByRole("button", { name: "Save" }).click();
259
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual({
260
+ name: "John",
261
+ email: "john@example.com",
262
+ });
263
+ }));
264
+ (0, fixtures_1.test)("onCancel event fires when cancel button clicked", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
265
+ const { testStateDriver } = yield initTestBed(`
266
+ <Form onCancel="testState = 'cancelled'">
267
+ <FormItem label="Test" bindTo="test" />
268
+ </Form>
269
+ `);
270
+ yield page.getByRole("button", { name: "Cancel" }).click();
271
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual("cancelled");
272
+ }));
273
+ (0, fixtures_1.test)("onSuccess event fires on successful submission", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormDriver, }) {
274
+ const { testStateDriver } = yield initTestBed(`
275
+ <Form
276
+ testId="form"
277
+ submitUrl="/test-success"
278
+ onSuccess="testState = 'success'; console.log('Submitted successfully')"
279
+ data="{{ name: 'Test' }}">
280
+ <FormItem label="Name" bindTo="name" />
281
+ </Form>
282
+ `, {
283
+ apiInterceptor: {
284
+ operations: {
285
+ testSuccess: {
286
+ url: "/test-success",
287
+ method: "put",
288
+ handler: `return { success: true };`,
289
+ },
290
+ },
291
+ },
292
+ });
293
+ const driver = yield createFormDriver("form");
294
+ yield driver.submitForm();
295
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual("success");
296
+ }));
297
+ (0, fixtures_1.test)("onReset event fires when form is reset", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
298
+ const { testStateDriver } = yield initTestBed(`
299
+ <Form
300
+ id="testForm"
301
+ onReset="testState = 'reset'"
302
+ data="{{ name: 'Test' }}">
303
+ <FormItem label="Name" bindTo="name" />
304
+ <Button onClick="testForm.reset()" label="Reset Form" />
305
+ </Form>
306
+ `);
307
+ yield page.getByRole("button", { name: "Reset Form" }).click();
308
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual("reset");
309
+ }));
310
+ });
311
+ // =============================================================================
312
+ // API TESTS
313
+ // =============================================================================
314
+ fixtures_1.test.describe("APIs", () => {
315
+ (0, fixtures_1.test)("update method updates form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormItemDriver, createTextBoxDriver, }) {
316
+ yield initTestBed(`
317
+ <Form
318
+ id="testForm"
319
+ data="{{ name: 'Original', age: 25 }}">
320
+ <FormItem label="Name" bindTo="name" testId="nameField" />
321
+ <FormItem label="Age" bindTo="age" type="integer" testId="ageField" />
322
+ <Button onClick="testForm.update({ name: 'Updated', age: 30 })" label="Update" />
323
+ </Form>
324
+ `);
325
+ const nameDriver = yield createFormItemDriver("nameField");
326
+ const nameInput = yield createTextBoxDriver(nameDriver.input);
327
+ const ageDriver = yield createFormItemDriver("ageField");
328
+ const ageInput = yield createTextBoxDriver(ageDriver.input);
329
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("Original");
330
+ yield (0, fixtures_1.expect)(ageInput.field).toHaveValue("25");
331
+ yield page.getByRole("button", { name: "Update" }).click();
332
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("Updated");
333
+ yield (0, fixtures_1.expect)(ageInput.field).toHaveValue("30");
334
+ }));
335
+ (0, fixtures_1.test)("reset method resets form to initial state", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormItemDriver, createTextBoxDriver, }) {
336
+ yield initTestBed(`
337
+ <Form
338
+ id="testForm"
339
+ data="{{ name: 'Initial' }}">
340
+ <FormItem label="Name" bindTo="name" testId="nameField" />
341
+ <Button onClick="testForm.reset()" label="Reset" />
342
+ </Form>
343
+ `);
344
+ const nameDriver = yield createFormItemDriver("nameField");
345
+ const nameInput = yield createTextBoxDriver(nameDriver.input);
346
+ // Change the input value
347
+ yield nameInput.field.fill("Changed");
348
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("Changed");
349
+ // Reset the form
350
+ yield page.getByRole("button", { name: "Reset" }).click();
351
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("Initial");
352
+ }));
353
+ });
354
+ // =============================================================================
355
+ // CONTEXT VARIABLE TESTS
356
+ // =============================================================================
357
+ fixtures_1.test.describe("Context Variables", () => {
358
+ (0, fixtures_1.test)("$data context variable provides access to form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormItemDriver, }) {
359
+ // This test needs specific FormItem behavior that may vary
360
+ yield initTestBed(`
361
+ <Form data="{{ isEnabled: true, name: 'Joe' }}">
362
+ <FormItem testId="isEnabled" label="Enable name" bindTo="isEnabled" type="checkbox" />
363
+ <FormItem testId="name" enabled="{$data.isEnabled}" label="Name" bindTo="name" />
364
+ </Form>
365
+ `);
366
+ const enableSwitch = (yield createFormItemDriver("isEnabled")).checkbox;
367
+ const nameInput = (yield createFormItemDriver("name")).textBox;
368
+ yield (0, fixtures_1.expect)(enableSwitch).toBeVisible();
369
+ yield (0, fixtures_1.expect)(nameInput).toBeEnabled();
370
+ yield enableSwitch.click();
371
+ yield (0, fixtures_1.expect)(nameInput).toBeDisabled();
372
+ }));
373
+ (0, fixtures_1.test)("$data.update method updates form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormItemDriver, }) {
374
+ yield initTestBed(`
375
+ <Form data="{{ counter: 0 }}">
376
+ <FormItem testId="counter" label="Counter" bindTo="counter" type="integer" />
377
+ <Button onClick="$data.update({ counter: $data.counter + 1 })" label="Increment" />
378
+ </Form>
379
+ `);
380
+ const counterDriver = yield createFormItemDriver("counter");
381
+ const counterInput = counterDriver.textBox;
382
+ yield (0, fixtures_1.expect)(counterInput).toHaveValue("0");
383
+ yield page.getByRole("button", { name: "Increment" }).click({ force: true });
384
+ yield (0, fixtures_1.expect)(counterInput).toHaveValue("1");
385
+ }));
386
+ });
387
+ // =============================================================================
388
+ // SUBMIT URL AND METHOD TESTS
389
+ // =============================================================================
390
+ fixtures_1.test.describe("Submit URL and Method", () => {
391
+ (0, fixtures_1.test)("submits to custom URL with POST method (new date)", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
392
+ yield initTestBed(`<App><Form testId="form" submitUrl="/custom-endpoint" data="{null}">
393
+ <FormItem label="Name" bindTo="name" />
394
+ </Form></App>`, {
395
+ apiInterceptor: {
396
+ operations: {
397
+ customEndpoint: {
398
+ url: "/custom-endpoint",
399
+ method: "post",
400
+ handler: `return { success: true };`,
401
+ },
402
+ },
403
+ },
404
+ });
405
+ const driver = yield createFormDriver("form");
406
+ yield driver.submitForm();
407
+ const response = yield driver.getSubmitResponse("/custom-endpoint");
408
+ (0, fixtures_1.expect)(response.ok()).toEqual(true);
409
+ }));
410
+ (0, fixtures_1.test)("uses PUT method for existing data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
411
+ yield initTestBed(`<Form submitUrl="/entities/1" data="{{ id: 1, name: 'Existing' }}">
412
+ <FormItem label="Name" bindTo="name" />
413
+ </Form>`, {
414
+ apiInterceptor: {
415
+ operations: {
416
+ updateEntity: {
417
+ url: "/entities/1",
418
+ method: "put",
419
+ handler: `return { success: true };`,
420
+ },
421
+ },
422
+ },
423
+ });
424
+ const driver = yield createFormDriver();
425
+ yield driver.submitForm();
426
+ const response = yield driver.getSubmitResponse("/entities/1");
427
+ (0, fixtures_1.expect)(response.ok()).toEqual(true);
428
+ }));
429
+ (0, fixtures_1.test)("uses custom submit method", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
430
+ yield initTestBed(`<Form submitUrl="/custom" submitMethod="put" data="{{ name: 'Test' }}">
431
+ <FormItem label="Name" bindTo="name" />
432
+ </Form>`, {
433
+ apiInterceptor: {
434
+ operations: {
435
+ putCustom: {
436
+ url: "/custom",
437
+ method: "put",
438
+ handler: `return { success: true };`,
439
+ },
440
+ },
441
+ },
442
+ });
443
+ const driver = yield createFormDriver();
444
+ yield driver.submitForm();
445
+ const response = yield driver.getSubmitResponse("/custom");
446
+ (0, fixtures_1.expect)(response.ok()).toEqual(true);
447
+ }));
448
+ });
449
+ });
450
+ // =============================================================================
451
+ // ACCESSIBILITY TESTS
452
+ // =============================================================================
453
+ fixtures_1.test.describe("Accessibility", () => {
454
+ (0, fixtures_1.test)("form has correct semantic role", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
455
+ yield initTestBed(`<Form/>`);
456
+ yield (0, fixtures_1.expect)(page.locator("form")).toBeVisible();
457
+ }));
458
+ (0, fixtures_1.test)("form items are properly associated with labels", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, }) {
459
+ yield initTestBed(`
460
+ <Form>
461
+ <FormItem label="Full Name" bindTo="name" testId="nameField" />
462
+ </Form>
463
+ `);
464
+ const driver = yield createFormItemDriver("nameField");
465
+ yield (0, fixtures_1.expect)(driver.label).toBeVisible();
466
+ yield (0, fixtures_1.expect)(driver.label).toHaveText("Full Name");
467
+ }));
468
+ (0, fixtures_1.test)("form submission is keyboard accessible", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
469
+ const { testStateDriver } = yield initTestBed(`
470
+ <Form onSubmit="testState = 'submitted via keyboard'">
471
+ <FormItem label="Name" bindTo="name" />
472
+ </Form>
473
+ `);
474
+ const submitButton = page.getByRole("button", { name: "Save" });
475
+ yield submitButton.focus();
476
+ yield page.keyboard.press("Enter");
477
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual("submitted via keyboard");
478
+ }));
479
+ (0, fixtures_1.test)("form cancel is keyboard accessible", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
480
+ const { testStateDriver } = yield initTestBed(`
481
+ <Form onCancel="testState = 'cancelled via keyboard'">
482
+ <FormItem label="Name" bindTo="name" />
483
+ </Form>
484
+ `);
485
+ const cancelButton = page.getByRole("button", { name: "Cancel" });
486
+ yield cancelButton.focus();
487
+ yield page.keyboard.press("Enter");
488
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual("cancelled via keyboard");
489
+ }));
490
+ (0, fixtures_1.test)("disabled form buttons are properly disabled", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
491
+ yield initTestBed(`
492
+ <Form enabled="false">
493
+ <FormItem label="Name" bindTo="name" />
494
+ </Form>
495
+ `);
496
+ const saveButton = page.getByRole("button", { name: "Save" });
497
+ yield (0, fixtures_1.expect)(saveButton).toBeDisabled();
498
+ }));
499
+ });
500
+ // =============================================================================
501
+ // THEME VARIABLE TESTS
502
+ // =============================================================================
503
+ fixtures_1.test.describe("Theme Variables", () => {
504
+ (0, fixtures_1.test)("applies custom gap theme variable", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
505
+ yield initTestBed(`<Form testId="form"/>`, {
506
+ testThemeVars: {
507
+ "gap-Form": "2rem",
508
+ },
509
+ });
510
+ const driver = yield createFormDriver("form");
511
+ yield (0, fixtures_1.expect)(driver.component).toHaveCSS("gap", "32px");
512
+ }));
513
+ (0, fixtures_1.test)("applies custom button row gap theme variable", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
514
+ yield initTestBed(`<Form testId="form"/>`, {
515
+ testThemeVars: {
516
+ "gap-buttonRow-Form": "1rem",
517
+ },
518
+ });
519
+ const driver = yield createFormDriver("form");
520
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
521
+ }));
522
+ (0, fixtures_1.test)("applies validation display theme variables", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
523
+ // This test requires validation system to trigger error display
524
+ yield initTestBed(`
525
+ <Form>
526
+ <FormItem testId="email" label="Email" bindTo="email" type="email" required="true" />
527
+ </Form>
528
+ `, {
529
+ testThemeVars: {
530
+ "backgroundColor-ValidationDisplay-error": "rgb(255, 0, 0)",
531
+ "textColor-ValidationDisplay-error": "rgb(255, 255, 255)",
532
+ },
533
+ });
534
+ // Trigger validation by submitting with empty required field
535
+ yield page.getByRole("button", { name: "Save" }).click();
536
+ const emailComp = page.getByTestId("email");
537
+ yield (0, fixtures_1.expect)(emailComp).toContainText("This field is required");
538
+ }));
539
+ });
540
+ // =============================================================================
541
+ // EDGE CASES TESTS
542
+ // =============================================================================
543
+ fixtures_1.test.describe("Edge Cases", () => {
544
+ (0, fixtures_1.test)("handles form without any form items", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
545
+ yield initTestBed(`<Form testId="form"/>`);
546
+ const driver = yield createFormDriver("form");
547
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
548
+ }));
549
+ (0, fixtures_1.test)("handles malformed data input gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
550
+ yield initTestBed(`<Form data="{invalidJson}" testId="form"/>`);
551
+ const driver = yield createFormDriver("form");
552
+ yield (0, fixtures_1.expect)(driver.component).toBeVisible();
553
+ }));
554
+ (0, fixtures_1.test)("Form does not render if data receives malformed input", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
555
+ yield initTestBed(`<Form data="{}" />`);
556
+ yield (0, fixtures_1.expect)((yield createFormDriver()).component).not.toBeAttached();
557
+ }));
558
+ (0, fixtures_1.test)("handles deeply nested data structure", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
559
+ yield initTestBed(`
560
+ <Form data="{{ user: { profile: { name: 'John' } } }}">
561
+ <FormItem label="Name" bindTo="user.profile.name" testId="nameField" />
562
+ </Form>
563
+ `);
564
+ const driver = yield createFormItemDriver("nameField");
565
+ const input = yield createTextBoxDriver(driver.input);
566
+ yield (0, fixtures_1.expect)(input.field).toHaveValue("John");
567
+ }));
568
+ (0, fixtures_1.test)("handles form with validation errors", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
569
+ yield initTestBed(`
570
+ <Form>
571
+ <FormItem label="Email" bindTo="email" type="email" required="true" />
572
+ </Form>
573
+ `);
574
+ // Try to submit form without filling required field
575
+ yield page.getByRole("button", { name: "Save" }).click();
576
+ // Validation should prevent submission and show error
577
+ const form = page.locator("form");
578
+ yield (0, fixtures_1.expect)(form).toBeVisible();
579
+ }));
580
+ (0, fixtures_1.test)("handles rapid form submissions", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
581
+ const { testStateDriver } = yield initTestBed(`
582
+ <Form onSubmit="testState = (testState || 0) + 1">
583
+ <FormItem label="Name" bindTo="name" />
584
+ </Form>
585
+ `);
586
+ const submitButton = page.getByRole("button", { name: "Save" });
587
+ // Click submit button multiple times rapidly
588
+ yield submitButton.click();
589
+ yield submitButton.click();
590
+ yield submitButton.click();
591
+ // Should only submit once or handle gracefully
592
+ yield fixtures_1.expect.poll(testStateDriver.testState).toBeGreaterThanOrEqual(1);
593
+ }));
594
+ (0, fixtures_1.test)("handles null and undefined in nested data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
595
+ yield initTestBed(`
596
+ <Form data="{{ user: null, settings: undefined, name: 'Test' }}">
597
+ <FormItem label="Name" bindTo="name" testId="nameField" />
598
+ </Form>
599
+ `);
600
+ const driver = yield createFormItemDriver("nameField");
601
+ const input = yield createTextBoxDriver(driver.input);
602
+ yield (0, fixtures_1.expect)(input.field).toHaveValue("Test");
603
+ }));
604
+ (0, fixtures_1.test)("handles form with empty string properties", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
605
+ yield initTestBed(`
606
+ <Form
607
+ cancelLabel=""
608
+ saveLabel=""
609
+ data="{{ name: '' }}">
610
+ <FormItem label="Name" bindTo="name" />
611
+ </Form>
612
+ `);
613
+ // Form should still be visible
614
+ const form = page.locator("form");
615
+ yield (0, fixtures_1.expect)(form).toBeVisible();
616
+ }));
617
+ (0, fixtures_1.test)("handles special characters in form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
618
+ yield initTestBed(`
619
+ <Form data="{{ name: 'José María', description: 'Test & symbols' }}">
620
+ <FormItem label="Name" bindTo="name" testId="nameField" />
621
+ <FormItem label="Description" bindTo="description" testId="descField" />
622
+ </Form>
623
+ `);
624
+ const nameDriver = yield createFormItemDriver("nameField");
625
+ const nameInput = yield createTextBoxDriver(nameDriver.input);
626
+ const descDriver = yield createFormItemDriver("descField");
627
+ const descInput = yield createTextBoxDriver(descDriver.input);
628
+ yield (0, fixtures_1.expect)(nameInput.field).toHaveValue("José María");
629
+ yield (0, fixtures_1.expect)(descInput.field).toHaveValue("Test & symbols");
630
+ }));
631
+ (0, fixtures_1.test)("user cannot submit with clientside errors present", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
632
+ const { testStateDriver } = yield initTestBed(`
633
+ <Form onSubmit="testState = true">
634
+ <FormItem bindTo="name" required="true" />
635
+ </Form>
636
+ `);
637
+ const driver = yield createFormDriver();
638
+ // The onSubmit event should have been triggered if not for the client error of an empty required field
639
+ yield driver.submitForm("click");
640
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual(null);
641
+ }));
642
+ (0, fixtures_1.test)("can submit with invisible required field", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createFormItemDriver, createTextBoxDriver, page, }) {
643
+ const { testStateDriver } = yield initTestBed(`
644
+ <Form onSubmit="testState = true">
645
+ <FormItem testId="select" bindTo="authenticationType"
646
+ type="select" label="Authentication Type:" initialValue="{0}">
647
+ <Option value="{0}" label="Password" />
648
+ <Option value="{1}" label="Public Key" />
649
+ </FormItem>
650
+ <FormItem label="name1" testId="name1" bindTo="name1"
651
+ required="true" when="{$data.authenticationType == 0}"/>
652
+ <FormItem label="name2" testId="name2" bindTo="name2"
653
+ required="true" when="{$data.authenticationType == 1}"/>
654
+ </Form>
655
+ `);
656
+ const formDriver = yield createFormDriver();
657
+ const selectDriver = yield createFormItemDriver("select");
658
+ const textfieldElement = (yield createFormItemDriver("name2")).input;
659
+ const textfieldDriver = yield createTextBoxDriver(textfieldElement);
660
+ yield selectDriver.component.click();
661
+ yield page.getByLabel("Public Key").click();
662
+ yield textfieldDriver.field.fill("John");
663
+ yield formDriver.submitForm();
664
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual(true);
665
+ }));
666
+ (0, fixtures_1.test)("conditional fields keep the state", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createOptionDriver, createTextBoxDriver, }) {
667
+ yield initTestBed(`
668
+ <Form>
669
+ <FormItem testId="select" bindTo="authenticationType"
670
+ type="radioGroup" label="Authentication Type:" initialValue="{0}">
671
+ <Option value="{0}" label="Password" testId="password"/>
672
+ <Option value="{1}" label="Public Key" testId="publicKey" />
673
+ </FormItem>
674
+ <FormItem label="name1" testId="name1" bindTo="name1"
675
+ required="true" when="{$data.authenticationType == 0}"/>
676
+ <FormItem label="name2" testId="name2" bindTo="name2"
677
+ required="true" when="{$data.authenticationType == 1}"/>
678
+ </Form>
679
+ `);
680
+ const option1Driver = yield createFormItemDriver("password");
681
+ const option2Driver = yield createOptionDriver("publicKey");
682
+ const textfield1Element = (yield createFormItemDriver("name1")).input;
683
+ const textfield1Driver = yield createTextBoxDriver(textfield1Element);
684
+ // Fill in first field
685
+ yield textfield1Driver.field.fill("Test Value");
686
+ yield (0, fixtures_1.expect)(textfield1Driver.field).toHaveValue("Test Value");
687
+ // Switch to second option
688
+ yield option2Driver.component.click();
689
+ // Switch back to first option
690
+ yield option1Driver.component.click();
691
+ // Field should retain its value
692
+ yield (0, fixtures_1.expect)(textfield1Driver.field).toHaveValue("Test Value");
693
+ }));
694
+ });
695
+ // =============================================================================
696
+ // ORIGINAL TEST SUITE (LEGACY TESTS)
697
+ // =============================================================================
698
+ (0, fixtures_1.test)("mock service responds", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
699
+ yield initTestBed(`
700
+ <Form submitUrl="/test" />`, {
701
+ apiInterceptor: {
702
+ operations: {
703
+ test: {
704
+ url: "/test",
705
+ method: "post",
706
+ handler: `return true;`,
707
+ },
708
+ },
709
+ },
710
+ });
711
+ const driver = yield createFormDriver();
712
+ yield driver.submitForm();
713
+ const request = yield driver.getSubmitResponse("/test");
714
+ (0, fixtures_1.expect)(request.ok()).toEqual(true);
715
+ }));
716
+ // --- $data
717
+ (0, fixtures_1.test)("$data is correctly bound to form data", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createButtonDriver }) {
718
+ yield initTestBed(`
719
+ <Form data="{{ field: 'test' }}">
720
+ <FormItem label="testField" bindTo="field">
721
+ <Button testId="custom" label="{$data.field}" />
722
+ </FormItem>
723
+ </Form> `);
724
+ const driver = yield createButtonDriver("custom");
725
+ yield (0, fixtures_1.expect)(driver.component).toHaveExplicitLabel("test");
726
+ }));
727
+ (0, fixtures_1.test)("$data is correctly undefined if data is not set in props", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createButtonDriver, }) {
728
+ yield initTestBed(`
729
+ <Form>
730
+ <FormItem label="testField" bindTo="field">
731
+ <Button testId="custom" label="{$data.field}" />
732
+ </FormItem>
733
+ </Form> `);
734
+ const driver = yield createButtonDriver("custom");
735
+ yield (0, fixtures_1.expect)(driver.component).toHaveExplicitLabel(undefined);
736
+ }));
737
+ (0, fixtures_1.test)("Form buttons and contained FormItems are enabled", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormDriver, }) {
738
+ yield initTestBed(`
739
+ <Form testId="form">
740
+ <FormItem label="Name" bindTo="name" />
741
+ <FormItem label="Email" bindTo="email" />
742
+ </Form>
743
+ `);
744
+ const driver = yield createFormDriver("form");
745
+ yield (0, fixtures_1.expect)(page.getByText("Name")).toBeVisible();
746
+ yield (0, fixtures_1.expect)(page.getByText("Email")).toBeVisible();
747
+ yield (0, fixtures_1.expect)(driver.cancelButton).toBeEnabled();
748
+ yield (0, fixtures_1.expect)(driver.submitButton).toBeEnabled();
749
+ }));
750
+ (0, fixtures_1.test)("submit only triggers when enabled", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
751
+ const { testStateDriver } = yield initTestBed(`
752
+ <Form enabled="false" data="{{ name: 'John' }}" onSubmit="testState = true">
753
+ <FormItem bindTo="name" />
754
+ </Form>`);
755
+ const driver = yield createFormDriver();
756
+ yield (0, fixtures_1.expect)(driver.submitButton).toBeDisabled();
757
+ yield driver.submitForm("keypress");
758
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual(null);
759
+ }));
760
+ (0, fixtures_1.test)("submit with unbound fields", (_a) => __awaiter(void 0, [_a], void 0, function* ({ page, initTestBed, createFormDriver }) {
761
+ yield initTestBed(`
762
+ <Fragment var.output="none">
763
+ <Form testId="form"
764
+ data="{{ firstname: 'James', lastname: 'Clewell' }}"
765
+ onSubmit="args => output = JSON.stringify(args)">
766
+ <FormItem label="Firstname" bindTo="firstname" />
767
+ <FormItem label="Middle name" initialValue="Robert" />
768
+ <FormItem label="Lastname" />
769
+ </Form>
770
+ <Text testId="text">{output}</Text>
771
+ </Fragment>
772
+ `);
773
+ const driver = yield createFormDriver("form");
774
+ yield driver.submitForm();
775
+ yield (0, fixtures_1.expect)(page.getByTestId("text")).toHaveText('{"firstname":"James"}');
776
+ }));
777
+ (0, fixtures_1.test)(`submit with type 'items'`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createButtonDriver, createFormItemDriver, }) {
778
+ const { testStateDriver } = yield initTestBed(`
779
+ <Form onSubmit="data => testState = data" testId="form">
780
+ <FormItem testId="formItem" type="items" bindTo="arrayItems" id="arrayItems">
781
+ <FormItem bindTo="name" testId="text{$itemIndex}"/>
782
+ </FormItem>
783
+ <Button testId="addButton" onClick="arrayItems.addItem()"/>
784
+ </Form>`);
785
+ yield (yield createButtonDriver("addButton")).click();
786
+ yield (yield createFormItemDriver("text0")).textBox.fill("John");
787
+ yield (yield createButtonDriver("addButton")).click();
788
+ yield (yield createFormItemDriver("text1")).textBox.fill("Peter");
789
+ const driver = yield createFormDriver("form");
790
+ yield driver.submitForm();
791
+ yield fixtures_1.expect.poll(testStateDriver.testState).toStrictEqual({
792
+ arrayItems: [{ name: "John" }, { name: "Peter" }],
793
+ });
794
+ }));
795
+ (0, fixtures_1.test)(`submit with type 'items', empty bindTo`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createButtonDriver, createFormItemDriver, }) {
796
+ const { testStateDriver } = yield initTestBed(`
797
+ <Form onSubmit="data => testState = data" testId="form">
798
+ <FormItem testId="formItem" type="items" bindTo="arrayItems" id="arrayItems">
799
+ <FormItem testId="text{$itemIndex}" bindTo=""/>
800
+ </FormItem>
801
+ <Button testId="addButton" onClick="arrayItems.addItem()"/>
802
+ </Form>`);
803
+ yield (yield createButtonDriver("addButton")).click();
804
+ yield (yield createFormItemDriver("text0")).textBox.fill("John");
805
+ yield (yield createButtonDriver("addButton")).click();
806
+ yield (yield createFormItemDriver("text1")).textBox.fill("Peter");
807
+ const driver = yield createFormDriver("form");
808
+ yield driver.submitForm();
809
+ yield fixtures_1.expect.poll(testStateDriver.testState).toStrictEqual({
810
+ arrayItems: ["John", "Peter"],
811
+ });
812
+ }));
813
+ // --- Testing
814
+ // --- --- buttonRowTemplate
815
+ (0, fixtures_1.test)("buttonRowTemplate can render buttons", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createButtonDriver }) {
816
+ yield initTestBed(`
817
+ <Form>
818
+ <property name="buttonRowTemplate">
819
+ <Button testId="submitBtn" type="submit" label="Hello Button" />
820
+ </property>
821
+ </Form>`);
822
+ yield (0, fixtures_1.expect)((yield createButtonDriver("submitBtn")).component).toBeAttached();
823
+ }));
824
+ (0, fixtures_1.test)("buttonRowTemplate replaces built-in buttons", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
825
+ yield initTestBed(`
826
+ <Form testId="form">
827
+ <property name="buttonRowTemplate">
828
+ <Button testId="submitBtn" type="submit" label="Hello Button" />
829
+ </property>
830
+ </Form>`);
831
+ const driver = yield createFormDriver("form");
832
+ (0, fixtures_1.expect)(driver.submitButton).not.toBeVisible();
833
+ (0, fixtures_1.expect)(driver.cancelButton).not.toBeVisible();
834
+ }));
835
+ (0, fixtures_1.test)("setting buttonRowTemplate without buttons still runs submit on Enter", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
836
+ const { testStateDriver } = yield initTestBed(`
837
+ <Form onSubmit="testState = true">
838
+ <property name="buttonRowTemplate">
839
+ <Fragment />
840
+ </property>
841
+ <FormItem bindTo="name" />
842
+ </Form>
843
+ `);
844
+ const driver = yield createFormDriver();
845
+ yield driver.submitForm("keypress");
846
+ yield fixtures_1.expect.poll(testStateDriver.testState).toBe(true);
847
+ }));
848
+ (0, fixtures_1.test)("data accepts an object", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
849
+ yield initTestBed(`
850
+ <Form data="{{ field1: 'test' }}">
851
+ <FormItem testId="inputField" bindTo="field1" />
852
+ </Form>
853
+ `);
854
+ const driver = yield createFormItemDriver("inputField");
855
+ yield (0, fixtures_1.expect)((yield createTextBoxDriver(driver.input)).field).toHaveValue("test");
856
+ }));
857
+ (0, fixtures_1.test)(`data accepts primitive`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
858
+ yield initTestBed(`
859
+ <Form data="test">
860
+ <FormItem bindTo="field1" />
861
+ </Form>
862
+ `);
863
+ const component = (yield createFormDriver()).component;
864
+ yield (0, fixtures_1.expect)(component).toBeAttached();
865
+ }));
866
+ (0, fixtures_1.test)(`data accepts empty array`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
867
+ yield initTestBed(`
868
+ <Form data="{[]}">
869
+ <FormItem bindTo="field1" />
870
+ </Form>
871
+ `);
872
+ const component = (yield createFormDriver()).component;
873
+ yield (0, fixtures_1.expect)(component).toBeAttached();
874
+ }));
875
+ (0, fixtures_1.test)("data accepts relative URL endpoint", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createTextBoxDriver, }) {
876
+ yield initTestBed(`
877
+ <Form data="/test">
878
+ <FormItem testId="inputField" bindTo="name" />
879
+ </Form>`, {
880
+ apiInterceptor: {
881
+ operations: {
882
+ test: {
883
+ url: "/test",
884
+ method: "get",
885
+ handler: `return { name: 'John' };`,
886
+ },
887
+ },
888
+ },
889
+ });
890
+ const driver = yield createFormItemDriver("inputField");
891
+ yield (0, fixtures_1.expect)((yield createTextBoxDriver(driver.input)).field).toHaveValue("John");
892
+ }));
893
+ (0, fixtures_1.test)("cancel button and save button use default label", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
894
+ yield initTestBed(`
895
+ <Form testId="form">
896
+ <FormItem label="Name" bindTo="name" />
897
+ <FormItem label="Email" bindTo="email" />
898
+ </Form>
899
+ `);
900
+ const driver = yield createFormDriver("form");
901
+ yield (0, fixtures_1.expect)(driver.cancelButton).toHaveText("Cancel");
902
+ yield (0, fixtures_1.expect)(driver.submitButton).toHaveText("Save");
903
+ }));
904
+ (0, fixtures_1.test)("cancel button is rendered with cancelLabel", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
905
+ yield initTestBed(`
906
+ <Form testId="form" cancelLabel="Abort">
907
+ <FormItem label="Name" bindTo="name" />
908
+ <FormItem label="Email" bindTo="email" />
909
+ </Form>
910
+ `);
911
+ const driver = yield createFormDriver("form");
912
+ yield (0, fixtures_1.expect)(driver.cancelButton).toHaveText("Abort");
913
+ yield (0, fixtures_1.expect)(driver.submitButton).toHaveText("Save");
914
+ }));
915
+ (0, fixtures_1.test)("save button is rendered with saveLabel", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
916
+ yield initTestBed(`
917
+ <Form testId="form" saveLabel="Submit">
918
+ <FormItem label="Name" bindTo="name" />
919
+ <FormItem label="Email" bindTo="email" />
920
+ </Form>
921
+ `);
922
+ const driver = yield createFormDriver("form");
923
+ yield (0, fixtures_1.expect)(driver.cancelButton).toHaveText("Cancel");
924
+ yield (0, fixtures_1.expect)(driver.submitButton).toHaveText("Submit");
925
+ }));
926
+ // swapCancelAndSave
927
+ (0, fixtures_1.test)("built-in button row order is default if swapCancelAndSave is false", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
928
+ yield initTestBed(`
929
+ <Form testId="form" saveLabel="Submit">
930
+ <FormItem label="Name" bindTo="name" />
931
+ <FormItem label="Email" bindTo="email" />
932
+ </Form>
933
+ `);
934
+ const driver = yield createFormDriver("form");
935
+ const cancelBox = yield driver.cancelButton.boundingBox();
936
+ const submitBox = yield driver.submitButton.boundingBox();
937
+ (0, fixtures_1.expect)(cancelBox.x).toBeLessThan(submitBox.x);
938
+ }));
939
+ (0, fixtures_1.test)("built-in button row order flips if swapCancelAndSave is true", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
940
+ yield initTestBed(`
941
+ <Form testId="form" saveLabel="Submit" swapCancelAndSave="true">
942
+ <FormItem label="Name" bindTo="name" />
943
+ <FormItem label="Email" bindTo="email" />
944
+ </Form>
945
+ `);
946
+ const driver = yield createFormDriver("form");
947
+ const cancelBox = yield driver.cancelButton.boundingBox();
948
+ const submitBox = yield driver.submitButton.boundingBox();
949
+ (0, fixtures_1.expect)(cancelBox.x).toBeGreaterThan(submitBox.x);
950
+ }));
951
+ // --- submitUrl
952
+ (0, fixtures_1.test)("form submits to correct url", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
953
+ const endpoint = "/test";
954
+ yield initTestBed(`
955
+ <Form data="{{ name: 'John' }}" submitUrl="${endpoint}" submitMethod="post">
956
+ <FormItem bindTo="name" />
957
+ </Form>`, {
958
+ apiInterceptor: {
959
+ operations: {
960
+ test: {
961
+ url: endpoint,
962
+ method: "post",
963
+ handler: `{ return true; }`,
964
+ },
965
+ },
966
+ },
967
+ });
968
+ const driver = yield createFormDriver();
969
+ yield driver.submitForm();
970
+ const response = yield driver.getSubmitResponse(endpoint);
971
+ (0, fixtures_1.expect)(response.ok()).toBe(true);
972
+ (0, fixtures_1.expect)(new URL(response.url()).pathname).toBe(endpoint);
973
+ }));
974
+ // --- submitMethod
975
+ // NOTE: GET doesn't work because GET/HEAD cannot have a 'body'
976
+ ["post", "put", "delete"].forEach((method) => {
977
+ (0, fixtures_1.test)(`${method} REST op on submit`, (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
978
+ yield initTestBed(`<Form submitUrl="/test" submitMethod="${method}" />`, {
979
+ apiInterceptor: {
980
+ operations: {
981
+ testPost: {
982
+ url: "/test",
983
+ method: "post",
984
+ handler: `return true;`,
985
+ },
986
+ testPut: {
987
+ url: "/test",
988
+ method: "put",
989
+ handler: `return true;`,
990
+ },
991
+ testDelete: {
992
+ url: "/test",
993
+ method: "delete",
994
+ handler: `return true;`,
995
+ },
996
+ },
997
+ },
998
+ });
999
+ const driver = yield createFormDriver();
1000
+ const request = yield driver.getSubmitRequest("/test", method, "click");
1001
+ (0, fixtures_1.expect)(request.failure()).toBeNull();
1002
+ }));
1003
+ });
1004
+ // --- submitting the Form
1005
+ (0, fixtures_1.test)("submit triggers when clicking save/submit button", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
1006
+ yield initTestBed(`
1007
+ <Form data="{{ name: 'John' }}" submitUrl="/test" submitMethod="post">
1008
+ <FormItem bindTo="name" />
1009
+ </Form>`, {
1010
+ apiInterceptor: {
1011
+ operations: {
1012
+ test: {
1013
+ url: "/test",
1014
+ method: "post",
1015
+ handler: `return true;`,
1016
+ },
1017
+ },
1018
+ },
1019
+ });
1020
+ const driver = yield createFormDriver();
1021
+ const request = yield driver.getSubmitRequest("/test", "POST", "click");
1022
+ (0, fixtures_1.expect)(request.failure()).toBeNull();
1023
+ }));
1024
+ (0, fixtures_1.test)("submit triggers when pressing Enter", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver }) {
1025
+ yield initTestBed(`
1026
+ <Form data="{{ name: 'John' }}" submitUrl="/test" submitMethod="post">
1027
+ <FormItem bindTo="name" />
1028
+ </Form>`, {
1029
+ apiInterceptor: {
1030
+ operations: {
1031
+ test: {
1032
+ url: "/test",
1033
+ method: "post",
1034
+ handler: `return true;`,
1035
+ },
1036
+ },
1037
+ },
1038
+ });
1039
+ const driver = yield createFormDriver();
1040
+ const request = yield driver.getSubmitRequest("/test", "POST", "keypress");
1041
+ (0, fixtures_1.expect)(request.failure()).toBeNull();
1042
+ }));
1043
+ (0, fixtures_1.test)("user cannot submit with clientside errors present", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
1044
+ const { testStateDriver } = yield initTestBed(`
1045
+ <Form onSubmit="testState = true">
1046
+ <FormItem bindTo="name" required="true" />
1047
+ </Form>
1048
+ `);
1049
+ const driver = yield createFormDriver();
1050
+ // The onSubmit event should have been triggered if not for the client error of an empty required field
1051
+ yield driver.submitForm("click");
1052
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual(null);
1053
+ }));
1054
+ // --- backend validation summary
1055
+ (0, fixtures_1.test)("submitting with errors shows validation summary", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
1056
+ yield initTestBed(`<Form submitUrl="/general-validation-error" submitMethod="post" />`, {
1057
+ apiInterceptor: errorDisplayInterceptor,
1058
+ });
1059
+ const driver = yield createFormDriver();
1060
+ yield driver.submitForm();
1061
+ yield (0, fixtures_1.expect)(yield driver.getValidationSummary()).toBeVisible();
1062
+ }));
1063
+ (0, fixtures_1.test)("submitting without errors does not show summary", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, }) {
1064
+ yield initTestBed(`<Form submitUrl="/no-validation-error" submitMethod="post" />`, {
1065
+ apiInterceptor: errorDisplayInterceptor,
1066
+ });
1067
+ const driver = yield createFormDriver();
1068
+ yield driver.submitForm();
1069
+ yield (0, fixtures_1.expect)(yield driver.getValidationSummary()).not.toBeVisible();
1070
+ }));
1071
+ (0, fixtures_1.test)("general error messages are rendered in the summary", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createValidationDisplayDriver, }) {
1072
+ yield initTestBed(`<Form submitUrl="/general-validation-error" submitMethod="post" />`, {
1073
+ apiInterceptor: errorDisplayInterceptor,
1074
+ });
1075
+ const formDriver = yield createFormDriver();
1076
+ yield formDriver.submitForm();
1077
+ // TODO: strip this down -> it's verbose but hard to read
1078
+ const warningDisplay = yield createValidationDisplayDriver(yield formDriver.getValidationDisplaysBySeverity("warning"));
1079
+ const errorDisplay = yield createValidationDisplayDriver(yield formDriver.getValidationDisplaysBySeverity("error"));
1080
+ (0, fixtures_1.expect)(yield warningDisplay.getText()).toContain("Warning for the whole form");
1081
+ (0, fixtures_1.expect)(yield errorDisplay.getText()).toContain("Error for the whole form");
1082
+ }));
1083
+ (0, fixtures_1.test)("field-related errors are rendered at FormItems", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createFormItemDriver, }) {
1084
+ yield initTestBed(`
1085
+ <Form submitUrl="/field-validation-error" submitMethod="post">
1086
+ <FormItem testId="testField" bindTo="test" label="test" />
1087
+ </Form>`, {
1088
+ apiInterceptor: errorDisplayInterceptor,
1089
+ });
1090
+ const formDriver = yield createFormDriver();
1091
+ const fieldDriver = yield createFormItemDriver("testField");
1092
+ yield formDriver.submitForm();
1093
+ yield (0, fixtures_1.expect)(yield fieldDriver.getValidationStatusIndicator()).toHaveAttribute(fieldDriver.validationStatusTag, "warning");
1094
+ }));
1095
+ (0, fixtures_1.test)("field-related errors map to correct FormItems", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createFormItemDriver, }) {
1096
+ yield initTestBed(`
1097
+ <Form submitUrl="/field-validation-error" submitMethod="post">
1098
+ <FormItem testId="testField" bindTo="test" label="test" />
1099
+ <FormItem testId="testField2" bindTo="test2" label="test2" />
1100
+ </Form>`, {
1101
+ apiInterceptor: errorDisplayInterceptor,
1102
+ });
1103
+ const formDriver = yield createFormDriver();
1104
+ const fieldDriver = yield createFormItemDriver("testField");
1105
+ yield formDriver.submitForm();
1106
+ yield (0, fixtures_1.expect)(yield fieldDriver.getValidationStatusIndicator()).toHaveAttribute(fieldDriver.validationStatusTag, "warning");
1107
+ }));
1108
+ (0, fixtures_1.test)("field-related errors disappear if user updates FormItems", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createFormItemDriver }) {
1109
+ yield initTestBed(`
1110
+ <Form testId="form">
1111
+ <FormItem testId="testField" bindTo="test" label="test" required />
1112
+ <FormItem testId="testField2" bindTo="test2" label="test2" />
1113
+ </Form>`);
1114
+ const fieldDriver = yield createFormItemDriver("testField");
1115
+ const fieldDriver2 = yield createFormItemDriver("testField2");
1116
+ yield fieldDriver.component.focus();
1117
+ yield fieldDriver.textBox.fill("a");
1118
+ yield fieldDriver.textBox.fill("", { timeout: 500 }); // trigger 'required' error
1119
+ yield (0, fixtures_1.expect)(yield fieldDriver.getValidationStatusIndicator()).toHaveAttribute(fieldDriver.validationStatusTag, "error");
1120
+ //await fieldDriver.component.focus();
1121
+ yield fieldDriver.textBox.fill("a");
1122
+ yield fieldDriver.textBox.blur();
1123
+ yield fieldDriver2.component.focus();
1124
+ yield page.waitForTimeout(200);
1125
+ yield fieldDriver2.textBox.fill("b");
1126
+ (0, fixtures_1.expect)(yield fieldDriver.getValidationStatusIndicator()).not.toBeVisible();
1127
+ }));
1128
+ const smartCrudInterceptor = {
1129
+ initialize: `
1130
+ $state.items = {
1131
+ [10]: { name: "Smith", id: 10 }
1132
+ };
1133
+ $state.currentId = 10;
1134
+ `,
1135
+ operations: {
1136
+ create: {
1137
+ url: "/entities",
1138
+ method: "post",
1139
+ handler: `() => {
1140
+ $state.currentId++;
1141
+ $state.items[$state.currentId] = $requestBody;
1142
+ $state.items[$state.currentId].id = $state.currentId;
1143
+
1144
+ return $state.items[$state.currentId];
1145
+ }`,
1146
+ },
1147
+ read: {
1148
+ url: "/entities/:id",
1149
+ method: "get",
1150
+ handler: `() => {
1151
+ return $state.items[$pathParams.id];
1152
+ }`,
1153
+ },
1154
+ update: {
1155
+ url: "/entities/:id",
1156
+ method: "put",
1157
+ handler: `() => {
1158
+ $state.items[$pathParams.id] = { ...$state.items[$pathParams.id], ...$requestBody };
1159
+ return $state.items[$pathParams.id];
1160
+ }`,
1161
+ },
1162
+ },
1163
+ };
1164
+ (0, fixtures_1.test)("create form works with submitUrl", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createFormItemDriver, createTextBoxDriver, }) {
1165
+ yield initTestBed(`
1166
+ <Form submitUrl="/entities">
1167
+ <FormItem bindTo="name" testId="nameInput"/>
1168
+ </Form>
1169
+ `, { apiInterceptor: smartCrudInterceptor });
1170
+ const formDriver = yield createFormDriver();
1171
+ const inputElement = (yield createFormItemDriver("nameInput")).input;
1172
+ const fieldDriver = yield createTextBoxDriver(inputElement);
1173
+ yield fieldDriver.field.fill("John");
1174
+ yield formDriver.submitForm("click");
1175
+ const response = yield formDriver.getSubmitResponse();
1176
+ (0, fixtures_1.expect)(yield response.json()).toEqual({
1177
+ name: "John",
1178
+ id: 11,
1179
+ });
1180
+ }));
1181
+ (0, fixtures_1.test)("regression: data url through modal context", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createButtonDriver, createFormDriver, createFormItemDriver, createTextBoxDriver, }) {
1182
+ yield initTestBed(`
1183
+ <Fragment>
1184
+ <Button testId="openModalButton" onClick="modal.open({data: '/entities/10'})"/>
1185
+ <ModalDialog id="modal">
1186
+ <Form testId="modalForm" data="{$param.data}" submitUrl="{$param.submitUrl}">
1187
+ <FormItem bindTo="name" testId="nameInput"/>
1188
+ </Form>
1189
+ </ModalDialog>
1190
+ </Fragment>
1191
+ `, {
1192
+ apiInterceptor: smartCrudInterceptor,
1193
+ });
1194
+ const formDriver = yield createFormDriver("modalForm");
1195
+ const inputElement = (yield createFormItemDriver("nameInput")).input;
1196
+ const inputDriver = yield createTextBoxDriver(inputElement);
1197
+ (yield createButtonDriver("openModalButton")).click();
1198
+ yield (0, fixtures_1.expect)(inputDriver.field).toHaveValue("Smith");
1199
+ yield inputDriver.field.fill("EDITED-Smith");
1200
+ yield formDriver.submitForm("click");
1201
+ const response = yield formDriver.getSubmitResponse();
1202
+ (0, fixtures_1.expect)(yield response.json()).toEqual({
1203
+ name: "EDITED-Smith",
1204
+ id: 10,
1205
+ });
1206
+ }));
1207
+ // --- Conditional Rendering Cases
1208
+ (0, fixtures_1.test)("can submit with invisible required field", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormDriver, createFormItemDriver, createTextBoxDriver, page, }) {
1209
+ const { testStateDriver } = yield initTestBed(`
1210
+ <Form onSubmit="testState = true">
1211
+ <FormItem testId="select" bindTo="authenticationType"
1212
+ type="select" label="Authentication Type:" initialValue="{0}">
1213
+ <Option value="{0}" label="Password" />
1214
+ <Option value="{1}" label="Public Key" />
1215
+ </FormItem>
1216
+ <FormItem label="name1" testId="name1" bindTo="name1"
1217
+ required="true" when="{$data.authenticationType == 0}"/>
1218
+ <FormItem label="name2" testId="name2" bindTo="name2"
1219
+ required="true" when="{$data.authenticationType == 1}"/>
1220
+ </Form>
1221
+ `);
1222
+ const formDriver = yield createFormDriver();
1223
+ const selectDriver = yield createFormItemDriver("select");
1224
+ const textfieldElement = (yield createFormItemDriver("name2")).input;
1225
+ const textfieldDriver = yield createTextBoxDriver(textfieldElement);
1226
+ yield selectDriver.component.click();
1227
+ yield page.getByLabel("Public Key").click();
1228
+ yield textfieldDriver.field.fill("John");
1229
+ yield formDriver.submitForm();
1230
+ yield fixtures_1.expect.poll(testStateDriver.testState).toEqual(true);
1231
+ }));
1232
+ (0, fixtures_1.test)("conditional fields keep the state", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, createFormItemDriver, createOptionDriver, createTextBoxDriver, }) {
1233
+ yield initTestBed(`
1234
+ <Form>
1235
+ <FormItem testId="select" bindTo="authenticationType"
1236
+ type="radioGroup" label="Authentication Type:" initialValue="{0}">
1237
+ <Option value="{0}" label="Password" testId="password"/>
1238
+ <Option value="{1}" label="Public Key" testId="publicKey" />
1239
+ </FormItem>
1240
+ <FormItem label="name1" testId="name1" bindTo="name1"
1241
+ required="true" when="{$data.authenticationType == 0}"/>
1242
+ <FormItem label="name2" testId="name2" bindTo="name2"
1243
+ required="true" when="{$data.authenticationType == 1}"/>
1244
+ </Form>
1245
+ `);
1246
+ const option1Driver = yield createFormItemDriver("password");
1247
+ const option2Driver = yield createOptionDriver("publicKey");
1248
+ const textfield1Element = (yield createFormItemDriver("name1")).input;
1249
+ const textfield1Driver = yield createTextBoxDriver(textfield1Element);
1250
+ const textfield2Element = (yield createFormItemDriver("name2")).input;
1251
+ const textfield2Driver = yield createTextBoxDriver(textfield2Element);
1252
+ yield textfield1Driver.field.fill("name1");
1253
+ yield option2Driver.click();
1254
+ yield textfield2Driver.field.fill("name2");
1255
+ yield option1Driver.click();
1256
+ yield (0, fixtures_1.expect)(textfield1Driver.field).toHaveValue("name1");
1257
+ }));