@api-client/ui 0.0.12 → 0.0.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 (194) hide show
  1. package/demo/elements/authorization/cc.ts +56 -27
  2. package/dist/bindings/base/FileBindings.d.ts +4 -0
  3. package/dist/bindings/base/FileBindings.d.ts.map +1 -1
  4. package/dist/bindings/base/FileBindings.js +21 -1
  5. package/dist/bindings/base/FileBindings.js.map +1 -1
  6. package/dist/bindings/base/StoreBindings.d.ts +1 -17
  7. package/dist/bindings/base/StoreBindings.d.ts.map +1 -1
  8. package/dist/bindings/base/StoreBindings.js +0 -59
  9. package/dist/bindings/base/StoreBindings.js.map +1 -1
  10. package/dist/bindings/web/WebFileBindings.js +1 -1
  11. package/dist/bindings/web/WebFileBindings.js.map +1 -1
  12. package/dist/define/http/certificate-add.d.ts +9 -0
  13. package/dist/define/http/certificate-add.d.ts.map +1 -0
  14. package/dist/define/http/certificate-add.js +10 -0
  15. package/dist/define/http/certificate-add.js.map +1 -0
  16. package/dist/define/http/http-body-editor.d.ts.map +1 -1
  17. package/dist/define/http/http-body-editor.js +1 -1
  18. package/dist/define/http/http-body-editor.js.map +1 -1
  19. package/dist/define/ui/ui-segmented-button-set.d.ts +1 -1
  20. package/dist/define/ui/ui-segmented-button-set.d.ts.map +1 -1
  21. package/dist/define/ui/ui-segmented-button-set.js.map +1 -1
  22. package/dist/elements/authorization/ui/CC.styles.d.ts.map +1 -1
  23. package/dist/elements/authorization/ui/CC.styles.js +4 -9
  24. package/dist/elements/authorization/ui/CC.styles.js.map +1 -1
  25. package/dist/elements/authorization/ui/CcAuthorization.d.ts +14 -29
  26. package/dist/elements/authorization/ui/CcAuthorization.d.ts.map +1 -1
  27. package/dist/elements/authorization/ui/CcAuthorization.js +67 -158
  28. package/dist/elements/authorization/ui/CcAuthorization.js.map +1 -1
  29. package/dist/elements/http/BodyEditor.js +5 -5
  30. package/dist/elements/http/BodyEditor.js.map +1 -1
  31. package/dist/elements/http/BodyEditor.styles.d.ts +1 -1
  32. package/dist/elements/http/BodyEditor.styles.d.ts.map +1 -1
  33. package/dist/elements/http/BodyEditor.styles.js +5 -19
  34. package/dist/elements/http/BodyEditor.styles.js.map +1 -1
  35. package/dist/elements/http/CertificateAdd.element.d.ts +91 -0
  36. package/dist/elements/http/CertificateAdd.element.d.ts.map +1 -0
  37. package/dist/elements/http/CertificateAdd.element.js +389 -0
  38. package/dist/elements/http/CertificateAdd.element.js.map +1 -0
  39. package/dist/elements/http/CertificateAdd.styles.d.ts +3 -0
  40. package/dist/elements/http/CertificateAdd.styles.d.ts.map +1 -0
  41. package/dist/elements/http/CertificateAdd.styles.js +61 -0
  42. package/dist/elements/http/CertificateAdd.styles.js.map +1 -0
  43. package/dist/elements/project/ProjectRunReport.d.ts +2 -1
  44. package/dist/elements/project/ProjectRunReport.d.ts.map +1 -1
  45. package/dist/elements/project/ProjectRunReport.js.map +1 -1
  46. package/dist/elements/store/FilePicker.styles.d.ts.map +1 -1
  47. package/dist/elements/store/FilePicker.styles.js +1 -0
  48. package/dist/elements/store/FilePicker.styles.js.map +1 -1
  49. package/dist/elements/store/FilesLib.d.ts +2 -2
  50. package/dist/elements/store/FilesLib.d.ts.map +1 -1
  51. package/dist/elements/store/FilesLib.js.map +1 -1
  52. package/dist/events/EventTypes.d.ts +6 -7
  53. package/dist/events/EventTypes.d.ts.map +1 -1
  54. package/dist/events/EventTypes.js +7 -7
  55. package/dist/events/EventTypes.js.map +1 -1
  56. package/dist/events/Events.d.ts +6 -1
  57. package/dist/events/Events.d.ts.map +1 -1
  58. package/dist/events/Events.js +2 -0
  59. package/dist/events/Events.js.map +1 -1
  60. package/dist/events/FilesystemEvents.d.ts +8 -0
  61. package/dist/events/FilesystemEvents.d.ts.map +1 -0
  62. package/dist/events/FilesystemEvents.js +59 -0
  63. package/dist/events/FilesystemEvents.js.map +1 -0
  64. package/dist/events/HttpClientEvents.d.ts +0 -2
  65. package/dist/events/HttpClientEvents.d.ts.map +1 -1
  66. package/dist/events/HttpClientEvents.js +0 -2
  67. package/dist/events/HttpClientEvents.js.map +1 -1
  68. package/dist/http-client/idb/Arc18DataUpgrade.d.ts +0 -8
  69. package/dist/http-client/idb/Arc18DataUpgrade.d.ts.map +1 -1
  70. package/dist/http-client/idb/Arc18DataUpgrade.js +11 -206
  71. package/dist/http-client/idb/Arc18DataUpgrade.js.map +1 -1
  72. package/dist/http-client/store/Cursor.js +2 -2
  73. package/dist/http-client/store/Cursor.js.map +1 -1
  74. package/dist/http-client/store/HttpClientIdbDatabase.d.ts.map +1 -1
  75. package/dist/http-client/store/HttpClientIdbDatabase.js +2 -6
  76. package/dist/http-client/store/HttpClientIdbDatabase.js.map +1 -1
  77. package/dist/http-client/store/State.d.ts +1 -3
  78. package/dist/http-client/store/State.d.ts.map +1 -1
  79. package/dist/http-client/store/State.js.map +1 -1
  80. package/dist/http-client/store/StoreBroadcast.d.ts +0 -5
  81. package/dist/http-client/store/StoreBroadcast.d.ts.map +1 -1
  82. package/dist/http-client/store/StoreBroadcast.js +0 -7
  83. package/dist/http-client/store/StoreBroadcast.js.map +1 -1
  84. package/dist/http-client/store/idb/IdbStore.d.ts +1 -10
  85. package/dist/http-client/store/idb/IdbStore.d.ts.map +1 -1
  86. package/dist/http-client/store/idb/IdbStore.js +0 -48
  87. package/dist/http-client/store/idb/IdbStore.js.map +1 -1
  88. package/dist/http-client/store/types.d.ts +2 -56
  89. package/dist/http-client/store/types.d.ts.map +1 -1
  90. package/dist/http-client/store/types.js.map +1 -1
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +2 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/lib/files/FileUtils.d.ts +9 -0
  96. package/dist/lib/files/FileUtils.d.ts.map +1 -0
  97. package/dist/lib/files/FileUtils.js +13 -0
  98. package/dist/lib/files/FileUtils.js.map +1 -0
  99. package/dist/mixins/RouteMixin.d.ts +4 -0
  100. package/dist/mixins/RouteMixin.d.ts.map +1 -1
  101. package/dist/mixins/RouteMixin.js +1 -0
  102. package/dist/mixins/RouteMixin.js.map +1 -1
  103. package/dist/pages/api-client/ApiClient.screen.d.ts +8 -4
  104. package/dist/pages/api-client/ApiClient.screen.d.ts.map +1 -1
  105. package/dist/pages/api-client/ApiClient.screen.js +25 -4
  106. package/dist/pages/api-client/ApiClient.screen.js.map +1 -1
  107. package/dist/pages/api-client/ApiClient.styles.d.ts.map +1 -1
  108. package/dist/pages/api-client/ApiClient.styles.js +0 -12
  109. package/dist/pages/api-client/ApiClient.styles.js.map +1 -1
  110. package/dist/pages/api-client/pages/Files.page.d.ts.map +1 -1
  111. package/dist/pages/api-client/pages/Files.page.js +13 -0
  112. package/dist/pages/api-client/pages/Files.page.js.map +1 -1
  113. package/dist/pages/api-client/pages/Trash.page.d.ts.map +1 -1
  114. package/dist/pages/api-client/pages/Trash.page.js +3 -11
  115. package/dist/pages/api-client/pages/Trash.page.js.map +1 -1
  116. package/dist/ui/button/SegmentedButtonsSet.d.ts +14 -0
  117. package/dist/ui/button/SegmentedButtonsSet.d.ts.map +1 -1
  118. package/dist/ui/button/SegmentedButtonsSet.js.map +1 -1
  119. package/dist/ui/list/UiDropdownList.js +1 -1
  120. package/dist/ui/list/UiDropdownList.js.map +1 -1
  121. package/dist/ui/notification/SnackNotifications.d.ts +1 -0
  122. package/dist/ui/notification/SnackNotifications.d.ts.map +1 -1
  123. package/dist/ui/notification/SnackNotifications.js +7 -0
  124. package/dist/ui/notification/SnackNotifications.js.map +1 -1
  125. package/package.json +2 -2
  126. package/src/bindings/base/FileBindings.ts +25 -1
  127. package/src/bindings/base/StoreBindings.ts +1 -73
  128. package/src/bindings/web/WebFileBindings.ts +1 -1
  129. package/src/define/http/certificate-add.ts +12 -0
  130. package/src/define/http/http-body-editor.ts +1 -1
  131. package/src/define/ui/ui-segmented-button-set.ts +1 -1
  132. package/src/elements/authorization/ui/CC.styles.ts +4 -9
  133. package/src/elements/authorization/ui/CcAuthorization.ts +67 -167
  134. package/src/elements/http/BodyEditor.styles.ts +5 -19
  135. package/src/elements/http/BodyEditor.ts +5 -5
  136. package/src/elements/http/CertificateAdd.element.ts +443 -0
  137. package/src/elements/http/CertificateAdd.styles.ts +61 -0
  138. package/src/elements/project/ProjectRunReport.ts +2 -1
  139. package/src/elements/store/FilePicker.styles.ts +1 -0
  140. package/src/elements/store/FilesLib.ts +2 -2
  141. package/src/events/EventTypes.ts +7 -7
  142. package/src/events/Events.ts +2 -0
  143. package/src/events/FilesystemEvents.ts +63 -0
  144. package/src/events/HttpClientEvents.ts +0 -2
  145. package/src/http-client/idb/Arc18DataUpgrade.ts +84 -84
  146. package/src/http-client/store/Cursor.ts +2 -2
  147. package/src/http-client/store/HttpClientIdbDatabase.ts +5 -9
  148. package/src/http-client/store/State.ts +1 -5
  149. package/src/http-client/store/StoreBroadcast.ts +0 -8
  150. package/src/http-client/store/idb/IdbStore.ts +1 -51
  151. package/src/http-client/store/types.ts +2 -57
  152. package/src/index.ts +3 -0
  153. package/src/lib/files/FileUtils.ts +12 -0
  154. package/src/mixins/RouteMixin.ts +8 -1
  155. package/src/pages/api-client/ApiClient.screen.ts +33 -9
  156. package/src/pages/api-client/ApiClient.styles.ts +0 -12
  157. package/src/pages/api-client/pages/Files.page.ts +11 -0
  158. package/src/pages/api-client/pages/Trash.page.ts +3 -10
  159. package/src/ui/button/SegmentedButtonsSet.ts +16 -1
  160. package/src/ui/list/UiDropdownList.ts +1 -1
  161. package/src/ui/notification/SnackNotifications.ts +8 -0
  162. package/test/elements/http/BodyFormdataEditorElement.test.ts +458 -454
  163. package/test/elements/http/BodyMultipartEditorElement.test.ts +609 -605
  164. package/test/elements/http/BodyRawEditorElement.test.ts +60 -56
  165. package/test/elements/http/CertificateAdd.test.ts +430 -0
  166. package/test/events/EventTypes.test.ts +0 -22
  167. package/test/helpers/UiMock.ts +19 -2
  168. package/web-test-runner.config.mjs +6 -5
  169. package/dist/events/http-client/models/CertificatesEvents.d.ts +0 -12
  170. package/dist/events/http-client/models/CertificatesEvents.d.ts.map +0 -1
  171. package/dist/events/http-client/models/CertificatesEvents.js +0 -18
  172. package/dist/events/http-client/models/CertificatesEvents.js.map +0 -1
  173. package/dist/http-client/idb/AuthDataModel.d.ts +0 -60
  174. package/dist/http-client/idb/AuthDataModel.d.ts.map +0 -1
  175. package/dist/http-client/idb/AuthDataModel.js +0 -150
  176. package/dist/http-client/idb/AuthDataModel.js.map +0 -1
  177. package/dist/http-client/idb/HostsModel.d.ts +0 -25
  178. package/dist/http-client/idb/HostsModel.d.ts.map +0 -1
  179. package/dist/http-client/idb/HostsModel.js +0 -82
  180. package/dist/http-client/idb/HostsModel.js.map +0 -1
  181. package/dist/http-client/idb/LegacyMockedStore.d.ts +0 -214
  182. package/dist/http-client/idb/LegacyMockedStore.d.ts.map +0 -1
  183. package/dist/http-client/idb/LegacyMockedStore.js +0 -486
  184. package/dist/http-client/idb/LegacyMockedStore.js.map +0 -1
  185. package/dist/http-client/store/Validator.d.ts +0 -4
  186. package/dist/http-client/store/Validator.d.ts.map +0 -1
  187. package/dist/http-client/store/Validator.js +0 -32
  188. package/dist/http-client/store/Validator.js.map +0 -1
  189. package/src/events/http-client/models/CertificatesEvents.ts +0 -23
  190. package/src/http-client/idb/AuthDataModel.ts +0 -175
  191. package/src/http-client/idb/HostsModel.ts +0 -125
  192. package/src/http-client/idb/LegacyMockedStore.ts +0 -544
  193. package/src/http-client/store/Validator.ts +0 -33
  194. package/test/apic-ui.test.ts +0 -31
@@ -5,74 +5,78 @@ import '../../../src/define/http/http-body-text-editor.js'
5
5
 
6
6
  /* global monaco */
7
7
 
8
- describe('BodyTextEditor()', () => {
9
- async function basicFixture(): Promise<BodyTextEditor> {
10
- return fixture(`<http-body-text-editor></http-body-text-editor>`);
11
- }
8
+ describe('elements', () => {
9
+ describe('http', () => {
10
+ describe('BodyTextEditor()', () => {
11
+ async function basicFixture(): Promise<BodyTextEditor> {
12
+ return fixture(`<http-body-text-editor></http-body-text-editor>`);
13
+ }
12
14
 
13
- before(async () => loadMonaco());
15
+ before(async () => loadMonaco());
14
16
 
15
- describe('constructor()', () => {
16
- let element: BodyTextEditor;
17
- beforeEach(async () => { element = await basicFixture(); });
17
+ describe('constructor()', () => {
18
+ let element: BodyTextEditor;
19
+ beforeEach(async () => { element = await basicFixture(); });
18
20
 
19
- it('sets the default readOnly', () => {
20
- assert.isFalse(element.readOnly);
21
- });
21
+ it('sets the default readOnly', () => {
22
+ assert.isFalse(element.readOnly);
23
+ });
22
24
 
23
- it('sets the default value', () => {
24
- assert.equal(element.value, '');
25
- });
26
- });
25
+ it('sets the default value', () => {
26
+ assert.equal(element.value, '');
27
+ });
28
+ });
27
29
 
28
- describe('#editor', () => {
29
- let element: BodyTextEditor;
30
- beforeEach(async () => { element = await basicFixture(); });
30
+ describe('#editor', () => {
31
+ let element: BodyTextEditor;
32
+ beforeEach(async () => { element = await basicFixture(); });
31
33
 
32
- it('has the editor instance set', () => {
33
- assert.typeOf(element.editor, 'object');
34
- });
35
- });
34
+ it('has the editor instance set', () => {
35
+ assert.typeOf(element.editor, 'object');
36
+ });
37
+ });
36
38
 
37
- describe('#readOnly', () => {
38
- let element: BodyTextEditor;
39
- beforeEach(async () => { element = await basicFixture(); });
39
+ describe('#readOnly', () => {
40
+ let element: BodyTextEditor;
41
+ beforeEach(async () => { element = await basicFixture(); });
40
42
 
41
- it('sets the editor readOnly', () => {
42
- element.readOnly = true;
43
- // @ts-ignore
44
- const value = element.editor.getOption(monaco.editor.EditorOptions.readOnly.id);
45
- assert.isTrue(value);
46
- });
47
- });
43
+ it('sets the editor readOnly', () => {
44
+ element.readOnly = true;
45
+ // @ts-ignore
46
+ const value = element.editor.getOption(monaco.editor.EditorOptions.readOnly.id);
47
+ assert.isTrue(value);
48
+ });
49
+ });
48
50
 
49
- describe('#contentType', () => {
50
- let element: BodyTextEditor;
51
- beforeEach(async () => { element = await basicFixture(); });
51
+ describe('#contentType', () => {
52
+ let element: BodyTextEditor;
53
+ beforeEach(async () => { element = await basicFixture(); });
52
54
 
53
- it('sets the [languageValue]', () => {
54
- element.contentType = 'application/json';
55
- assert.equal(element.language, 'json');
56
- });
55
+ it('sets the [languageValue]', () => {
56
+ element.contentType = 'application/json';
57
+ assert.equal(element.language, 'json');
58
+ });
57
59
 
58
- it('sets the editor model', () => {
59
- element.contentType = 'application/json';
60
- const model = element.editor!.getModel()!;
61
- assert.equal(model.getLanguageId(), 'json');
62
- });
60
+ it('sets the editor model', () => {
61
+ element.contentType = 'application/json';
62
+ const model = element.editor!.getModel()!;
63
+ assert.equal(model.getLanguageId(), 'json');
64
+ });
63
65
 
64
- [
65
- ['application/json', 'json'],
66
- ['application/x-json', 'json'],
67
- ['application/svg+xml', 'xml'],
68
- ['application/xml', 'xml'],
69
- ['text/html', 'html'],
70
- ['text/css', 'css'],
71
- ].forEach(([mime, lang]) => {
72
- it(`sets the editor language for ${mime}`, () => {
73
- element.contentType = mime;
74
- const model = element.editor!.getModel()!;
75
- assert.equal(model.getLanguageId(), lang);
66
+ [
67
+ ['application/json', 'json'],
68
+ ['application/x-json', 'json'],
69
+ ['application/svg+xml', 'xml'],
70
+ ['application/xml', 'xml'],
71
+ ['text/html', 'html'],
72
+ ['text/css', 'css'],
73
+ ].forEach(([mime, lang]) => {
74
+ it(`sets the editor language for ${mime}`, () => {
75
+ element.contentType = mime;
76
+ const model = element.editor!.getModel()!;
77
+ assert.equal(model.getLanguageId(), lang);
78
+ });
79
+ });
76
80
  });
77
81
  });
78
82
  });
@@ -0,0 +1,430 @@
1
+ import { assert, aTimeout, fixture, html } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ import type CertificateAdd from '../../../src/elements/http/CertificateAdd.element.js';
4
+ import type Input from '../../../src/ui/input/Input.js';
5
+ import { UiMock } from '../../helpers/UiMock.js';
6
+ import { EventTypes } from '../../../src/events/EventTypes.js';
7
+ import type { FileReadOptions, IOpenFileDialogInit, IOpenFileDialogResult } from '../../../src/bindings/base/FileBindings.js';
8
+ import '../../../src/define/http/certificate-add.js'
9
+ import { SnackNotifications } from '../../../src/ui/notification/SnackNotifications.js';
10
+
11
+ describe('elements', () => {
12
+ describe('http', () => {
13
+ describe('CertificateAdd', () => {
14
+ async function basicFixture(): Promise<CertificateAdd> {
15
+ return fixture(html`<certificate-add></certificate-add>`);
16
+ }
17
+
18
+ async function pfxFixture(): Promise<CertificateAdd> {
19
+ return fixture(html`<certificate-add importType="p12"></certificate-add>`);
20
+ }
21
+
22
+ describe('PEM', () => {
23
+ let element: CertificateAdd;
24
+
25
+ beforeEach(async () => {
26
+ element = await basicFixture();
27
+ });
28
+
29
+ it('renders the certificate name input', async () => {
30
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
31
+ assert.ok(input, 'has the input');
32
+ });
33
+
34
+ it('renders the certificate file filed', async () => {
35
+ const input = element.shadowRoot!.querySelector('.cert-file[data-kind="certificate"]')! as HTMLElement;
36
+ assert.ok(input, 'has the input');
37
+ });
38
+
39
+ it('renders the key file filed', async () => {
40
+ const input = element.shadowRoot!.querySelector('.cert-file[data-kind="key"]')! as HTMLElement;
41
+ assert.ok(input, 'has the input');
42
+ });
43
+
44
+ it('renders the key password filed', async () => {
45
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="keyPassword"]') as Input;
46
+ assert.ok(input, 'has the input');
47
+ });
48
+
49
+ it('does not render the certificate password filed', async () => {
50
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="certificatePassword"]');
51
+ assert.notOk(input, 'has no input');
52
+ });
53
+ });
54
+
55
+ describe('PFX/PKCS12', () => {
56
+ let element: CertificateAdd;
57
+
58
+ beforeEach(async () => {
59
+ element = await pfxFixture();
60
+ });
61
+
62
+ it('renders the certificate name input', async () => {
63
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
64
+ assert.ok(input, 'has the input');
65
+ });
66
+
67
+ it('renders the certificate file filed', async () => {
68
+ const input = element.shadowRoot!.querySelector('.cert-file[data-kind="certificate"]')! as HTMLElement;
69
+ assert.ok(input, 'has the input');
70
+ });
71
+
72
+ it('does not render the key file filed', async () => {
73
+ const input = element.shadowRoot!.querySelector('.cert-file[data-kind="key"]');
74
+ assert.notOk(input, 'has no input');
75
+ });
76
+
77
+ it('does not render the key password filed', async () => {
78
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="keyPassword"]');
79
+ assert.notOk(input, 'has no input');
80
+ });
81
+
82
+ it('renders the certificate password input', async () => {
83
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="certificatePassword"]')! as Input;
84
+ assert.ok(input, 'has the input');
85
+ });
86
+ });
87
+
88
+ describe('File drag and drop', () => {
89
+ let element: CertificateAdd;
90
+ let certTarget: HTMLElement;
91
+ let keyTarget: HTMLElement;
92
+
93
+ beforeEach(async () => {
94
+ element = await basicFixture();
95
+ certTarget = element.shadowRoot!.querySelector('.cert-file[data-kind="certificate"]') as HTMLElement;
96
+ keyTarget = element.shadowRoot!.querySelector('.cert-file[data-kind="key"]') as HTMLElement;
97
+ });
98
+
99
+ it('handles the drag enter event on the certificate input', async () => {
100
+ const e = UiMock.getFileDragEvent('dragenter');
101
+ certTarget.dispatchEvent(e);
102
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
103
+ assert.isTrue(certTarget.classList.contains('dragover'), 'adds the dragover class');
104
+ });
105
+
106
+ it('handles the drag enter event on the key input', async () => {
107
+ const e = UiMock.getFileDragEvent('dragenter');
108
+ keyTarget.dispatchEvent(e);
109
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
110
+ assert.isTrue(keyTarget.classList.contains('dragover'), 'adds the dragover class');
111
+ });
112
+
113
+ it('handles the drag leave event on the certificate input', async () => {
114
+ certTarget.classList.add('dragover');
115
+ const e = UiMock.getFileDragEvent('dragleave');
116
+ certTarget.dispatchEvent(e);
117
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
118
+ assert.isFalse(certTarget.classList.contains('dragover'), 'adds the dragover class');
119
+ });
120
+
121
+ it('handles the drag leave event on the key input', async () => {
122
+ keyTarget.classList.add('dragover');
123
+ const e = UiMock.getFileDragEvent('dragleave');
124
+ keyTarget.dispatchEvent(e);
125
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
126
+ assert.isFalse(keyTarget.classList.contains('dragover'), 'adds the dragover class');
127
+ });
128
+
129
+ it('handles the drag over event on the certificate input', async () => {
130
+ const e = UiMock.getFileDragEvent('dragover');
131
+ certTarget.dispatchEvent(e);
132
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
133
+ assert.isTrue(certTarget.classList.contains('dragover'), 'adds the dragover class');
134
+ });
135
+
136
+ it('handles the drag over event on the key input', async () => {
137
+ const e = UiMock.getFileDragEvent('dragover');
138
+ keyTarget.dispatchEvent(e);
139
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
140
+ assert.isTrue(keyTarget.classList.contains('dragover'), 'adds the dragover class');
141
+ });
142
+
143
+ it('handles the drop event on the certificate input', async () => {
144
+ certTarget.classList.add('dragover');
145
+ const spy = sinon.spy(element, 'processDroppedFile');
146
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' });
147
+ const e = UiMock.getFileDragEvent('drop', { file });
148
+ certTarget.dispatchEvent(e);
149
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
150
+ assert.isFalse(certTarget.classList.contains('dragover'), 'adds the dragover class');
151
+ assert.isTrue(spy.called, 'calls the processDroppedFile method');
152
+ assert.equal(spy.args[0][0], file, 'passes the file argument');
153
+ assert.equal(spy.args[0][1], 'certificate', 'passes the kind argument');
154
+ });
155
+
156
+ it('handles the drop event on the key input', async () => {
157
+ keyTarget.classList.add('dragover');
158
+ const spy = sinon.spy(element, 'processDroppedFile');
159
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' });
160
+ const e = UiMock.getFileDragEvent('drop', { file });
161
+ keyTarget.dispatchEvent(e);
162
+ assert.isTrue(e.defaultPrevented, 'the event is prevented');
163
+ assert.isFalse(keyTarget.classList.contains('dragover'), 'adds the dragover class');
164
+ assert.isTrue(spy.called, 'calls the processDroppedFile method');
165
+ assert.equal(spy.args[0][0], file, 'passes the file argument');
166
+ assert.equal(spy.args[0][1], 'key', 'passes the kind argument');
167
+ });
168
+ });
169
+
170
+ describe('Manual file selecting for PEM', () => {
171
+ let element: CertificateAdd;
172
+ let certTarget: HTMLElement;
173
+ let keyTarget: HTMLElement;
174
+
175
+ beforeEach(async () => {
176
+ element = await basicFixture();
177
+ certTarget = element.shadowRoot!.querySelector('.cert-file[data-kind="certificate"] ui-button') as HTMLElement;
178
+ keyTarget = element.shadowRoot!.querySelector('.cert-file[data-kind="key"] ui-button') as HTMLElement;
179
+ });
180
+
181
+ it('dispatches the Filesystem.requestOpenFile for the certificate', async () => {
182
+ let openOptions: IOpenFileDialogInit | undefined;
183
+ let readOptions: FileReadOptions | undefined;
184
+ let eventPath: string | undefined;
185
+
186
+ element.addEventListener(EventTypes.Filesystem.requestOpenFile, (e: Event): void => {
187
+ const event = e as CustomEvent<{ options: IOpenFileDialogInit, result: Promise<IOpenFileDialogResult> }>;
188
+ openOptions = event.detail.options;
189
+ event.detail.result = Promise.resolve({
190
+ canceled: false,
191
+ filePath: ['test/file.pem'],
192
+ });
193
+ });
194
+
195
+ element.addEventListener(EventTypes.Filesystem.readFile, (e: Event): void => {
196
+ const event = e as CustomEvent<{ path: string, options: FileReadOptions, result: Promise<string | ArrayBuffer | Buffer> }>;
197
+ readOptions = event.detail.options;
198
+ eventPath = event.detail.path;
199
+ event.detail.result = Promise.resolve(new ArrayBuffer(100));
200
+ });
201
+
202
+ certTarget.click();
203
+ // Promises are resolved in the save event loop at the end as microtasks so `1` timeout should be enough
204
+ // as this will be executed with the next event loop.
205
+ await aTimeout(1);
206
+
207
+ assert.typeOf(openOptions, 'object', 'has the file open request options');
208
+ assert.isFalse(openOptions!.multiple, 'the (open request) options.multiple is false');
209
+ assert.equal(openOptions!.title, 'Select a certificate file', 'has the (open request) options.title');
210
+ assert.lengthOf(openOptions!.filters!, 1, 'has the (open request) options.filters');
211
+ const [openFilter] = openOptions!.filters!;
212
+ assert.equal(openFilter.description, 'Certificate files', 'open filter has the description');
213
+ assert.deepEqual(openFilter.accept, { 'application/x-pem-file': ['.pem', '.crt', '.cer', '.key'] }, 'filter has the accept');
214
+
215
+ assert.typeOf(readOptions, 'object', 'has the file read request options');
216
+ assert.equal(readOptions!.returnType, 'buffer', 'read file return type is set');
217
+ assert.isTrue(readOptions!.dispose, 'read file dispose is set');
218
+
219
+ assert.equal(eventPath, 'test/file.pem', 'read event has the correct path');
220
+ });
221
+
222
+ it('dispatches the Filesystem.requestOpenFile for the key', async () => {
223
+ let openOptions: IOpenFileDialogInit | undefined;
224
+ let readOptions: FileReadOptions | undefined;
225
+ let eventPath: string | undefined;
226
+
227
+ element.addEventListener(EventTypes.Filesystem.requestOpenFile, (e: Event): void => {
228
+ const event = e as CustomEvent<{ options: IOpenFileDialogInit, result: Promise<IOpenFileDialogResult> }>;
229
+ openOptions = event.detail.options;
230
+ event.detail.result = Promise.resolve({
231
+ canceled: false,
232
+ filePath: ['test/file.pem'],
233
+ });
234
+ });
235
+
236
+ element.addEventListener(EventTypes.Filesystem.readFile, (e: Event): void => {
237
+ const event = e as CustomEvent<{ path: string, options: FileReadOptions, result: Promise<string | ArrayBuffer | Buffer> }>;
238
+ readOptions = event.detail.options;
239
+ eventPath = event.detail.path;
240
+ event.detail.result = Promise.resolve(new ArrayBuffer(100));
241
+ });
242
+
243
+ keyTarget.click();
244
+ // Promises are resolved in the save event loop at the end as microtasks so `1` timeout should be enough
245
+ // as this will be executed with the next event loop.
246
+ await aTimeout(1);
247
+
248
+ assert.typeOf(openOptions, 'object', 'has the file open request options');
249
+ assert.isFalse(openOptions!.multiple, 'the (open request) options.multiple is false');
250
+ assert.equal(openOptions!.title, 'Select a key file', 'has the (open request) options.title');
251
+ assert.lengthOf(openOptions!.filters!, 1, 'has the (open request) options.filters');
252
+ const [openFilter] = openOptions!.filters!;
253
+ assert.equal(openFilter.description, 'Certificate key files', 'open filter has the description');
254
+ assert.deepEqual(openFilter.accept, { 'application/x-pem-file': ['.pem', '.crt', '.cer', '.key'] }, 'filter has the accept');
255
+
256
+ assert.typeOf(readOptions, 'object', 'has the file read request options');
257
+ assert.equal(readOptions!.returnType, 'buffer', 'read file return type is set');
258
+ assert.isTrue(readOptions!.dispose, 'read file dispose is set');
259
+
260
+ assert.equal(eventPath, 'test/file.pem', 'read event has the correct path');
261
+ });
262
+ });
263
+
264
+ describe('Manual file selecting for PFX/PKCS12', () => {
265
+ let element: CertificateAdd;
266
+ let certTarget: HTMLElement;
267
+
268
+ beforeEach(async () => {
269
+ element = await pfxFixture();
270
+ certTarget = element.shadowRoot!.querySelector('.cert-file[data-kind="certificate"] ui-button') as HTMLElement;
271
+ });
272
+
273
+ it('dispatches the Filesystem.requestOpenFile for the certificate', async () => {
274
+ let openOptions: IOpenFileDialogInit | undefined;
275
+ let readOptions: FileReadOptions | undefined;
276
+ let eventPath: string | undefined;
277
+
278
+ element.addEventListener(EventTypes.Filesystem.requestOpenFile, (e: Event): void => {
279
+ const event = e as CustomEvent<{ options: IOpenFileDialogInit, result: Promise<IOpenFileDialogResult> }>;
280
+ openOptions = event.detail.options;
281
+ event.detail.result = Promise.resolve({
282
+ canceled: false,
283
+ filePath: ['test/file.pem'],
284
+ });
285
+ });
286
+
287
+ element.addEventListener(EventTypes.Filesystem.readFile, (e: Event): void => {
288
+ const event = e as CustomEvent<{ path: string, options: FileReadOptions, result: Promise<string | ArrayBuffer | Buffer> }>;
289
+ readOptions = event.detail.options;
290
+ eventPath = event.detail.path;
291
+ event.detail.result = Promise.resolve(new ArrayBuffer(100));
292
+ });
293
+
294
+ certTarget.click();
295
+ // Promises are resolved in the save event loop at the end as microtasks so `1` timeout should be enough
296
+ // as this will be executed with the next event loop.
297
+ await aTimeout(1);
298
+
299
+ assert.typeOf(openOptions, 'object', 'has the file open request options');
300
+ assert.isFalse(openOptions!.multiple, 'the (open request) options.multiple is false');
301
+ assert.equal(openOptions!.title, 'Select a certificate file', 'has the (open request) options.title');
302
+ assert.lengthOf(openOptions!.filters!, 1, 'has the (open request) options.filters');
303
+ const [openFilter] = openOptions!.filters!;
304
+ assert.equal(openFilter.description, 'Certificate files', 'open filter has the description');
305
+ assert.deepEqual(openFilter.accept, { 'application/x-pkcs12': ['.p12', '.pfx'] }, 'filter has the accept');
306
+
307
+ assert.typeOf(readOptions, 'object', 'has the file read request options');
308
+ assert.equal(readOptions!.returnType, 'buffer', 'read file return type is set');
309
+ assert.isTrue(readOptions!.dispose, 'read file dispose is set');
310
+
311
+ assert.equal(eventPath, 'test/file.pem', 'read event has the correct path');
312
+ });
313
+
314
+ });
315
+
316
+ describe('processDroppedFile()', () => {
317
+ let element: CertificateAdd;
318
+
319
+ beforeEach(async () => {
320
+ element = await basicFixture();
321
+ });
322
+
323
+ it('sets the certificate file info', async () => {
324
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' });
325
+ await element.processDroppedFile(file, 'certificate');
326
+ const info = element.certificateFile!;
327
+ assert.equal(info.fileName, 'test.txt', 'sets the file name');
328
+ assert.ok(info.contents, 'sets the file contents');
329
+ });
330
+
331
+ it('sets the key file info', async () => {
332
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' });
333
+ await element.processDroppedFile(file, 'key');
334
+ const info = element.keyFile!;
335
+ assert.equal(info.fileName, 'test.txt', 'sets the file name');
336
+ assert.ok(info.contents, 'sets the file contents');
337
+ });
338
+ });
339
+
340
+ describe('submit() on PEM', () => {
341
+ let element: CertificateAdd;
342
+
343
+ beforeEach(async () => {
344
+ element = await basicFixture();
345
+ });
346
+
347
+ afterEach(() => {
348
+ SnackNotifications.clear();
349
+ });
350
+
351
+ it('reports validity when missing certificate name', async () => {
352
+ const cert = new File(['test'], 'cert.pem', { type: 'text/plain' });
353
+ const key = new File(['test'], 'key.key', { type: 'text/plain' });
354
+ await element.processDroppedFile(cert, 'certificate');
355
+ await element.processDroppedFile(key, 'key');
356
+ const spy = sinon.spy();
357
+ element.addEventListener(EventTypes.Store.File.create, spy);
358
+ await element.submit();
359
+ assert.isFalse(spy.called, 'does not dispatch store event');
360
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
361
+ assert.isTrue(input.invalid, 'the input is invalid')
362
+ });
363
+
364
+ it('informs when the certificate is missing', async () => {
365
+ const key = new File(['test'], 'key.key', { type: 'text/plain' });
366
+ await element.processDroppedFile(key, 'key');
367
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
368
+ input.value = 'test';
369
+ input.notifyChange();
370
+ await input.updateComplete;
371
+
372
+ const spy = sinon.spy();
373
+ element.addEventListener(EventTypes.Store.File.create, spy);
374
+ await element.submit();
375
+ assert.isFalse(spy.called, 'does not dispatch store event');
376
+ });
377
+
378
+ it('informs when the key is missing', async () => {
379
+ const cert = new File(['test'], 'key.key', { type: 'text/plain' });
380
+ await element.processDroppedFile(cert, 'certificate');
381
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
382
+ input.value = 'test';
383
+ input.notifyChange();
384
+ await input.updateComplete;
385
+
386
+ const spy = sinon.spy();
387
+ element.addEventListener(EventTypes.Store.File.create, spy);
388
+ await element.submit();
389
+ assert.isFalse(spy.called, 'does not dispatch store event');
390
+ });
391
+
392
+ it('throws when no space', async () => {
393
+ const cert = new File(['test'], 'cert.pem', { type: 'text/plain' });
394
+ const key = new File(['test'], 'key.key', { type: 'text/plain' });
395
+ await element.processDroppedFile(cert, 'certificate');
396
+ await element.processDroppedFile(key, 'key');
397
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
398
+ input.value = 'test';
399
+ input.notifyChange();
400
+ await input.updateComplete;
401
+
402
+ let error: Error | undefined;
403
+ try {
404
+ await element.submit();
405
+ } catch (e) {
406
+ error = e as Error;
407
+ }
408
+
409
+ assert.ok(error);
410
+ });
411
+
412
+ it('dispatches the store event', async () => {
413
+ element.space = 'abc';
414
+ const cert = new File(['test'], 'cert.pem', { type: 'text/plain' });
415
+ const key = new File(['test'], 'key.key', { type: 'text/plain' });
416
+ await element.processDroppedFile(cert, 'certificate');
417
+ await element.processDroppedFile(key, 'key');
418
+ const input = element.shadowRoot!.querySelector('ui-text-field[name="name"]')! as Input;
419
+ input.value = 'test';
420
+ input.notifyChange();
421
+ await input.updateComplete;
422
+ const spy = sinon.spy();
423
+ element.addEventListener(EventTypes.Store.File.create, spy);
424
+ await element.submit();
425
+ assert.isTrue(spy.calledOnce);
426
+ });
427
+ });
428
+ });
429
+ });
430
+ });
@@ -314,28 +314,6 @@ describe('events', () => {
314
314
  ensureUnique('EventTypes.Store.History', EventTypes.Store.History);
315
315
  });
316
316
  });
317
-
318
- describe('Certificate namespace', () => {
319
- it('has Certificate namespace', () => {
320
- assert.typeOf(EventTypes.Store.Certificate, 'object');
321
- });
322
-
323
- [
324
- ['read', 'storeclientcertificateread'],
325
- ['list', 'storeclientcertificatelist'],
326
- ['delete', 'storeclientcertificatedelete'],
327
- ['update', 'storeclientcertificateupdate'],
328
- ['insert', 'storeclientcertificateinsert'],
329
- ].forEach(([prop, value]) => {
330
- it(`has ${prop} property`, () => {
331
- assert.equal(EventTypes.Store.Certificate[prop], value);
332
- });
333
- });
334
-
335
- it('has unique events', () => {
336
- ensureUnique('EventTypes.HttpClient.Model.Certificate', EventTypes.Store.Certificate);
337
- });
338
- });
339
317
  });
340
318
 
341
319
  describe('Config', () => {
@@ -39,8 +39,8 @@ export class UiMock {
39
39
  const { x, y, width, height } = element.getBoundingClientRect();
40
40
 
41
41
  return {
42
- x: Math.floor(x + window.pageXOffset + width / 2),
43
- y: Math.floor(y + window.pageYOffset + height / 2),
42
+ x: Math.floor(x + window.screenX + width / 2),
43
+ y: Math.floor(y + window.scrollY + height / 2),
44
44
  };
45
45
  }
46
46
 
@@ -96,4 +96,21 @@ export class UiMock {
96
96
  await sendMouse({ type: 'up' });
97
97
  // await executeServerCommand('take-screenshot', { name: `after-up` });
98
98
  }
99
+
100
+ static getFileDragEvent(type: string, opts: { file?: File } = {}): DragEvent {
101
+ let file: File;
102
+ if (opts.file) {
103
+ file = opts.file;
104
+ } else {
105
+ file = new File(['test'], 'test.txt', { type: 'text/plain' });
106
+ }
107
+ const dt = new DataTransfer();
108
+ dt.items.add(file);
109
+ return new DragEvent(type, {
110
+ dataTransfer: dt,
111
+ cancelable: true,
112
+ composed: true,
113
+ bubbles: true
114
+ });
115
+ }
99
116
  }
@@ -7,7 +7,7 @@ import {
7
7
  Clients,
8
8
  Testing,
9
9
  } from "@api-client/net-store";
10
- import { rmdir } from 'node:fs/promises'
10
+ import { rm } from 'node:fs/promises'
11
11
  import { takeScreenshotPlugin } from "./test/plugins/takeScreenshotPlugin.js";
12
12
 
13
13
  /** @typedef {import('@api-client/net-store').IServerConfiguration} IServerConfiguration */
@@ -27,7 +27,8 @@ const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];
27
27
  export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
28
28
  /** Test files to run */
29
29
  files: [
30
- "test/**/**/*.test.ts",
30
+ "test/**/*.test.ts",
31
+ // "test/amf/**/*.test.ts",
31
32
  // "test/elements/store/*.test.ts",
32
33
  ],
33
34
 
@@ -117,7 +118,7 @@ export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
117
118
  await oauth2server.stop();
118
119
  await singleServer.stop();
119
120
  await singleStore.cleanup();
120
- await rmdir("test/store", { recursive: true });
121
+ await rm("test/store", { recursive: true, force: true });
121
122
  },
122
123
  },
123
124
  ],
@@ -149,10 +150,10 @@ export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
149
150
 
150
151
  testFramework: {
151
152
  config: {
152
- timeout: 600000,
153
+ timeout: 60000,
153
154
  },
154
155
  },
155
156
  browserStartTimeout: 20000,
156
157
  testsStartTimeout: 20000,
157
- testsFinishTimeout: 600000,
158
+ testsFinishTimeout: 60000,
158
159
  });