@epa-wg/custom-element-dist 0.0.21 → 0.0.23

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 (174) hide show
  1. package/.idea/.gitignore +8 -0
  2. package/README.md +4 -4
  3. package/coverage/coverage-final.json +13 -11
  4. package/coverage/index.html +30 -30
  5. package/coverage/src/custom-element/coverage.svg +1 -1
  6. package/coverage/src/custom-element/custom-element.js/coverage.svg +1 -1
  7. package/coverage/src/custom-element/custom-element.js.html +603 -420
  8. package/coverage/src/custom-element/http-request.js.html +10 -10
  9. package/coverage/src/custom-element/index.html +18 -18
  10. package/coverage/src/custom-element/local-storage.js.html +2 -2
  11. package/coverage/src/custom-element/location-element.js.html +1 -1
  12. package/coverage/src/index.html +1 -1
  13. package/coverage/src/mocks/handlers.ts.html +1 -1
  14. package/coverage/src/mocks/index.html +1 -1
  15. package/coverage/src/stories/{css.stories.ts → attributes.test.stories.ts}/coverage.svg +1 -1
  16. package/coverage/src/stories/{attributes.stories.ts.html → attributes.test.stories.ts.html} +113 -83
  17. package/coverage/src/stories/coverage.svg +1 -1
  18. package/coverage/src/stories/css.test.stories.ts/coverage.svg +10 -0
  19. package/coverage/src/stories/{css.stories.ts.html → css.test.stories.ts.html} +122 -65
  20. package/coverage/src/stories/dom-merge.test.stories.ts/coverage.svg +10 -0
  21. package/coverage/src/stories/{dom-merge.stories.ts.html → dom-merge.test.stories.ts.html} +118 -70
  22. package/coverage/src/stories/external-template.test.stories.ts/coverage.svg +10 -0
  23. package/coverage/src/stories/{external-template.stories.ts.html → external-template.test.stories.ts.html} +180 -150
  24. package/coverage/src/stories/form.test.stories.ts/coverage.svg +10 -0
  25. package/coverage/src/stories/form.test.stories.ts.html +655 -0
  26. package/coverage/src/stories/http-request.stories.ts.html +7 -7
  27. package/coverage/src/stories/index.html +118 -88
  28. package/coverage/src/stories/{dom-merge.stories.ts → local-storage.test.stories.ts}/coverage.svg +1 -1
  29. package/coverage/src/stories/{local-storage.stories.ts.html → local-storage.test.stories.ts.html} +475 -439
  30. package/coverage/src/stories/{external-template.stories.ts → location-element.test.stories.ts}/coverage.svg +1 -1
  31. package/coverage/src/stories/{location-element.stories.ts.html → location-element.test.stories.ts.html} +134 -98
  32. package/coverage/src/stories/slice-events.test.stories.ts/coverage.svg +10 -0
  33. package/coverage/src/stories/slice-events.test.stories.ts.html +685 -0
  34. package/coverage/src/stories/slots.test.stories.ts/coverage.svg +10 -0
  35. package/coverage/src/stories/slots.test.stories.ts.html +736 -0
  36. package/coverage/src/stories/{renderPlay.ts.html → testStoryBook.ts.html} +44 -26
  37. package/coverage/src/sum.ts.html +1 -1
  38. package/dist/custom-element-BISbI4SU.js +463 -0
  39. package/dist/custom-element-N-sWiqGK.cjs +53 -0
  40. package/dist/custom-element-bundle.cjs +1 -1
  41. package/dist/custom-element-bundle.js +2 -2
  42. package/dist/mockServiceWorker.js +1 -1
  43. package/package.json +4 -4
  44. package/public/mockServiceWorker.js +1 -1
  45. package/src/custom-element/custom-element.d.ts +4 -0
  46. package/src/custom-element/custom-element.js +103 -42
  47. package/src/custom-element/demo/a.html +38 -41
  48. package/src/custom-element/demo/b.html +13 -0
  49. package/src/custom-element/demo/data-slices.html +32 -0
  50. package/src/custom-element/demo/form.html +240 -0
  51. package/src/custom-element/demo/s.xml +11 -14
  52. package/src/custom-element/demo/s.xslt +22 -38
  53. package/src/custom-element/demo/s1.xslt +60 -0
  54. package/src/custom-element/ide/customData-dce.json +14 -1
  55. package/src/custom-element/ide/web-types-dce.json +6 -1
  56. package/src/custom-element/ide/web-types-xsl.json +1 -1
  57. package/src/custom-element/index.html +1 -0
  58. package/src/custom-element.test.ts +24 -8
  59. package/src/stories/{attributes.stories.ts → attributes.test.stories.ts} +19 -9
  60. package/src/stories/{css.stories.ts → css.test.stories.ts} +28 -9
  61. package/src/stories/{dom-merge.stories.ts → dom-merge.test.stories.ts} +19 -3
  62. package/src/stories/{external-template.stories.ts → external-template.test.stories.ts} +13 -3
  63. package/src/stories/form.test.stories.ts +190 -0
  64. package/src/stories/http-request.stories.ts +6 -6
  65. package/src/stories/http-request.test.ts +0 -9
  66. package/src/stories/{local-storage.stories.ts → local-storage.test.stories.ts} +24 -12
  67. package/src/stories/{location-element.stories.ts → location-element.test.stories.ts} +21 -9
  68. package/src/stories/{slice-events.stories.ts → slice-events.test.stories.ts} +88 -5
  69. package/src/stories/slots.test.stories.ts +217 -0
  70. package/src/stories/testStoryBook.ts +28 -0
  71. package/storybook-static/assets/{Color-RQJUDNI5-C4yZhNbM.js → Color-PRSJMWNM-BD_Ds9NW.js} +1 -1
  72. package/storybook-static/assets/{Configure-C7d36rng.js → Configure-70I_VApa.js} +1 -1
  73. package/storybook-static/assets/DocsRenderer-K4EAMTCU-9dn0-HCP.js +2 -0
  74. package/storybook-static/assets/WithTooltip-KJL26V4Q-C6g5GOU9.js +1 -0
  75. package/storybook-static/assets/{attributes.stories-ZB0RTY1d.js → attributes.test.stories-BEOraI4E.js} +22 -21
  76. package/storybook-static/assets/css.test.stories-D9WaxrEv.js +96 -0
  77. package/storybook-static/assets/custom-element-BV8-hRQS.js +219 -0
  78. package/storybook-static/assets/{dom-merge.stories-CgHZUABU.js → dom-merge.test.stories-BhbNeum_.js} +5 -6
  79. package/storybook-static/assets/{entry-preview-CQqNFx4W.js → entry-preview-DrgzXgwT.js} +1 -1
  80. package/storybook-static/assets/{entry-preview-docs-CWgqLfd3.js → entry-preview-docs-Bxv0qQWs.js} +1 -1
  81. package/storybook-static/assets/{external-template.stories-DtSLMxvg.js → external-template.test.stories-Bpr_wxBo.js} +23 -24
  82. package/storybook-static/assets/form.test.stories-3tURbEdv.js +250 -0
  83. package/storybook-static/assets/{formatter-B5HCVTEV-tKeEfJA9.js → formatter-2WMMO6ZP-6IvBq34u.js} +5 -5
  84. package/storybook-static/assets/http-request.stories-8K_qSs8C.js +300 -0
  85. package/storybook-static/assets/iframe-zdt9kuj6.js +2 -0
  86. package/storybook-static/assets/index-B3oZkK3F.js +1 -0
  87. package/storybook-static/assets/index-C30JwJMK.js +548 -0
  88. package/storybook-static/assets/index-CVRyq5ci.js +27 -0
  89. package/storybook-static/assets/index-DXimoRZY.js +1 -0
  90. package/storybook-static/assets/{index-DnEJ_bKa.js → index-DhXZyjEd.js} +1 -1
  91. package/storybook-static/assets/index-DuIEV_9C.js +13 -0
  92. package/storybook-static/assets/{lit-element-B4_0akdT.js → lit-element-CenEXOuS.js} +2 -2
  93. package/storybook-static/assets/{local-storage.stories-BkO6djDz.js → local-storage.test.stories-CtisAQBB.js} +28 -24
  94. package/storybook-static/assets/{location-element.stories-DCIOUd0D.js → location-element.test.stories-5O_t_m4Y.js} +11 -11
  95. package/storybook-static/assets/preview-4Up_z4Em.js +7 -0
  96. package/storybook-static/assets/preview-BKCN0mOr.js +1 -0
  97. package/storybook-static/assets/{preview-CkgAD_DE.js → preview-D0eCfQft.js} +2 -2
  98. package/storybook-static/assets/preview-DRnyIGXK.js +48 -0
  99. package/storybook-static/assets/preview-FpHGYA1q.js +1 -0
  100. package/storybook-static/assets/{preview-PxUn-cIn.js → preview-TCN6m6T-.js} +1 -1
  101. package/storybook-static/assets/slice-events.test.stories-BSXCLIA5.js +231 -0
  102. package/storybook-static/assets/slots.test.stories-B1vqfHmN.js +214 -0
  103. package/storybook-static/assets/syntaxhighlighter-BP7B2CQK-DpPBKyTO.js +1 -0
  104. package/storybook-static/iframe.html +153 -10
  105. package/storybook-static/index.html +1 -1
  106. package/storybook-static/index.json +1 -1
  107. package/storybook-static/mockServiceWorker.js +1 -1
  108. package/storybook-static/project.json +1 -1
  109. package/storybook-static/sb-addons/chromatic-com-storybook-9/manager-bundle.js +35 -29
  110. package/storybook-static/sb-addons/chromatic-com-storybook-9/manager-bundle.js.LEGAL.txt +1 -1
  111. package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js +1 -1
  112. package/storybook-static/sb-addons/essentials-backgrounds-4/manager-bundle.js +5 -5
  113. package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js +35 -35
  114. package/storybook-static/sb-addons/essentials-measure-7/manager-bundle.js +1 -1
  115. package/storybook-static/sb-addons/essentials-outline-8/manager-bundle.js +1 -1
  116. package/storybook-static/sb-addons/essentials-toolbars-6/manager-bundle.js +1 -1
  117. package/storybook-static/sb-addons/essentials-viewport-5/manager-bundle.js +1 -1
  118. package/storybook-static/sb-addons/interactions-10/manager-bundle.js +18 -16
  119. package/storybook-static/sb-addons/links-1/manager-bundle.js +1 -1
  120. package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +1 -1
  121. package/storybook-static/sb-manager/WithTooltip-KJL26V4Q-5LS5AN27.js +1 -0
  122. package/storybook-static/sb-manager/{chunk-S4VOIVUE.js → chunk-B3YDJJJH.js} +9 -9
  123. package/storybook-static/sb-manager/{chunk-FEE35O7J.js → chunk-BLWCBWKL.js} +3 -3
  124. package/storybook-static/sb-manager/{chunk-XCO5HRLK.js → chunk-GUVK2GTO.js} +3 -3
  125. package/storybook-static/sb-manager/chunk-LFRML3ZV.js +186 -0
  126. package/storybook-static/sb-manager/chunk-MC7RAF2B.js +274 -0
  127. package/storybook-static/sb-manager/{chunk-XP3HGWTR.js → chunk-ZR5JZWHI.js} +1 -1
  128. package/storybook-static/sb-manager/{formatter-B5HCVTEV-7DCBOGO6.js → formatter-2WMMO6ZP-JI7RHVTW.js} +1 -1
  129. package/storybook-static/sb-manager/globals-module-info.js +1 -1
  130. package/storybook-static/sb-manager/globals-runtime.js +1 -1
  131. package/storybook-static/sb-manager/index.js +1 -1
  132. package/storybook-static/sb-manager/runtime.js +1 -1
  133. package/storybook-static/sb-manager/{syntaxhighlighter-JOJW2KGS-VF6EEVPI.js → syntaxhighlighter-BP7B2CQK-WOJYHKQR.js} +1 -1
  134. package/storybook-static/sb-preview/runtime.js +28 -11
  135. package/tsconfig.json +31 -21
  136. package/vite.config.js +5 -5
  137. package/yarn.lock +10242 -0
  138. package/.vscode/settings.json +0 -24
  139. package/coverage/src/stories/local-storage.stories.ts/coverage.svg +0 -10
  140. package/coverage/src/stories/location-element.stories.ts/coverage.svg +0 -10
  141. package/coverage/src/stories/renderPlay.ts/coverage.svg +0 -10
  142. package/coverage/src/stories/slice-events.stories.ts/coverage.svg +0 -10
  143. package/coverage/src/stories/slice-events.stories.ts.html +0 -436
  144. package/dist/custom-element-B4v-KaIh.cjs +0 -53
  145. package/dist/custom-element-_g0GTup2.js +0 -436
  146. package/src/stories/attributes.test.ts +0 -14
  147. package/src/stories/css.test.ts +0 -12
  148. package/src/stories/dom-merge.test.ts +0 -12
  149. package/src/stories/external-template.test.ts +0 -12
  150. package/src/stories/local-storage.test.ts +0 -12
  151. package/src/stories/location-element.test.ts +0 -14
  152. package/src/stories/renderPlay.ts +0 -22
  153. package/src/stories/slice-events.test.ts +0 -12
  154. package/storybook-static/assets/DocsRenderer-K4EAMTCU-BLMupvSb.js +0 -2
  155. package/storybook-static/assets/WithTooltip-Y7J54OF7-BAQSPSFk.js +0 -1
  156. package/storybook-static/assets/css.stories-CLSX-Xxd.js +0 -86
  157. package/storybook-static/assets/custom-element-BLZZ00dz.js +0 -53
  158. package/storybook-static/assets/http-request.stories-CUzlXO89.js +0 -300
  159. package/storybook-static/assets/iframe-gCvlWuoC.js +0 -2
  160. package/storybook-static/assets/index-CBQwM6ST.js +0 -508
  161. package/storybook-static/assets/index-CDavW7r9.js +0 -193
  162. package/storybook-static/assets/index-CQA5dlr6.js +0 -13
  163. package/storybook-static/assets/index-DgaNIR0t.js +0 -1
  164. package/storybook-static/assets/index-Dkj0J1ds.js +0 -1
  165. package/storybook-static/assets/preview-C6t8KBFr.js +0 -1
  166. package/storybook-static/assets/preview-CYD85dwb.js +0 -7
  167. package/storybook-static/assets/preview-D8LadFCz.js +0 -48
  168. package/storybook-static/assets/preview-DNpCpRPf.js +0 -1
  169. package/storybook-static/assets/slice-events.stories-DXKjXI37.js +0 -115
  170. package/storybook-static/assets/syntaxhighlighter-JOJW2KGS-C04pIVD3.js +0 -1
  171. package/storybook-static/sb-manager/WithTooltip-Y7J54OF7-CEHQ77YF.js +0 -1
  172. package/storybook-static/sb-manager/chunk-E3WK6ZOZ.js +0 -234
  173. package/storybook-static/sb-manager/chunk-E6ABNH5R.js +0 -183
  174. /package/coverage/src/stories/{attributes.stories.ts → testStoryBook.ts}/coverage.svg +0 -0
@@ -1,9 +1,16 @@
1
1
  // noinspection DuplicatedCode
2
2
 
3
- import type { StoryObj } from '@storybook/web-components';
3
+ import type { StoryObj } from '@storybook/web-components';
4
4
  import {expect, getByTestId, within, userEvent} from '@storybook/test';
5
5
 
6
6
  import '../custom-element/custom-element.js';
7
+ import {
8
+ ByIdWithinXsltFile, EmbeddingInAnotherFile,
9
+ ExternalHtmlFile, ExternalHtmlFileInline, ExternalSvg, ExternalXsltFile, HtmlWithinHtmlFile, MathMLWithinHtmlFile,
10
+ MissingIdWithinXsltFile,
11
+ NoTag,
12
+ SvgWithinHtmlFile, TemplateInPage
13
+ } from './external-template.test.stories';
7
14
 
8
15
  type TProps = { title: string; body:string};
9
16
 
@@ -55,7 +62,6 @@ export const CharsCountInTextarea:Story =
55
62
  await userEvent.keyboard(titleText);
56
63
  expect(textarea.value).toEqual(titleText);
57
64
  expect(textarea.value.length).toEqual(titleText.length);
58
- debugger;
59
65
  canvas.getByTestId('refocus-id').focus();
60
66
  await sleep(10);
61
67
  expect(canvas.getByTestId('counter-id').textContent).toEqual(''+titleText?.length,'counter of symbols');
@@ -80,7 +86,7 @@ export const WordCountOnType:Story =
80
86
  <code data-testid="words-id"
81
87
  >{
82
88
  string-length(normalize-space(//slice/txt)) -
83
- string-length(translate(normalize-space(//slice/txt), ' ', '')) + 1
89
+ string-length(translate(normalize-space(//slice/txt), ' ', '')) + 1
84
90
  }</code>
85
91
  <!-- The expression first normalizes the string by removing leading and trailing whitespace and
86
92
  collapsing internal whitespace into a single space. It then subtracts the length of the string
@@ -111,3 +117,13 @@ export const WordCountOnType:Story =
111
117
  expect(canvas.getByTestId('words-id').textContent.trim()).toEqual('6', 'counter of words in render');
112
118
  },
113
119
  };
120
+
121
+ /* istanbul ignore else -- @preserve */
122
+ if( 'test' === import.meta.env.MODE &&
123
+ !import.meta.url.includes('skiptest') )
124
+ {
125
+ const mod = await import('./dom-merge.test.stories.ts?skiptest');
126
+ const { testStoryBook } = await import('./testStoryBook')
127
+ const { describe } = await import('vitest')
128
+ describe(meta.title, () => testStoryBook( mod, meta ) );
129
+ }
@@ -4,6 +4,7 @@ import type { StoryObj } from '@storybook/web-components';
4
4
  import {expect, getByTestId, within} from '@storybook/test';
5
5
 
6
6
  import '../custom-element/custom-element.js';
7
+ import {Demo, SrcAttribute} from './location-element.test.stories';
7
8
 
8
9
  type TProps = { title: string; body:string};
9
10
 
@@ -32,10 +33,10 @@ export const TemplateInPage:Story =
32
33
  <template id="template1">
33
34
  <slot>Hello</slot> World!
34
35
  </template>
35
-
36
+
36
37
  <custom-element tag="dce-internal" src="#template1"></custom-element>
37
38
  <!-- no need for loading fallback as the template exists -->
38
-
39
+
39
40
  <dce-internal data-testid="slot-override">👋</dce-internal>
40
41
  <dce-internal data-testid="slot-default"></dce-internal>
41
42
  `}
@@ -194,7 +195,6 @@ export const MathMLWithinHtmlFile:Story =
194
195
  const canvas = within(canvasElement);
195
196
  await canvas.findByText(MathMLWithinHtmlFile.args!.title as string);
196
197
  const ml = await canvas.findByTestId('ml-test');
197
- debugger;
198
198
  expect(ml.firstElementChild.localName).toEqual('mrow');
199
199
  },
200
200
  };
@@ -243,3 +243,13 @@ export const EmbeddingInAnotherFile:Story =
243
243
  expect(canvas.getByTestId('wave').innerHTML).toEqual('🖖');
244
244
  },
245
245
  };
246
+
247
+ /* istanbul ignore else -- @preserve */
248
+ if( 'test' === import.meta.env.MODE &&
249
+ !import.meta.url.includes('skiptest') )
250
+ {
251
+ const mod = await import('./external-template.test.stories.ts?skiptest');
252
+ const { testStoryBook } = await import('./testStoryBook')
253
+ const { describe } = await import('vitest')
254
+ describe(meta.title, () => testStoryBook( mod, meta ) );
255
+ }
@@ -0,0 +1,190 @@
1
+ // noinspection DuplicatedCode
2
+
3
+ import type { StoryObj } from '@storybook/web-components';
4
+ import {expect, within, userEvent} from '@storybook/test';
5
+
6
+ import '../custom-element/custom-element.js';
7
+
8
+ type TProps = { title: string; body:string};
9
+
10
+ type Story = StoryObj<TProps>;
11
+
12
+ function render(args: TProps)
13
+ {
14
+ const {title, body} = args;
15
+ return `
16
+ <fieldset>
17
+ <legend>${ title }</legend>
18
+ ${ body }
19
+ </fieldset>
20
+ `;
21
+ }
22
+ const meta =
23
+ { title: 'form'
24
+ , render
25
+ };
26
+
27
+ export default meta;
28
+
29
+ export const SystemMessage:Story =
30
+ { args : {title: 'custom-validity boolean', body:`
31
+ <p>type and then clear test in input should lead to system validation message shown next to input field.
32
+ Something like <q>Please fill out this field</q>.</p>
33
+ <custom-element>
34
+ <template>
35
+ <form>
36
+ <label> Email
37
+ <input slice="username" slice-event="input" placeholder="non-empty" required data-testid="input-1">
38
+ </label>
39
+ <if test="//username/@validation-message">
40
+ <var data-testid="validation-msg">{//username/@validation-message}</var>
41
+ </if>
42
+ <button>Next</button>
43
+ </form>
44
+ </template>
45
+ </custom-element>
46
+ `}
47
+ , play: async ({canvasElement}) =>
48
+ {
49
+ const titleText = SystemMessage.args!.title as string;
50
+ const canvas = within(canvasElement);
51
+
52
+ await expect( canvas.queryByTestId('validation-msg')).toBeNull();
53
+ const input = await canvas.findByTestId('input-1');
54
+ input.focus();
55
+ await userEvent.keyboard('abc');
56
+
57
+ await userEvent.clear(input);
58
+ await expect( canvas.queryByTestId('validation-msg')).toBeInTheDocument();
59
+ },
60
+ };
61
+
62
+ export const FormData:Story =
63
+ { args : {title: 'form-data populated', body:`
64
+ <p>type and then clear test in input should lead to system validation message shown next to input field.
65
+ Something like <q>Please fill out this field</q>.</p>
66
+ <custom-element>
67
+ <template>
68
+ <form slice="signin-form" >
69
+ <input name="f1" placeholder="non-empty" required data-testid="input-1"/>
70
+ <input name="f2" placeholder="non-empty" required data-testid="input-2"/>
71
+ <input name="f3" placeholder="non-empty" required data-testid="input-3"/>
72
+
73
+ <button data-testid="next-button">Next</button><br/>
74
+ f1: <code data-testid="c1">{ /datadom/slice/signin-form/form-data/f1 }</code><br/>
75
+ f2: <code data-testid="c2">{ //form-data/f2 }</code><br/>
76
+ f3: <code data-testid="c3">{/datadom/slice/signin-form/form-data/f3}</code><br/>
77
+ </form>
78
+ </template>
79
+ </custom-element>
80
+ `}
81
+ , play: async ({canvasElement}) =>
82
+ {
83
+ const canvas = within(canvasElement);
84
+ await userEvent.type(canvas.getByTestId('input-1'), 'ABC');
85
+ await userEvent.click(canvas.getByRole('button'));
86
+ await expect( await canvas.findByText('ABC')).toBeInTheDocument();
87
+ await userEvent.type(canvas.getByTestId('input-2'), 'DCE');
88
+ await userEvent.click(canvas.getByRole('button'));
89
+ await expect( await canvas.findByText('DCE')).toBeInTheDocument();
90
+ await userEvent.type(canvas.getByTestId('input-3'), 'XYZ');
91
+ canvas.getByTestId('input-1').focus();
92
+ await expect( await canvas.findByText('XYZ')).toBeInTheDocument();
93
+ },
94
+ };
95
+ export const SetValidityMessage:Story =
96
+ { args : {title: 'setCustomValidity', body:`
97
+ <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity">setCustomValidity()</a>
98
+ invoked by <code>custom-validity</code> attribute. Type in the input fiels to observe the chars count in
99
+ text, click "next" and observe same message in dropdown.
100
+ </p>
101
+ <custom-element>
102
+ <template>
103
+ <form>
104
+ <input slice="s1" slice-event="input keyup" placeholder="type to see the custom error"
105
+ custom-validity=" concat( 'char count ', string-length(//s1) ) "
106
+ data-testid="input-1"/><br/>
107
+ s1: <code data-testid="c1">{ //s1 }</code><br/>
108
+ @validation-message: <var data-testid="validation-msg">{//s1/@validation-message}</var>
109
+ <button>next</button>
110
+ </form>
111
+ </template>
112
+ </custom-element>
113
+ `}
114
+ , play: async ({canvasElement}) =>
115
+ {
116
+ const canvas = within(canvasElement);
117
+ await userEvent.type(canvas.getByTestId('input-1'), 'ABC');
118
+ await expect( canvas.getByText('ABC')).toBeInTheDocument();
119
+ await expect( canvas.getByText('char count 3')).toBeInTheDocument();
120
+ },
121
+ };
122
+
123
+ export const FormCustomValidityBoolean:Story =
124
+ { args : {title: 'form custom-validity, boolean', body:`
125
+ <p> Form is valid only when input text length longer of 3 characters. </p>
126
+ <custom-element>
127
+ <template>
128
+ <form slice="form-1" custom-validity=" string-length(//form-1//f1) &gt; 3 "
129
+ data-testid="form-1"
130
+ >
131
+ <input name="f1" data-testid="input-1"/><br/>
132
+
133
+ <input type="hidden" name="id" value="form--form-custom-validity-boolean"/>
134
+ <input type="hidden" name="viewMode" value="story"/>
135
+ //form-1//f1: <code data-testid="c1">{ //form-1//f1 }</code><br/>
136
+ <button>next</button>
137
+ </form>
138
+ </template>
139
+ </custom-element>
140
+ `}
141
+ , play: async ({canvasElement}) =>
142
+ {
143
+ const canvas = within(canvasElement);
144
+ await userEvent.type(canvas.getByTestId('input-1'), 'AB');
145
+ await userEvent.click(canvas.getByRole('button'));
146
+
147
+ await expect( canvas.getByText('AB')).toBeInTheDocument(); // i.e. not reloaded by form submit
148
+ },
149
+ };
150
+ export const FormCustomValidityString:Story =
151
+ { args : {title: 'form custom-validity, string', body:`
152
+ <p> Form is valid only when input text is longer of 3 characters, @validation-message propagated in form slot </p>
153
+ <custom-element>
154
+ <template>
155
+ <form slice="form-1"
156
+ custom-validity=" string-length(//form-1//f1) &gt; 3 ?? concat('should be more than 3 characters, now is ',string-length(//form-1//f1) ) "
157
+ data-testid="form-1"
158
+ >
159
+ <input name="f1" data-testid="input-1"/><br/>
160
+
161
+ <input type="hidden" name="id" value="form--form-custom-validity-string"/>
162
+ <input type="hidden" name="viewMode" value="story"/>
163
+ //form-1//f1: <code data-testid="c1">{ //form-1//f1 }</code><br/>
164
+ //form-1/@validation-message: <code data-testid="c1">{ //@validation-message }</code><br/>
165
+ <button>next</button>
166
+ </form>
167
+ </template>
168
+ </custom-element>
169
+ `}
170
+ , play: async ({canvasElement}) =>
171
+ {
172
+ const canvas = within(canvasElement);
173
+ await userEvent.type(canvas.getByTestId('input-1'), 'AB');
174
+ await userEvent.click(canvas.getByRole('button'));
175
+
176
+ await expect( canvas.getByText('AB')).toBeInTheDocument(); // i.e. not reloaded by form submit
177
+ await expect( canvas.getByText('should be more than 3 characters, now is 2')).toBeInTheDocument();
178
+ },
179
+ };
180
+ // custom validity rules on form : boolean and string values
181
+
182
+ /* istanbul ignore else -- @preserve */
183
+ if( 'test' === import.meta.env.MODE &&
184
+ !import.meta.url.includes('skiptest') )
185
+ {
186
+ const mod = await import('./form.test.stories.ts?skiptest');
187
+ const { testStoryBook } = await import('./testStoryBook')
188
+ const { describe } = await import('vitest')
189
+ describe(meta.title, () => testStoryBook( mod, meta ) );
190
+ }
@@ -28,12 +28,12 @@ function Template({title, slice, url}: TProps)
28
28
  slice="${slice}"
29
29
  ></http-request>
30
30
  <input placeholder="URL for fetch" slice="url" value="{ //url ?? '${ url }' }"/>
31
- <button>set</button>
32
- <button slice="url" slice-value="''" slice-event="click">set blank</button>
33
- <button slice="url" slice-value="'/reflect'" slice-event="click">/reflect</button>
34
- <button slice="url" slice-value="'/pokemon'" slice-event="click">/pokemon</button>
35
- <button slice="url" slice-value="'/pokemon?limit=6'" slice-event="click">/pokemon?limit=6</button>
36
- <button slice="url" slice-value="'/pokemon?limit=3'" slice-event="click">/pokemon?limit=3</button>
31
+ <button>set</button>
32
+ <button slice="url" slice-value="''" slice-event="click">set blank</button>
33
+ <button slice="url" slice-value="'/reflect'" slice-event="click">/reflect</button>
34
+ <button slice="url" slice-value="'/pokemon'" slice-event="click">/pokemon</button>
35
+ <button slice="url" slice-value="'/pokemon?limit=6'" slice-event="click">/pokemon?limit=6</button>
36
+ <button slice="url" slice-value="'/pokemon?limit=3'" slice-event="click">/pokemon?limit=3</button>
37
37
 
38
38
  <p>Pokemon Count: {count(/datadom/slice/${slice}//results)}</p>
39
39
  <if test="count(/datadom/slice/${slice}//results) &lt; 0">
@@ -12,15 +12,6 @@ import {handlers} from '../mocks/handlers.ts';
12
12
  export const worker = setupWorker(...handlers);
13
13
  await worker.start();
14
14
 
15
-
16
- // worker.start({serviceWorker: { url: '/public/mockServiceWorker.js' } });
17
- // worker.use(...handlers);
18
-
19
- // beforeAll( () => {worker.start()});//{ onUnhandledRequest: 'error' }));
20
- //
21
- // afterAll(() => worker.stop());
22
-
23
-
24
15
  const {renderPlay} = meta;
25
16
  describe('http-request', () => {
26
17
  for (let story of Object.values(Stories) as StoryObj[] )
@@ -27,13 +27,13 @@ function render(args: TProps)
27
27
 
28
28
  <custom-element>
29
29
  <template><!-- wrapping into template to prevent images loading within DCE declaration -->
30
- <local-storage
31
- key="${ key }"
32
- slice="${ slice }"
33
- ${ live ? `live="${live }"`:''}
34
- ${ value ? `value="${value }"`:''}
30
+ <local-storage
31
+ key="${ key }"
32
+ slice="${ slice }"
33
+ ${ live ? `live="${live }"`:''}
34
+ ${ value ? `value="${value }"`:''}
35
35
  ></local-storage>
36
-
36
+
37
37
  <br/>
38
38
  <var>${key}</var>:<code data-testid="slice-value">{ //slice/${slice} }</code>
39
39
  <br/>
@@ -53,12 +53,12 @@ export default meta;
53
53
  export const Demo:Story =
54
54
  { args : {title: 'live value', live:'live', body:`
55
55
  <input placeholder="value for localStorage" id="textinput"
56
- slice="${defs.slice}"
56
+ slice="${defs.slice}"
57
57
  value="{ //${defs.slice} ?? '${ defs.value }' }"/>
58
58
  <button onclick="localStorage.setItem('${defs.key}',textinput.value )">set</button>
59
59
  <button onclick="localStorage.setItem('${defs.key}','text value' )">text value</button>
60
- <button onclick="localStorage.setItem('${defs.key}','another text')">another text</button>
61
- <button onclick="localStorage.removeItem('${defs.key}' )">set blank</button>
60
+ <button onclick="localStorage.setItem('${defs.key}','another text')">another text</button>
61
+ <button onclick="localStorage.removeItem('${defs.key}' )">set blank</button>
62
62
  `}
63
63
  , play: async ({canvasElement}) =>
64
64
  {
@@ -94,8 +94,8 @@ export const Demo:Story =
94
94
  export const AlwaysOverride:Story =
95
95
  { args : {title: 'AlwaysOverride', live:'', value:'ABC', body:`
96
96
  buttons are changing the localStorage value, but without 'live' attribute slice ^^ from <i>local-storage</i> is not updated<br/>
97
- <button onclick="localStorage.setItem('${defs.key}','text value' )">text value</button>
98
- <button onclick="localStorage.removeItem('${defs.key}' )">set blank</button>
97
+ <button onclick="localStorage.setItem('${defs.key}','text value' )">text value</button>
98
+ <button onclick="localStorage.removeItem('${defs.key}' )">set blank</button>
99
99
  `}
100
100
  , play: async ({canvasElement}) =>
101
101
  {
@@ -168,7 +168,7 @@ export const FromStorageWithDefault:Story =
168
168
 
169
169
  export const TypeAttribute:Story =
170
170
  { args : {title: 'local-storage type attribute variations', body:`
171
-
171
+
172
172
  <local-storage key="textKey" slice="text-key" type="text" live="live"></local-storage>
173
173
  <local-storage key="dateKey" slice="date-key" type="date" live="live"></local-storage>
174
174
  <local-storage key="timeKey" slice="time-key" type="time" live="live"></local-storage>
@@ -218,6 +218,8 @@ export const TypeAttribute:Story =
218
218
  `}
219
219
  , play: async ({canvasElement}) =>
220
220
  {
221
+ window['JsonSample'] = {a:1,b:'B'};
222
+
221
223
  const canvas = within(canvasElement);
222
224
  await canvas.findByText(TypeAttribute.args!.title as string);
223
225
  const byText = txt => canvas.getByText(txt)
@@ -386,3 +388,13 @@ export const TypeAttribute:Story =
386
388
  expectVal('json-key' ,'\na : 1b : B' );
387
389
  },
388
390
  };
391
+
392
+ /* istanbul ignore else -- @preserve */
393
+ if( 'test' === import.meta.env.MODE &&
394
+ !import.meta.url.includes('skiptest') )
395
+ {
396
+ const mod = await import('./local-storage.test.stories.ts?skiptest');
397
+ const { testStoryBook } = await import('./testStoryBook')
398
+ const { describe } = await import('vitest')
399
+ describe(meta.title, () => testStoryBook( mod, meta ) );
400
+ }
@@ -1,10 +1,11 @@
1
1
  // noinspection DuplicatedCode
2
2
 
3
- import type { StoryObj } from '@storybook/web-components';
4
- import {expect, getByTestId, within} from '@storybook/test';
3
+ import type { StoryObj } from '@storybook/web-components';
4
+ import {expect, getByTestId, within} from '@storybook/test';
5
5
 
6
6
  import '../custom-element/custom-element.js';
7
7
  import '../custom-element/location-element.js';
8
+ import {RealtimeEventInSlice, SliceInitChangeEvent} from './slice-events.test.stories';
8
9
 
9
10
  type TProps = { title: string; slice: string; href: string; live:string; body:string};
10
11
  const defs: TProps =
@@ -26,13 +27,13 @@ function render(args: TProps)
26
27
 
27
28
  <custom-element>
28
29
  <template><!-- wrapping into template to prevent images loading within DCE declaration -->
29
- <location-element
30
- slice="${ slice }"
31
- ${ href ? `href="${ href }"`:''}
30
+ <location-element
31
+ slice="${ slice }"
32
+ ${ href ? `href="${ href }"`:''}
32
33
  live="${ live }"
33
34
  ></location-element>
34
-
35
-
35
+
36
+
36
37
  ${ body }
37
38
  <xhtml:table>
38
39
  <xhtml:tbody>
@@ -40,12 +41,12 @@ function render(args: TProps)
40
41
  <xhtml:th><h3> URL properties </h3></xhtml:th>
41
42
  <xhtml:td>{count(//value/@*)}</xhtml:td>
42
43
  </xhtml:tr>
43
- <apply-templates mode="attrs" select="//value/@*"></apply-templates>
44
+ <apply-templates mode="attrs" select="//${ slice }/value/@*"></apply-templates>
44
45
  </xhtml:tbody>
45
46
  </xhtml:table>
46
47
  <xhtml:table>
47
48
  <h3> URL parameters </h3>
48
- <apply-templates mode="attrs" select="//params/*/*"></apply-templates>
49
+ <apply-templates mode="attrs" select="//${ slice }/value/params/*/*"></apply-templates>
49
50
  </xhtml:table>
50
51
  <xsl:template mode="attrs" match="*|@*">
51
52
  <xhtml:tr>
@@ -131,3 +132,14 @@ export const SrcAttribute:Story =
131
132
 
132
133
  },
133
134
  };
135
+
136
+
137
+ /* istanbul ignore else -- @preserve */
138
+ if( 'test' === import.meta.env.MODE &&
139
+ !import.meta.url.includes('skiptest') )
140
+ {
141
+ const mod = await import('./location-element.test.stories.ts?skiptest');
142
+ const { testStoryBook } = await import('./testStoryBook')
143
+ const { describe } = await import('vitest')
144
+ describe(meta.title, () => testStoryBook( mod, meta ) );
145
+ }
@@ -1,7 +1,7 @@
1
1
  // noinspection DuplicatedCode
2
2
 
3
- import type { StoryObj } from '@storybook/web-components';
4
- import { expect, within } from '@storybook/test';
3
+ import type { StoryObj } from '@storybook/web-components';
4
+ import {expect, userEvent, within, spyOn} from '@storybook/test';
5
5
 
6
6
  import '../custom-element/custom-element.js';
7
7
 
@@ -74,7 +74,7 @@ export const RealtimeEventInSlice:Story =
74
74
  <p>move the mouse over TEXTAREA and click to see slice and slice event changed</p>
75
75
  <custom-element>
76
76
  <template>
77
- <textarea slice="s" slice-value="concat('x:', //@pageX)" slice-event="mousemove click"
77
+ <textarea slice="s" slice-value="concat('x:', //@pageX)" slice-event="mousemove click"
78
78
  style="width:16rem;height:16rem;box-shadow: inset {//@offsetX}px {//@offsetY}px gold;"></textarea><br/>
79
79
  //slice/s : <code data-testid="//slice/s" >{ //slice/s }</code> <br/>
80
80
  //slice/s/event/@offsetY : <code data-testid="//slice/s/event/@offsetY" >{ //slice/s/event/@offsetY }</code> <br/>
@@ -108,10 +108,93 @@ export const RealtimeEventInSlice:Story =
108
108
  input.dispatchEvent( ev );
109
109
  };
110
110
 
111
- emitXy(10,20,'click');
111
+ emitXy(20,20,'click');
112
112
  await sleep(10);
113
- expect( sliceText() ).to.equal('x:10', 'click slot value 10');
113
+ expect( sliceText() ).to.equal('x:20', 'click slot value 20');
114
114
  expect( Number(offsetY()) ).to.be.lessThan(0, 'offsetY click');
115
115
  expect( eventType() ).to.equal('click', 'click event type');
116
116
  },
117
117
  };
118
+
119
+ export const DoubleEventInSlice:Story =
120
+ { args : {title: 'slice-event="change submit change submit" ', body:`
121
+ <p> double same event should be treated as one.</p>
122
+ <custom-element>
123
+ <template>
124
+ <form slice-event="submit submit change change" slice="form-1">
125
+ <input slice-event="change change" required slice="field-1" data-testid="f1" name="f1"/>
126
+ <input name="f2" value="populated in form-data"/>
127
+ <button>next</button> <code>slices count {count(/datadom/slice/*)}</code>
128
+ </form>
129
+ </template>
130
+ </custom-element>
131
+ `}
132
+ , play: async ({canvasElement}) =>
133
+ {
134
+ const canvas = within(canvasElement);
135
+ const input = await canvas.findByTestId('f1');
136
+ input.focus();
137
+ await userEvent.type ( input, 'AB');
138
+ canvas.getByRole('button').focus()
139
+ await userEvent.clear( input );
140
+ await userEvent.click( canvas.getByRole('button'));
141
+ expect( await canvas.findByText('slices count 2')).toBeInTheDocument();
142
+ },
143
+ };
144
+ export const MultipleSlices:Story =
145
+ { args : {title: 'slice="/datadom/attributes/emotion | s1" ', body:`
146
+ <p> double same event should be treated as one.</p>
147
+ <custom-element>
148
+ <template>
149
+ <input slice="s1|s2"
150
+ slice-event="input"
151
+ data-testid="f1"
152
+ /><br/>
153
+ Type to update s1 and s2 slices <br/>
154
+ slice <code>s1: {//slice/s1}</code><br/>
155
+ slice <code>s2: {//slice/s2}</code><br/>
156
+ </template>
157
+ </custom-element>
158
+ `}
159
+ , play: async ({canvasElement}) =>
160
+ {
161
+ const canvas = within(canvasElement);
162
+ const input = await canvas.findByTestId('f1');
163
+ input.focus();
164
+ await userEvent.type ( input, 'AB');
165
+ await expect( await canvas.findByText('s1: AB')).toBeInTheDocument();
166
+ await expect( await canvas.findByText('s2: AB')).toBeInTheDocument();
167
+ },
168
+ };
169
+ export const SlicesInAttrAndName:Story =
170
+ { args : {title: 'slice="/datadom/attributes/emotion | s1" ', body:`
171
+ <p> double same event should be treated as one.</p>
172
+ <custom-element>
173
+ <template>
174
+ <attribute name="emotion">😃</attribute>
175
+ <input slice-event="input" slice="/datadom/attributes/emotion | s1" data-testid="f1"/>
176
+ <p>Type to update </p>
177
+ <p>emotion attribute: {emotion}</p>
178
+ <p>slice: {//slice/s1}</p>
179
+ </template>
180
+ </custom-element>
181
+ `}
182
+ , play: async ({canvasElement}) =>
183
+ {
184
+ const canvas = within(canvasElement);
185
+ const input = await canvas.findByTestId('f1');
186
+ input.focus();
187
+ await userEvent.type ( input, 'AB');
188
+ await expect( await canvas.findByText( 'emotion attribute: AB')).toBeInTheDocument();
189
+ },
190
+ };
191
+
192
+ /* istanbul ignore else -- @preserve */
193
+ if( 'test' === import.meta.env.MODE &&
194
+ !import.meta.url.includes('skiptest') )
195
+ {
196
+ const mod = await import('./slice-events.test.stories.ts?skiptest');
197
+ const { testStoryBook } = await import('./testStoryBook')
198
+ const { describe } = await import('vitest')
199
+ describe(meta.title, () => testStoryBook( mod, meta ) );
200
+ }