@rancher/shell 3.0.9-rc.4 → 3.0.9-rc.6

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 (218) hide show
  1. package/assets/brand/suse/metadata.json +2 -1
  2. package/assets/images/providers/oci-open-containers.svg +22 -0
  3. package/assets/images/providers/traefik.png +0 -0
  4. package/assets/styles/themes/_dark.scss +2 -0
  5. package/assets/styles/themes/_light.scss +2 -0
  6. package/assets/styles/themes/_modern.scss +6 -0
  7. package/assets/translations/en-us.yaml +218 -26
  8. package/components/ActionMenuShell.vue +1 -1
  9. package/components/CruResource.vue +3 -1
  10. package/components/ExplorerProjectsNamespaces.vue +12 -12
  11. package/components/Inactivity.vue +2 -2
  12. package/components/Resource/Detail/Card/ExtrasCard.vue +49 -15
  13. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +109 -0
  14. package/components/Resource/Detail/Card/StatusCard/index.vue +21 -4
  15. package/components/Resource/Detail/Card/__tests__/ExtrasCard.test.ts +111 -0
  16. package/components/Resource/Detail/Masthead/__tests__/index.test.ts +0 -17
  17. package/components/Resource/Detail/Masthead/index.vue +11 -4
  18. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +19 -2
  19. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +19 -11
  20. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +3 -1
  21. package/components/Resource/Detail/Metadata/index.vue +1 -1
  22. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +12 -0
  23. package/components/Resource/Detail/ResourcePopover/index.vue +2 -0
  24. package/components/Resource/Detail/ResourceRow.vue +3 -3
  25. package/components/ResourceDetail/Masthead/latest.vue +12 -2
  26. package/components/ResourceList/index.vue +12 -0
  27. package/components/ResourceTable.vue +38 -4
  28. package/components/Tabbed/Tab.vue +4 -0
  29. package/components/Tabbed/index.vue +4 -1
  30. package/components/Window/ContainerLogs.vue +48 -37
  31. package/components/fleet/FleetClusterTargets/TargetsList.vue +2 -2
  32. package/components/fleet/FleetClusterTargets/index.vue +6 -1
  33. package/components/fleet/GitRepoAdvancedTab.vue +333 -0
  34. package/components/fleet/GitRepoMetadataTab.vue +43 -0
  35. package/components/fleet/GitRepoRepositoryTab.vue +101 -0
  36. package/components/fleet/GitRepoTargetTab.vue +77 -0
  37. package/components/fleet/HelmOpAdvancedTab.vue +247 -0
  38. package/components/fleet/HelmOpChartTab.vue +158 -0
  39. package/components/fleet/HelmOpMetadataTab.vue +46 -0
  40. package/components/fleet/HelmOpTargetTab.vue +84 -0
  41. package/components/fleet/HelmOpValuesTab.vue +147 -0
  42. package/components/fleet/__tests__/FleetClusterTargets.test.ts +119 -70
  43. package/components/form/ChangePassword.vue +41 -35
  44. package/components/form/NodeScheduling.vue +81 -7
  45. package/components/form/PodAffinity.vue +1 -36
  46. package/components/form/ResourceLabeledSelect.vue +8 -4
  47. package/components/form/ResourceQuota/Namespace.vue +30 -9
  48. package/components/form/ResourceQuota/NamespaceRow.vue +25 -7
  49. package/components/form/ResourceQuota/Project.vue +150 -51
  50. package/components/form/ResourceQuota/ResourceQuotaEntry.vue +145 -0
  51. package/components/form/ResourceQuota/__tests__/Namespace.test.ts +307 -0
  52. package/components/form/ResourceQuota/__tests__/NamespaceRow.test.ts +281 -0
  53. package/components/form/ResourceQuota/__tests__/Project.test.ts +310 -0
  54. package/components/form/ResourceQuota/__tests__/ResourceQuotaEntry.test.ts +215 -0
  55. package/components/form/SchedulingCustomization.vue +14 -6
  56. package/components/form/SelectOrCreateAuthSecret.vue +113 -19
  57. package/components/form/__tests__/NodeScheduling.test.ts +12 -9
  58. package/components/form/__tests__/PodAffinity.test.ts +21 -2
  59. package/components/form/__tests__/SchedulingCustomization.test.ts +240 -0
  60. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +35 -0
  61. package/components/formatter/ClusterLink.vue +8 -0
  62. package/components/formatter/MachineSummaryGraph.vue +10 -2
  63. package/components/formatter/SecretOrigin.vue +79 -0
  64. package/components/nav/TopLevelMenu.helper.ts +50 -2
  65. package/components/nav/TopLevelMenu.vue +14 -0
  66. package/components/nav/Type.vue +5 -0
  67. package/components/nav/__tests__/TopLevelMenu.test.ts +3 -3
  68. package/components/nav/__tests__/Type.test.ts +6 -4
  69. package/config/labels-annotations.js +7 -6
  70. package/config/pagination-table-headers.js +6 -4
  71. package/config/product/explorer.js +5 -14
  72. package/config/product/manager.js +18 -1
  73. package/config/query-params.js +3 -0
  74. package/config/router/navigation-guards/authentication.js +8 -9
  75. package/config/settings.ts +15 -2
  76. package/config/table-headers.js +21 -17
  77. package/config/types.js +33 -10
  78. package/detail/auditlog.cattle.io.auditpolicy.vue +19 -0
  79. package/detail/management.cattle.io.user.vue +1 -2
  80. package/detail/node.vue +0 -1
  81. package/detail/provisioning.cattle.io.cluster.vue +2 -1
  82. package/detail/workload/index.vue +11 -16
  83. package/dialog/ChangePasswordDialog.vue +8 -0
  84. package/dialog/DeactivateDriverDialog.vue +1 -1
  85. package/dialog/GenericPrompt.vue +20 -3
  86. package/dialog/Ipv6NetworkingDialog.vue +156 -0
  87. package/dialog/ScaleMachineDownDialog.vue +65 -15
  88. package/dialog/ScalePoolDownDialog.vue +2 -2
  89. package/dialog/SearchDialog.vue +10 -2
  90. package/dialog/__tests__/ScaleMachineDownDialog.test.ts +184 -0
  91. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +89 -0
  92. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +1 -0
  93. package/edit/__tests__/management.cattle.io.project.test.js +81 -98
  94. package/edit/auditlog.cattle.io.auditpolicy/AdditionalRedactions.vue +114 -0
  95. package/edit/auditlog.cattle.io.auditpolicy/Filters.vue +119 -0
  96. package/edit/auditlog.cattle.io.auditpolicy/General.vue +180 -0
  97. package/edit/auditlog.cattle.io.auditpolicy/__tests__/AdditionalRedactions.test.ts +327 -0
  98. package/edit/auditlog.cattle.io.auditpolicy/__tests__/Filters.test.ts +449 -0
  99. package/edit/auditlog.cattle.io.auditpolicy/__tests__/General.test.ts +472 -0
  100. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/AdditionalRedactions.test.ts.snap +27 -0
  101. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/Filters.test.ts.snap +39 -0
  102. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +174 -0
  103. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +29 -0
  104. package/edit/auditlog.cattle.io.auditpolicy/__tests__/index.test.ts +215 -0
  105. package/edit/auditlog.cattle.io.auditpolicy/index.vue +104 -0
  106. package/edit/auditlog.cattle.io.auditpolicy/types.ts +28 -0
  107. package/edit/auth/oidc.vue +1 -1
  108. package/edit/catalog.cattle.io.clusterrepo.vue +155 -25
  109. package/edit/fleet.cattle.io.gitrepo.vue +161 -276
  110. package/edit/fleet.cattle.io.helmop.vue +190 -332
  111. package/edit/management.cattle.io.project.vue +11 -42
  112. package/edit/management.cattle.io.setting.vue +6 -0
  113. package/edit/management.cattle.io.user.vue +29 -34
  114. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +55 -24
  115. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +1 -103
  116. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +13 -1
  117. package/edit/provisioning.cattle.io.cluster/__tests__/rke2-fleet-cluster-agent.test.ts +283 -0
  118. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +196 -2
  119. package/edit/provisioning.cattle.io.cluster/ingress/IngressCards.vue +112 -0
  120. package/edit/provisioning.cattle.io.cluster/ingress/IngressConfiguration.vue +158 -0
  121. package/edit/provisioning.cattle.io.cluster/rke2.vue +184 -66
  122. package/edit/provisioning.cattle.io.cluster/shared.ts +39 -0
  123. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +2 -1
  124. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +56 -7
  125. package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +319 -0
  126. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +2 -1
  127. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -1
  128. package/edit/provisioning.cattle.io.cluster/tabs/etcd/__tests__/S3Config.test.ts +13 -1
  129. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +10 -44
  130. package/edit/secret/index.vue +1 -1
  131. package/edit/token.vue +68 -29
  132. package/edit/workload/__tests__/index.test.ts +2 -37
  133. package/edit/workload/index.vue +6 -2
  134. package/edit/workload/mixins/workload.js +0 -32
  135. package/list/__tests__/management.cattle.io.setting.test.ts +198 -0
  136. package/list/auditlog.cattle.io.auditpolicy.vue +63 -0
  137. package/list/group.principal.vue +11 -15
  138. package/list/management.cattle.io.setting.vue +13 -0
  139. package/list/management.cattle.io.user.vue +11 -21
  140. package/list/provisioning.cattle.io.cluster.vue +50 -1
  141. package/list/secret.vue +4 -9
  142. package/list/service.vue +6 -8
  143. package/machine-config/amazonec2.vue +11 -4
  144. package/machine-config/azure.vue +14 -0
  145. package/machine-config/components/EC2Networking.vue +46 -30
  146. package/machine-config/components/__tests__/EC2Networking.test.ts +7 -7
  147. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +0 -9
  148. package/machine-config/digitalocean.vue +3 -3
  149. package/mixins/browser-tab-visibility.js +5 -4
  150. package/mixins/fetch.client.js +6 -0
  151. package/models/__tests__/auditlog.cattle.io.auditpolicy.test.ts +117 -0
  152. package/models/__tests__/namespace.test.ts +11 -0
  153. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +96 -0
  154. package/models/__tests__/workload.test.ts +90 -6
  155. package/models/auditlog.cattle.io.auditpolicy.js +46 -0
  156. package/models/catalog.cattle.io.clusterrepo.js +30 -4
  157. package/models/cluster.x-k8s.io.machine.js +1 -1
  158. package/models/cluster.x-k8s.io.machinedeployment.js +5 -5
  159. package/models/event.js +5 -0
  160. package/models/ext.cattle.io.groupmembershiprefreshrequest.js +15 -0
  161. package/models/ext.cattle.io.passwordchangerequest.js +15 -0
  162. package/models/ext.cattle.io.selfuser.js +15 -0
  163. package/models/ext.cattle.io.token.js +48 -0
  164. package/models/fleet-application.js +17 -7
  165. package/models/kontainerdriver.js +2 -2
  166. package/models/management.cattle.io.user.js +28 -31
  167. package/models/namespace.js +7 -1
  168. package/models/nodedriver.js +2 -2
  169. package/models/provisioning.cattle.io.cluster.js +28 -7
  170. package/models/schema.js +18 -0
  171. package/models/secret.js +27 -41
  172. package/models/service.js +44 -1
  173. package/models/steve-schema.ts +39 -2
  174. package/models/token.js +4 -0
  175. package/models/workload.js +13 -6
  176. package/package.json +1 -1
  177. package/pages/account/index.vue +108 -72
  178. package/pages/auth/login.vue +15 -8
  179. package/pages/auth/setup.vue +55 -27
  180. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +4 -1
  181. package/pages/c/_cluster/apps/charts/index.vue +93 -4
  182. package/pages/c/_cluster/apps/charts/install.vue +317 -42
  183. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -4
  184. package/pages/c/_cluster/settings/index.vue +3 -1
  185. package/pages/home.vue +9 -3
  186. package/plugins/dashboard-store/__tests__/getters.test.ts +108 -0
  187. package/plugins/dashboard-store/__tests__/resource-class.test.ts +28 -3
  188. package/plugins/dashboard-store/actions.js +10 -8
  189. package/plugins/dashboard-store/getters.js +30 -6
  190. package/plugins/dashboard-store/index.js +3 -2
  191. package/plugins/dashboard-store/mutations.js +8 -1
  192. package/plugins/dashboard-store/resource-class.js +15 -8
  193. package/plugins/steve/__tests__/steve-class.test.ts +128 -0
  194. package/plugins/steve/schema.d.ts +5 -0
  195. package/plugins/steve/steve-class.js +28 -0
  196. package/plugins/steve/steve-pagination-utils.ts +7 -2
  197. package/rancher-components/RcIcon/types.ts +2 -0
  198. package/rancher-components/RcItemCard/RcItemCard.vue +64 -19
  199. package/store/auth.js +57 -19
  200. package/store/notifications.ts +1 -1
  201. package/store/prefs.js +3 -0
  202. package/store/type-map.js +12 -1
  203. package/types/aws-sdk.d.ts +121 -0
  204. package/types/resources/node.ts +15 -0
  205. package/types/shell/index.d.ts +542 -516
  206. package/types/store/dashboard-store.types.ts +7 -0
  207. package/types/store/pagination.types.ts +5 -5
  208. package/utils/__tests__/array.test.ts +1 -29
  209. package/utils/__tests__/cluster-agent-configuration.test.ts +203 -0
  210. package/utils/array.ts +0 -11
  211. package/utils/aws.ts +21 -0
  212. package/utils/cluster.js +22 -2
  213. package/utils/pagination-wrapper.ts +11 -3
  214. package/utils/selector-typed.ts +1 -1
  215. package/vue.config.js +26 -13
  216. package/components/__tests__/ProjectRow.test.ts +0 -146
  217. package/components/form/ResourceQuota/ProjectRow.vue +0 -210
  218. package/edit/provisioning.cattle.io.cluster/defaults.ts +0 -1
@@ -0,0 +1,472 @@
1
+ import { shallowMount, VueWrapper } from '@vue/test-utils';
2
+ import General from '../General.vue';
3
+ import { ComponentPublicInstance } from 'vue';
4
+ import { AuditPolicy } from '@shell/edit/auditlog.cattle.io.auditpolicy/types';
5
+
6
+ interface GeneralComponent extends ComponentPublicInstance {
7
+ spec: AuditPolicy;
8
+ levelOptionsMap: Array<{ value: number; label: string }>;
9
+ }
10
+
11
+ // Mock the ID generation to have consistent snapshots
12
+ jest.mock('@shell/utils/string', () => ({ generateRandomAlphaString: () => 'test-id-123' }));
13
+
14
+ const defaultProps = {
15
+ value: {},
16
+ mode: 'create'
17
+ };
18
+
19
+ const globalMocks = {
20
+ global: {
21
+ mocks: {
22
+ $t: (key: string) => key,
23
+ t: (key: string) => key,
24
+ $store: {
25
+ getters: { 'i18n/t': (key: string) => key },
26
+ dispatch: jest.fn()
27
+ },
28
+ $route: {
29
+ params: {},
30
+ query: {}
31
+ },
32
+ $router: {
33
+ push: jest.fn(),
34
+ replace: jest.fn()
35
+ }
36
+ },
37
+ provide: {
38
+ store: {
39
+ getters: { 'i18n/t': (key: string) => key },
40
+ dispatch: jest.fn()
41
+ }
42
+ },
43
+ stubs: {
44
+ LabeledSelect: true,
45
+ Checkbox: true
46
+ }
47
+ }
48
+ };
49
+
50
+ function factory(props: Record<string, any> = {}, options: Record<string, any> = {}): VueWrapper<GeneralComponent> {
51
+ return (shallowMount(General, {
52
+ props: { ...defaultProps, ...props },
53
+ ...globalMocks,
54
+ ...options
55
+ }) as unknown) as VueWrapper<GeneralComponent>;
56
+ }
57
+
58
+ describe('component: General', () => {
59
+ describe('rendering & initial state', () => {
60
+ it('should render with default props (snapshot)', () => {
61
+ const wrapper = factory();
62
+
63
+ expect(wrapper.element).toMatchSnapshot();
64
+ });
65
+
66
+ it('should render with create mode', () => {
67
+ const wrapper = factory({ mode: 'create' });
68
+
69
+ expect(wrapper.findComponent({ name: 'Checkbox' }).exists()).toBe(true);
70
+ expect(wrapper.findComponent({ name: 'LabeledSelect' }).exists()).toBe(true);
71
+ });
72
+
73
+ it('should render with edit mode', () => {
74
+ const wrapper = factory({ mode: 'edit' });
75
+
76
+ expect(wrapper.findComponent({ name: 'Checkbox' }).exists()).toBe(true);
77
+ expect(wrapper.findComponent({ name: 'LabeledSelect' }).exists()).toBe(true);
78
+ });
79
+
80
+ it('should render with view mode', () => {
81
+ const wrapper = factory({ mode: 'view' });
82
+
83
+ expect(wrapper.findComponent({ name: 'Checkbox' }).exists()).toBe(true);
84
+ expect(wrapper.findComponent({ name: 'LabeledSelect' }).exists()).toBe(true);
85
+ });
86
+
87
+ it('should render with initial audit policy data', () => {
88
+ const value = {
89
+ enabled: true,
90
+ verbosity: {
91
+ level: 2,
92
+ request: { headers: true, body: false },
93
+ response: { headers: false, body: true }
94
+ }
95
+ };
96
+ const wrapper = factory({ value });
97
+
98
+ expect(wrapper.vm.spec.enabled).toBe(true);
99
+ expect(wrapper.vm.spec.verbosity?.level).toBe(2);
100
+ expect(wrapper.vm.spec.verbosity?.request?.headers).toBe(true);
101
+ expect(wrapper.vm.spec.verbosity?.response?.body).toBe(true);
102
+ });
103
+ });
104
+
105
+ describe('props & state changes', () => {
106
+ it('should handle empty value prop gracefully', () => {
107
+ const wrapper = factory({ value: {} });
108
+
109
+ expect(wrapper.vm.spec.enabled).toBe(false);
110
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
111
+ expect(wrapper.vm.spec.verbosity?.request?.headers).toBe(false);
112
+ expect(wrapper.vm.spec.verbosity?.response?.headers).toBe(false);
113
+ });
114
+
115
+ it('should handle null value prop gracefully', () => {
116
+ const wrapper = factory({ value: null });
117
+
118
+ expect(wrapper.vm.spec.enabled).toBe(false);
119
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
120
+ });
121
+
122
+ it('should accept different mode prop values', () => {
123
+ const createWrapper = factory({ mode: 'create' });
124
+ const editWrapper = factory({ mode: 'edit' });
125
+ const viewWrapper = factory({ mode: 'view' });
126
+
127
+ expect((createWrapper.props() as any).mode).toBe('create');
128
+ expect((editWrapper.props() as any).mode).toBe('edit');
129
+ expect((viewWrapper.props() as any).mode).toBe('view');
130
+ });
131
+
132
+ it('should merge defaults with provided value', () => {
133
+ const value = { enabled: true };
134
+ const wrapper = factory({ value });
135
+
136
+ expect(wrapper.vm.spec.enabled).toBe(true);
137
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
138
+ expect(wrapper.vm.spec.verbosity?.request).toBeDefined();
139
+ expect(wrapper.vm.spec.verbosity?.response).toBeDefined();
140
+ });
141
+
142
+ it('should handle missing verbosity request object', () => {
143
+ const value = {
144
+ enabled: true,
145
+ verbosity: { level: 1 }
146
+ };
147
+ const wrapper = factory({ value });
148
+
149
+ expect(wrapper.vm.spec.verbosity?.request?.headers).toBe(false);
150
+ expect(wrapper.vm.spec.verbosity?.request?.body).toBe(false);
151
+ });
152
+
153
+ it('should handle missing verbosity response object', () => {
154
+ const value = {
155
+ enabled: true,
156
+ verbosity: { level: 1 }
157
+ };
158
+ const wrapper = factory({ value });
159
+
160
+ expect(wrapper.vm.spec.verbosity?.response?.headers).toBe(false);
161
+ expect(wrapper.vm.spec.verbosity?.response?.body).toBe(false);
162
+ });
163
+ });
164
+
165
+ describe('user interaction', () => {
166
+ it('should emit update:value when enabled changes', async() => {
167
+ const wrapper = factory();
168
+
169
+ wrapper.vm.spec.enabled = true;
170
+ await wrapper.vm.$nextTick();
171
+
172
+ expect(wrapper.emitted('update:value')).toHaveLength(2);
173
+ expect((wrapper.emitted('update:value')?.[1]?.[0] as any).enabled).toBe(true);
174
+ });
175
+
176
+ it('should emit update:value when verbosity level changes', async() => {
177
+ const wrapper = factory();
178
+
179
+ wrapper.vm.spec.verbosity!.level = 2;
180
+ await wrapper.vm.$nextTick();
181
+
182
+ expect(wrapper.emitted('update:value')).toHaveLength(2);
183
+ expect((wrapper.emitted('update:value')?.[1]?.[0] as any).verbosity.level).toBe(2);
184
+ });
185
+
186
+ it('should emit update:value when request headers changes', async() => {
187
+ const wrapper = factory();
188
+
189
+ wrapper.vm.spec.verbosity!.request!.headers = true;
190
+ await wrapper.vm.$nextTick();
191
+
192
+ expect(wrapper.emitted('update:value')).toHaveLength(2);
193
+ expect((wrapper.emitted('update:value')?.[1]?.[0] as any).verbosity.request.headers).toBe(true);
194
+ });
195
+
196
+ it('should emit update:value when response body changes', async() => {
197
+ const wrapper = factory();
198
+
199
+ wrapper.vm.spec.verbosity!.response!.body = true;
200
+ await wrapper.vm.$nextTick();
201
+
202
+ expect(wrapper.emitted('update:value')).toHaveLength(2);
203
+ expect((wrapper.emitted('update:value')?.[1]?.[0] as any).verbosity.response.body).toBe(true);
204
+ });
205
+
206
+ it('should preserve existing prop values when emitting updates', async() => {
207
+ const value = { customField: 'test', enabled: false };
208
+ const wrapper = factory({ value });
209
+
210
+ wrapper.vm.spec.enabled = true;
211
+ await wrapper.vm.$nextTick();
212
+
213
+ const emittedValue = (wrapper.emitted('update:value')?.[1]?.[0] as any);
214
+
215
+ expect(emittedValue.customField).toBe('test');
216
+ expect(emittedValue.enabled).toBe(true);
217
+ });
218
+
219
+ it('should emit complete verbosity object with all properties', async() => {
220
+ const wrapper = factory();
221
+
222
+ wrapper.vm.spec.verbosity!.level = 3;
223
+ wrapper.vm.spec.verbosity!.request!.headers = true;
224
+ wrapper.vm.spec.verbosity!.response!.body = true;
225
+ await wrapper.vm.$nextTick();
226
+
227
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
228
+
229
+ expect(emittedValue.verbosity).toStrictEqual({
230
+ level: 3,
231
+ request: { headers: true, body: false },
232
+ response: { headers: false, body: true }
233
+ });
234
+ });
235
+ });
236
+
237
+ describe('computed properties & logic', () => {
238
+ it('should return correct levelOptionsMap values', () => {
239
+ const wrapper = factory();
240
+
241
+ expect(wrapper.vm.levelOptionsMap).toHaveLength(4);
242
+ expect(wrapper.vm.levelOptionsMap[0]).toStrictEqual({
243
+ value: 0,
244
+ label: 'auditPolicy.general.verbosity.level.0'
245
+ });
246
+ expect(wrapper.vm.levelOptionsMap[3]).toStrictEqual({
247
+ value: 3,
248
+ label: 'auditPolicy.general.verbosity.level.3'
249
+ });
250
+ });
251
+
252
+ it('should have reactive levelOptionsMap computed property', async() => {
253
+ const wrapper = factory();
254
+ const initialOptions = wrapper.vm.levelOptionsMap;
255
+
256
+ expect(wrapper.vm.levelOptionsMap).toStrictEqual(initialOptions);
257
+ });
258
+
259
+ it('should initialize spec reactive ref correctly', () => {
260
+ const wrapper = factory();
261
+
262
+ expect(wrapper.vm.spec).toBeDefined();
263
+ expect(wrapper.vm.spec.enabled).toBe(false);
264
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
265
+ });
266
+
267
+ it('should merge defaults with props correctly in spec', () => {
268
+ const value = { enabled: true, verbosity: { level: 2 } };
269
+ const wrapper = factory({ value });
270
+
271
+ expect(wrapper.vm.spec.enabled).toBe(true);
272
+ expect(wrapper.vm.spec.verbosity?.level).toBe(2);
273
+ expect(wrapper.vm.spec.verbosity?.request?.headers).toBe(false);
274
+ expect(wrapper.vm.spec.verbosity?.response?.body).toBe(false);
275
+ });
276
+ });
277
+
278
+ describe('component configuration', () => {
279
+ it('should configure Checkbox components with correct props', () => {
280
+ const wrapper = factory({ mode: 'edit' });
281
+ const checkboxes = wrapper.findAllComponents({ name: 'Checkbox' });
282
+
283
+ expect(checkboxes.length).toBeGreaterThan(0);
284
+ });
285
+
286
+ it('should render LabeledSelect component', () => {
287
+ const wrapper = factory({ mode: 'view' });
288
+ const select = wrapper.findComponent({ name: 'LabeledSelect' });
289
+
290
+ expect(select.exists()).toBe(true);
291
+ // With stub components, we can't test actual props
292
+ expect(wrapper.vm.levelOptionsMap).toHaveLength(4);
293
+ });
294
+
295
+ it('should maintain verbosity structure when level is valid', async() => {
296
+ const wrapper = factory();
297
+
298
+ wrapper.vm.spec.verbosity!.level = 1;
299
+ await wrapper.vm.$nextTick();
300
+
301
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
302
+
303
+ expect(emittedValue.verbosity).toBeDefined();
304
+ expect(emittedValue.verbosity.level).toBe(1);
305
+ expect(emittedValue.verbosity.request).toBeDefined();
306
+ expect(emittedValue.verbosity.response).toBeDefined();
307
+ });
308
+
309
+ it('should render form structure correctly', () => {
310
+ const wrapper = factory();
311
+
312
+ expect(wrapper.find('.row').exists()).toBe(true);
313
+ expect(wrapper.find('fieldset').exists()).toBe(true);
314
+ expect(wrapper.find('.spacer').exists()).toBe(true);
315
+ });
316
+ });
317
+
318
+ describe('verbosity data structure', () => {
319
+ it('should handle verbosity with level 0', () => {
320
+ const wrapper = factory();
321
+
322
+ // Level 0 is the default, so check the initial state
323
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
324
+ });
325
+
326
+ it('should handle verbosity with level 3', async() => {
327
+ const wrapper = factory();
328
+
329
+ wrapper.vm.spec.verbosity!.level = 3;
330
+ await wrapper.vm.$nextTick();
331
+
332
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
333
+
334
+ expect(emittedValue.verbosity.level).toBe(3);
335
+ });
336
+
337
+ it('should handle all request options', async() => {
338
+ const wrapper = factory();
339
+
340
+ wrapper.vm.spec.verbosity!.request!.headers = true;
341
+ wrapper.vm.spec.verbosity!.request!.body = true;
342
+ await wrapper.vm.$nextTick();
343
+
344
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
345
+
346
+ expect(emittedValue.verbosity.request.headers).toBe(true);
347
+ expect(emittedValue.verbosity.request.body).toBe(true);
348
+ });
349
+
350
+ it('should handle all response options', async() => {
351
+ const wrapper = factory();
352
+
353
+ wrapper.vm.spec.verbosity!.response!.headers = true;
354
+ wrapper.vm.spec.verbosity!.response!.body = true;
355
+ await wrapper.vm.$nextTick();
356
+
357
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
358
+
359
+ expect(emittedValue.verbosity.response.headers).toBe(true);
360
+ expect(emittedValue.verbosity.response.body).toBe(true);
361
+ });
362
+
363
+ it('should handle complete audit policy configuration', async() => {
364
+ const wrapper = factory();
365
+
366
+ wrapper.vm.spec.enabled = true;
367
+ wrapper.vm.spec.verbosity!.level = 2;
368
+ wrapper.vm.spec.verbosity!.request!.headers = true;
369
+ wrapper.vm.spec.verbosity!.response!.body = true;
370
+ await wrapper.vm.$nextTick();
371
+
372
+ const emittedValue = (wrapper.emitted('update:value')?.[1]?.[0] as any);
373
+
374
+ expect(emittedValue).toStrictEqual({
375
+ enabled: true,
376
+ verbosity: {
377
+ level: 2,
378
+ request: { headers: true, body: false },
379
+ response: { headers: false, body: true }
380
+ }
381
+ });
382
+ });
383
+ });
384
+
385
+ describe('edge cases', () => {
386
+ it('should handle missing verbosity object entirely', () => {
387
+ const value = { enabled: true };
388
+ const wrapper = factory({ value });
389
+
390
+ expect(wrapper.vm.spec.verbosity).toBeDefined();
391
+ expect(wrapper.vm.spec.verbosity?.level).toBe(0);
392
+ expect(wrapper.vm.spec.verbosity?.request).toBeDefined();
393
+ expect(wrapper.vm.spec.verbosity?.response).toBeDefined();
394
+ });
395
+
396
+ it('should handle undefined enabled property', () => {
397
+ const value = { verbosity: { level: 1 } };
398
+ const wrapper = factory({ value });
399
+
400
+ expect(wrapper.vm.spec.enabled).toBe(false);
401
+ });
402
+
403
+ it('should handle partial verbosity configuration', () => {
404
+ const value = {
405
+ verbosity: {
406
+ level: 1,
407
+ request: { headers: true }
408
+ }
409
+ };
410
+ const wrapper = factory({ value });
411
+
412
+ expect(wrapper.vm.spec.verbosity?.level).toBe(1);
413
+ expect(wrapper.vm.spec.verbosity?.request?.headers).toBe(true);
414
+ // The component doesn't fill in missing properties for existing objects
415
+ expect(wrapper.vm.spec.verbosity?.request?.body).toBe(false);
416
+ expect(wrapper.vm.spec.verbosity?.response).toBeDefined();
417
+ expect(wrapper.vm.spec.verbosity?.response?.headers).toBe(false);
418
+ expect(wrapper.vm.spec.verbosity?.response?.body).toBe(false);
419
+ });
420
+
421
+ it('should handle invalid verbosity data gracefully', () => {
422
+ // Use a more realistic invalid case - missing nested properties
423
+ const value = { verbosity: { level: 1 } }; // Missing request/response objects
424
+ const wrapper = factory({ value });
425
+
426
+ expect(wrapper.vm.spec.verbosity).toBeDefined();
427
+ expect(wrapper.vm.spec.verbosity?.level).toBe(1);
428
+ expect(wrapper.vm.spec.verbosity?.request).toBeDefined();
429
+ expect(wrapper.vm.spec.verbosity?.response).toBeDefined();
430
+ });
431
+
432
+ it('should handle deep reactivity correctly', async() => {
433
+ const wrapper = factory();
434
+
435
+ // Initialization should emit the first update
436
+ expect(wrapper.emitted('update:value')).toHaveLength(1);
437
+
438
+ // Make multiple nested changes
439
+ wrapper.vm.spec.verbosity!.request!.headers = true;
440
+ wrapper.vm.spec.verbosity!.request!.body = true;
441
+ wrapper.vm.spec.verbosity!.response!.headers = true;
442
+ await wrapper.vm.$nextTick();
443
+
444
+ // Second emission after changes, only one additional one
445
+ expect(wrapper.emitted('update:value')).toHaveLength(2);
446
+
447
+ const emittedValue = (wrapper.emitted('update:value')?.[0]?.[0] as any);
448
+
449
+ expect(emittedValue.verbosity.request.headers).toBe(true);
450
+ expect(emittedValue.verbosity.request.body).toBe(true);
451
+ expect(emittedValue.verbosity.response.headers).toBe(true);
452
+ });
453
+
454
+ it('should maintain object structure after verbosity restoration', async() => {
455
+ const wrapper = factory();
456
+
457
+ // Set level to null to trigger deletion
458
+ wrapper.vm.spec.verbosity!.level = null as any;
459
+ await wrapper.vm.$nextTick();
460
+
461
+ // Set level back to valid value
462
+ wrapper.vm.spec.verbosity!.level = 1;
463
+ await wrapper.vm.$nextTick();
464
+
465
+ const emittedValue = (wrapper.emitted('update:value')?.[1]?.[0] as any);
466
+
467
+ expect(emittedValue.verbosity).toBeDefined();
468
+ expect(emittedValue.verbosity.request).toBeDefined();
469
+ expect(emittedValue.verbosity.response).toBeDefined();
470
+ });
471
+ });
472
+ });
@@ -0,0 +1,27 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`component: AdditionalRedactions rendering & initial state should render with default props (snapshot) 1`] = `
4
+ <div>
5
+ <div
6
+ class="row mb-40"
7
+ >
8
+ <div
9
+ class="col span-12"
10
+ >
11
+ <tabbed-stub
12
+ componenttestid="tabbed"
13
+ flat="false"
14
+ hidesingletab="false"
15
+ nocontent="false"
16
+ removeborders="false"
17
+ scrollonchange="false"
18
+ showextensiontabs="true"
19
+ showtabsaddremove="true"
20
+ sidetabs="true"
21
+ tabsonly="false"
22
+ usehash="true"
23
+ />
24
+ </div>
25
+ </div>
26
+ </div>
27
+ `;
@@ -0,0 +1,39 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`component: Filters rendering & initial state should render with default props (snapshot) 1`] = `
4
+ <div>
5
+ <div
6
+ class="row mb-40"
7
+ >
8
+ <div
9
+ class="col span-12"
10
+ >
11
+ <array-list-stub
12
+ a11ylabel=""
13
+ addallowed="true"
14
+ addclass=""
15
+ adddisabled="false"
16
+ addicon=""
17
+ addlabel="auditPolicy.filters.add"
18
+ componenttestid="array-list"
19
+ defaultaddvalue="[object Object]"
20
+ disabled="false"
21
+ initialemptyrow="false"
22
+ loading="false"
23
+ mode="create"
24
+ protip="false"
25
+ removeallowed="true"
26
+ removelabel=""
27
+ required="false"
28
+ rules=""
29
+ showheader="true"
30
+ title=""
31
+ value=""
32
+ valuelabel="Value"
33
+ valuemultiline="false"
34
+ valueplaceholder="auditPolicy.filters.placeholder"
35
+ />
36
+ </div>
37
+ </div>
38
+ </div>
39
+ `;