@openmfp/webcomponents 0.6.1 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mfp-wc-dashboard.js +153 -0
- package/mfp-webcomponents.js +573 -0
- package/package.json +14 -68
- package/.github/workflows/pipeline.yaml +0 -41
- package/.storybook/main.ts +0 -34
- package/.storybook/preview.ts +0 -29
- package/.storybook/tsconfig.json +0 -11
- package/AGENTS.md +0 -153
- package/CODEOWNERS +0 -6
- package/CONTRIBUTING.md +0 -95
- package/LICENSE +0 -201
- package/LICENSES/Apache-2.0.txt +0 -73
- package/README.md +0 -91
- package/REUSE.toml +0 -9
- package/angular.json +0 -157
- package/docs/dashboard.md +0 -358
- package/docs/declarative-form.md +0 -178
- package/docs/declarative-table-card.md +0 -235
- package/docs/declarative-table.md +0 -315
- package/eslint.config.js +0 -41
- package/projects/ngx/cards/favorites/favorites.component.html +0 -12
- package/projects/ngx/cards/favorites/favorites.component.scss +0 -50
- package/projects/ngx/cards/favorites/favorites.component.ts +0 -19
- package/projects/ngx/cards/public-api.ts +0 -4
- package/projects/ngx/cards/service-status/service-status-card.component.html +0 -15
- package/projects/ngx/cards/service-status/service-status-card.component.scss +0 -87
- package/projects/ngx/cards/service-status/service-status-card.component.ts +0 -36
- package/projects/ngx/cards/stories/visited-service-card.stories.ts +0 -149
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.html +0 -17
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.scss +0 -34
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.ts +0 -22
- package/projects/ngx/cards/whats-new/whats-new.component.html +0 -10
- package/projects/ngx/cards/whats-new/whats-new.component.scss +0 -25
- package/projects/ngx/cards/whats-new/whats-new.component.ts +0 -46
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html +0 -28
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.scss +0 -44
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.spec.ts +0 -85
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.ts +0 -58
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.html +0 -29
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.scss +0 -63
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.spec.ts +0 -255
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.ts +0 -75
- package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts +0 -76
- package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.ts +0 -109
- package/projects/ngx/declarative-ui/dashboard/card/utils/index.ts +0 -4
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.spec.ts +0 -141
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.ts +0 -44
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.spec.ts +0 -142
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.ts +0 -52
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.spec.ts +0 -107
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.ts +0 -22
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html +0 -134
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.scss +0 -88
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.spec.ts +0 -354
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.ts +0 -238
- package/projects/ngx/declarative-ui/dashboard/dashboard/index.ts +0 -1
- package/projects/ngx/declarative-ui/dashboard/index.ts +0 -5
- package/projects/ngx/declarative-ui/dashboard/models/constants.ts +0 -2
- package/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts +0 -50
- package/projects/ngx/declarative-ui/dashboard/models/index.ts +0 -1
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html +0 -28
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.scss +0 -85
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.spec.ts +0 -104
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.ts +0 -23
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html +0 -62
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.scss +0 -12
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.spec.ts +0 -301
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.ts +0 -166
- package/projects/ngx/declarative-ui/form/declarative-form/index.ts +0 -1
- package/projects/ngx/declarative-ui/form/index.ts +0 -2
- package/projects/ngx/declarative-ui/form/models/form-field-definition.ts +0 -15
- package/projects/ngx/declarative-ui/form/models/index.ts +0 -1
- package/projects/ngx/declarative-ui/form/utils/set-property-by-path.ts +0 -30
- package/projects/ngx/declarative-ui/models/index.ts +0 -2
- package/projects/ngx/declarative-ui/models/resource.ts +0 -5
- package/projects/ngx/declarative-ui/models/ui-definition.ts +0 -95
- package/projects/ngx/declarative-ui/public-api.ts +0 -4
- package/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts +0 -91
- package/projects/ngx/declarative-ui/stories/background-lightblue.png +0 -0
- package/projects/ngx/declarative-ui/stories/dashboard.cards.ts +0 -107
- package/projects/ngx/declarative-ui/stories/dashboard.stories.ts +0 -296
- package/projects/ngx/declarative-ui/stories/declarative-form.stories.ts +0 -149
- package/projects/ngx/declarative-ui/stories/declarative-table-card.stories.ts +0 -358
- package/projects/ngx/declarative-ui/stories/declarative-table.stories.ts +0 -363
- package/projects/ngx/declarative-ui/stories/pods-table.config.ts +0 -188
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.html +0 -138
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.scss +0 -21
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.spec.ts +0 -345
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.ts +0 -61
- package/projects/ngx/declarative-ui/table/declarative-table/index.ts +0 -1
- package/projects/ngx/declarative-ui/table/index.ts +0 -2
- package/projects/ngx/declarative-ui/table/models/index.ts +0 -14
- package/projects/ngx/declarative-ui/table/models/table.model.ts +0 -17
- package/projects/ngx/declarative-ui/table/utils/cssRules.engine.spec.ts +0 -146
- package/projects/ngx/declarative-ui/table/utils/cssRules.engine.ts +0 -69
- package/projects/ngx/declarative-ui/table/utils/field-definition.utils.spec.ts +0 -70
- package/projects/ngx/declarative-ui/table/utils/field-definition.utils.ts +0 -13
- package/projects/ngx/declarative-ui/table/utils/proccess-fields.spec.ts +0 -511
- package/projects/ngx/declarative-ui/table/utils/proccess-fields.ts +0 -71
- package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.spec.ts +0 -372
- package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.ts +0 -98
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-cell.constants.ts +0 -5
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.html +0 -1
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.scss +0 -0
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.spec.ts +0 -119
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.ts +0 -35
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.html +0 -7
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.scss +0 -0
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.spec.ts +0 -114
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.ts +0 -19
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.html +0 -7
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.scss +0 -10
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.spec.ts +0 -188
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.ts +0 -16
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.html +0 -59
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.scss +0 -33
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.spec.ts +0 -316
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.ts +0 -115
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html +0 -156
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.scss +0 -123
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.spec.ts +0 -786
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.ts +0 -286
- package/projects/ngx/declarative-ui/table-card/index.ts +0 -2
- package/projects/ngx/declarative-ui/table-card/models/configs.ts +0 -46
- package/projects/ngx/declarative-ui/tsconfig.lib.json +0 -11
- package/projects/ngx/declarative-ui/tsconfig.lib.prod.json +0 -9
- package/projects/ngx/declarative-ui/tsconfig.spec.json +0 -9
- package/projects/ngx/ng-package.json +0 -8
- package/projects/ngx/package.json +0 -22
- package/projects/ngx/public-api.ts +0 -2
- package/projects/ngx/tsconfig.lib.json +0 -11
- package/projects/ngx/tsconfig.lib.prod.json +0 -9
- package/projects/webcomponents/main.ts +0 -92
- package/projects/webcomponents/tsconfig.app.json +0 -9
- package/projects/webcomponents-dashboard/main.ts +0 -15
- package/projects/webcomponents-dashboard/tsconfig.app.json +0 -9
- package/renovate.json +0 -6
- package/scripts/bundle-wc.mjs +0 -79
- package/tsconfig.json +0 -37
- package/tsconfig.spec.json +0 -8
- package/tsconfig.storybook.json +0 -16
- package/vitest.config.ts +0 -26
|
@@ -1,786 +0,0 @@
|
|
|
1
|
-
import { FormFieldChangeEvent, FormFieldDefinition } from '../form/models';
|
|
2
|
-
import {
|
|
3
|
-
ButtonSettings,
|
|
4
|
-
GenericResource,
|
|
5
|
-
TableFieldDefinition,
|
|
6
|
-
ValueCellButtonClickEvent,
|
|
7
|
-
} from '../table/models';
|
|
8
|
-
import { DeclarativeTableCard } from './declarative-table-card.component';
|
|
9
|
-
import {
|
|
10
|
-
DeleteResourceConfirmationConfig,
|
|
11
|
-
ResourceFormConfig,
|
|
12
|
-
TableCardConfig,
|
|
13
|
-
TableCardFormState,
|
|
14
|
-
TableConfig,
|
|
15
|
-
} from './models/configs';
|
|
16
|
-
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
|
|
17
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Helpers
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
type TableCardCreateConfig = ResourceFormConfig;
|
|
24
|
-
type TableCardReadConfig = TableConfig;
|
|
25
|
-
type TableCardEditConfig = ResourceFormConfig & {
|
|
26
|
-
editButtonSettings?: Partial<ButtonSettings>;
|
|
27
|
-
};
|
|
28
|
-
type TableCardDeleteConfig = DeleteResourceConfirmationConfig & {
|
|
29
|
-
deleteButtonSettings?: Partial<ButtonSettings>;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
type Comp = DeclarativeTableCard<GenericResource>;
|
|
33
|
-
type Fixture = ComponentFixture<Comp>;
|
|
34
|
-
|
|
35
|
-
const COLUMNS: TableFieldDefinition[] = [
|
|
36
|
-
{ label: 'Name', property: 'metadata.name' },
|
|
37
|
-
{ label: 'Namespace', property: 'metadata.namespace' },
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
const READ_CONFIG: TableCardReadConfig = {
|
|
41
|
-
fields: COLUMNS,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const RESOURCES: GenericResource[] = [
|
|
45
|
-
{ id: '1', metadata: { name: 'pod-alpha', namespace: 'default' } },
|
|
46
|
-
{ id: '2', metadata: { name: 'pod-beta', namespace: 'kube-system' } },
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
const FORM_FIELDS: FormFieldDefinition[] = [
|
|
50
|
-
{ name: 'metadata.name', label: 'Name', required: true },
|
|
51
|
-
{ name: 'metadata.namespace', label: 'Namespace' },
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
const CREATE_CONFIG: TableCardCreateConfig = {
|
|
55
|
-
fields: FORM_FIELDS,
|
|
56
|
-
title: 'Create Resource',
|
|
57
|
-
confirmLabel: 'Create',
|
|
58
|
-
cancelLabel: 'Cancel',
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const EDIT_CONFIG: TableCardEditConfig = {
|
|
62
|
-
fields: [
|
|
63
|
-
{ name: 'metadata.name', label: 'Name', required: true, disabled: true },
|
|
64
|
-
{ name: 'metadata.namespace', label: 'Namespace' },
|
|
65
|
-
],
|
|
66
|
-
title: 'Edit Resource',
|
|
67
|
-
confirmLabel: 'Save',
|
|
68
|
-
cancelLabel: 'Cancel',
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const DELETE_CONFIG: TableCardDeleteConfig = {
|
|
72
|
-
title: 'Confirm Delete',
|
|
73
|
-
message: 'This action cannot be undone.',
|
|
74
|
-
confirmLabel: 'Delete',
|
|
75
|
-
cancelLabel: 'Cancel',
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
function makeEvent(
|
|
79
|
-
action: string,
|
|
80
|
-
resource?: GenericResource,
|
|
81
|
-
): ValueCellButtonClickEvent<GenericResource> {
|
|
82
|
-
return {
|
|
83
|
-
event: new MouseEvent('click'),
|
|
84
|
-
field: {
|
|
85
|
-
label: '',
|
|
86
|
-
uiSettings: {
|
|
87
|
-
displayAs: 'button',
|
|
88
|
-
buttonSettings: { action, icon: action },
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
resource,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function setup(
|
|
96
|
-
opts: {
|
|
97
|
-
headerTooltip?: string;
|
|
98
|
-
readConfig?: TableCardReadConfig;
|
|
99
|
-
resources?: GenericResource[];
|
|
100
|
-
header?: string;
|
|
101
|
-
createConfig?: TableCardCreateConfig;
|
|
102
|
-
editConfig?: TableCardEditConfig;
|
|
103
|
-
deleteConfig?: TableCardDeleteConfig;
|
|
104
|
-
createFormState?: TableCardFormState;
|
|
105
|
-
editFormState?: TableCardFormState;
|
|
106
|
-
} = {},
|
|
107
|
-
): { fixture: Fixture; component: Comp } {
|
|
108
|
-
const fixture: Fixture = TestBed.createComponent(
|
|
109
|
-
DeclarativeTableCard as unknown as typeof DeclarativeTableCard<GenericResource>,
|
|
110
|
-
);
|
|
111
|
-
const component = fixture.componentInstance as Comp;
|
|
112
|
-
|
|
113
|
-
const config: TableCardConfig = {
|
|
114
|
-
header: opts.header || '',
|
|
115
|
-
headerTooltip: opts.headerTooltip,
|
|
116
|
-
tableConfig: opts.readConfig ?? READ_CONFIG,
|
|
117
|
-
createResourceFormConfig: opts.createConfig,
|
|
118
|
-
editResourceFormConfig: opts.editConfig,
|
|
119
|
-
deleteResourceConfirmationConfig: opts.deleteConfig,
|
|
120
|
-
buttonSettings: {
|
|
121
|
-
editButton: opts.editConfig?.editButtonSettings,
|
|
122
|
-
deleteButton: opts.deleteConfig?.deleteButtonSettings,
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
fixture.componentRef.setInput('config', config);
|
|
127
|
-
fixture.componentRef.setInput('resources', opts.resources ?? RESOURCES);
|
|
128
|
-
fixture.componentRef.setInput('createFormState', opts.createFormState ?? {});
|
|
129
|
-
fixture.componentRef.setInput('editFormState', opts.editFormState ?? {});
|
|
130
|
-
|
|
131
|
-
fixture.detectChanges();
|
|
132
|
-
return { fixture, component };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Tests
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
|
|
139
|
-
describe('DeclarativeTableCard', () => {
|
|
140
|
-
beforeEach(async () => {
|
|
141
|
-
await TestBed.configureTestingModule({
|
|
142
|
-
imports: [
|
|
143
|
-
DeclarativeTableCard as unknown as typeof DeclarativeTableCard<GenericResource>,
|
|
144
|
-
],
|
|
145
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
|
|
146
|
-
}).compileComponents();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// -------------------------------------------------------------------------
|
|
150
|
-
// 1. Component creation
|
|
151
|
-
// -------------------------------------------------------------------------
|
|
152
|
-
|
|
153
|
-
it('should create', () => {
|
|
154
|
-
const { component } = setup();
|
|
155
|
-
expect(component).toBeTruthy();
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// -------------------------------------------------------------------------
|
|
159
|
-
// 2. DOM: mfp-declarative-table rendered
|
|
160
|
-
// -------------------------------------------------------------------------
|
|
161
|
-
|
|
162
|
-
describe('DOM: mfp-declarative-table', () => {
|
|
163
|
-
it('renders mfp-declarative-table in the host element', () => {
|
|
164
|
-
const { fixture } = setup();
|
|
165
|
-
const root: ShadowRoot | HTMLElement =
|
|
166
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
167
|
-
expect(root.querySelector('mfp-declarative-table')).not.toBeNull();
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// -------------------------------------------------------------------------
|
|
172
|
-
// 3. header input
|
|
173
|
-
// -------------------------------------------------------------------------
|
|
174
|
-
|
|
175
|
-
describe('header input', () => {
|
|
176
|
-
it('renders the header title when header is provided', () => {
|
|
177
|
-
const { fixture } = setup({ header: 'My Pods' });
|
|
178
|
-
const root: ShadowRoot | HTMLElement =
|
|
179
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
180
|
-
const title = root.querySelector('.card__title');
|
|
181
|
-
expect(title).not.toBeNull();
|
|
182
|
-
expect(title?.textContent?.trim()).toBe('My Pods');
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// -------------------------------------------------------------------------
|
|
187
|
-
// 4. headerTooltip input
|
|
188
|
-
// -------------------------------------------------------------------------
|
|
189
|
-
|
|
190
|
-
describe('headerTooltip input', () => {
|
|
191
|
-
it('renders info icon when headerTooltip is provided', () => {
|
|
192
|
-
const { fixture } = setup({
|
|
193
|
-
header: 'My Pods',
|
|
194
|
-
headerTooltip: 'Some tooltip',
|
|
195
|
-
});
|
|
196
|
-
fixture.detectChanges();
|
|
197
|
-
const root: ShadowRoot | HTMLElement =
|
|
198
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
199
|
-
const icon = root.querySelector('ui5-icon[name="hint"]');
|
|
200
|
-
expect(icon).not.toBeNull();
|
|
201
|
-
expect(icon?.getAttribute('accessible-name')).toBe('Some tooltip');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('does not render info icon when headerTooltip is not provided', () => {
|
|
205
|
-
const { fixture } = setup({ headerTooltip: undefined });
|
|
206
|
-
const root: ShadowRoot | HTMLElement =
|
|
207
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
208
|
-
expect(root.querySelector('ui5-icon[name="hint"]')).toBeNull();
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// -------------------------------------------------------------------------
|
|
213
|
-
// 5. Search behaviour
|
|
214
|
-
// -------------------------------------------------------------------------
|
|
215
|
-
|
|
216
|
-
describe('search', () => {
|
|
217
|
-
it('searchExpanded starts as false', () => {
|
|
218
|
-
const { component } = setup();
|
|
219
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
220
|
-
expect((component as any).searchExpanded()).toBe(false);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('toggleSearch() sets searchExpanded to true on first call', () => {
|
|
224
|
-
const { component } = setup();
|
|
225
|
-
component.toggleSearch();
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
227
|
-
expect((component as any).searchExpanded()).toBe(true);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it('toggleSearch() starts collapsing on second call when already expanded', () => {
|
|
231
|
-
const { component } = setup();
|
|
232
|
-
component.toggleSearch(); // expand
|
|
233
|
-
component.toggleSearch(); // collapse
|
|
234
|
-
// searchCollapsing should be set; searchExpanded still true until animation ends
|
|
235
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
236
|
-
expect((component as any).searchCollapsing()).toBe(true);
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it('onSearchBlur() collapses search when value is empty', () => {
|
|
240
|
-
const { component } = setup();
|
|
241
|
-
component.toggleSearch();
|
|
242
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
243
|
-
(component as any).searchControl.setValue('');
|
|
244
|
-
component.onSearchBlur();
|
|
245
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
|
-
expect((component as any).searchCollapsing()).toBe(true);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('onSearchBlur() does not collapse when value is non-empty', () => {
|
|
250
|
-
const { component } = setup();
|
|
251
|
-
component.toggleSearch();
|
|
252
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
|
-
(component as any).searchControl.setValue('abc');
|
|
254
|
-
component.onSearchBlur();
|
|
255
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
256
|
-
expect((component as any).searchCollapsing()).toBe(false);
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it('onSearchAnimationEnd() resets search state after collapse animation', () => {
|
|
260
|
-
const { component } = setup();
|
|
261
|
-
component.toggleSearch(); // expand
|
|
262
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
263
|
-
(component as any).searchControl.setValue('query');
|
|
264
|
-
component.toggleSearch(); // start collapsing
|
|
265
|
-
component.onSearchAnimationEnd();
|
|
266
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
267
|
-
expect((component as any).searchCollapsing()).toBe(false);
|
|
268
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
269
|
-
expect((component as any).searchExpanded()).toBe(false);
|
|
270
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
271
|
-
expect((component as any).searchControl.value).toBe('');
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it('onSearchAnimationEnd() does nothing when not collapsing', () => {
|
|
275
|
-
const { component } = setup();
|
|
276
|
-
component.toggleSearch();
|
|
277
|
-
// Not in collapsing state — should be a no-op
|
|
278
|
-
component.onSearchAnimationEnd();
|
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
280
|
-
expect((component as any).searchExpanded()).toBe(true);
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// -------------------------------------------------------------------------
|
|
285
|
-
// 6. Create button visibility
|
|
286
|
-
// -------------------------------------------------------------------------
|
|
287
|
-
|
|
288
|
-
describe('create button', () => {
|
|
289
|
-
it('create button is absent when createConfig is not provided', () => {
|
|
290
|
-
const { fixture } = setup();
|
|
291
|
-
const root: ShadowRoot | HTMLElement =
|
|
292
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
293
|
-
expect(root.querySelector('.card__create-btn')).toBeNull();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('create button is present when createConfig is provided', () => {
|
|
297
|
-
const { fixture } = setup({ createConfig: CREATE_CONFIG });
|
|
298
|
-
const root: ShadowRoot | HTMLElement =
|
|
299
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
300
|
-
expect(root.querySelector('.card__create-btn')).not.toBeNull();
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
// -------------------------------------------------------------------------
|
|
305
|
-
// 7. effectiveColumns() computed
|
|
306
|
-
// -------------------------------------------------------------------------
|
|
307
|
-
|
|
308
|
-
describe('effectiveColumns()', () => {
|
|
309
|
-
it('returns only readConfig.fields when no edit or delete config is set', () => {
|
|
310
|
-
const { component } = setup();
|
|
311
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
312
|
-
const cols = (component as any).effectiveColumns();
|
|
313
|
-
expect(cols).toHaveLength(COLUMNS.length);
|
|
314
|
-
expect(cols).toEqual(COLUMNS);
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('adds an edit action column when editConfig is provided', () => {
|
|
318
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
319
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
320
|
-
const cols = (component as any).effectiveColumns();
|
|
321
|
-
expect(cols).toHaveLength(COLUMNS.length + 1);
|
|
322
|
-
const editCol = cols.find(
|
|
323
|
-
(c: TableFieldDefinition) =>
|
|
324
|
-
c.uiSettings?.buttonSettings?.action === 'edit',
|
|
325
|
-
);
|
|
326
|
-
expect(editCol).toBeDefined();
|
|
327
|
-
expect(editCol.uiSettings.buttonSettings.icon).toBe('edit');
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('adds a delete action column when deleteConfig is provided', () => {
|
|
331
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
332
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
333
|
-
const cols = (component as any).effectiveColumns();
|
|
334
|
-
expect(cols).toHaveLength(COLUMNS.length + 1);
|
|
335
|
-
const deleteCol = cols.find(
|
|
336
|
-
(c: TableFieldDefinition) =>
|
|
337
|
-
c.uiSettings?.buttonSettings?.action === 'delete',
|
|
338
|
-
);
|
|
339
|
-
expect(deleteCol).toBeDefined();
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('adds both edit and delete columns when both configs are provided', () => {
|
|
343
|
-
const { component } = setup({
|
|
344
|
-
editConfig: EDIT_CONFIG,
|
|
345
|
-
deleteConfig: DELETE_CONFIG,
|
|
346
|
-
});
|
|
347
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
348
|
-
const cols = (component as any).effectiveColumns();
|
|
349
|
-
expect(cols).toHaveLength(COLUMNS.length + 2);
|
|
350
|
-
const editCol = cols.find(
|
|
351
|
-
(c: TableFieldDefinition) =>
|
|
352
|
-
c.uiSettings?.buttonSettings?.action === 'edit',
|
|
353
|
-
);
|
|
354
|
-
const deleteCol = cols.find(
|
|
355
|
-
(c: TableFieldDefinition) =>
|
|
356
|
-
c.uiSettings?.buttonSettings?.action === 'delete',
|
|
357
|
-
);
|
|
358
|
-
expect(editCol).toBeDefined();
|
|
359
|
-
expect(deleteCol).toBeDefined();
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('delete column uses "decline" icon by default', () => {
|
|
363
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
364
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
365
|
-
const cols = (component as any).effectiveColumns();
|
|
366
|
-
const deleteCol = cols.find(
|
|
367
|
-
(c: TableFieldDefinition) =>
|
|
368
|
-
c.uiSettings?.buttonSettings?.action === 'delete',
|
|
369
|
-
);
|
|
370
|
-
expect(deleteCol.uiSettings.buttonSettings.icon).toBe('decline');
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
it('respects custom icon from editConfig.editButtonSettings', () => {
|
|
374
|
-
const customEditConfig: TableCardEditConfig = {
|
|
375
|
-
...EDIT_CONFIG,
|
|
376
|
-
editButtonSettings: { icon: 'pen-tool' },
|
|
377
|
-
};
|
|
378
|
-
const { component } = setup({ editConfig: customEditConfig });
|
|
379
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
380
|
-
const cols = (component as any).effectiveColumns();
|
|
381
|
-
const editCol = cols.find(
|
|
382
|
-
(c: TableFieldDefinition) =>
|
|
383
|
-
c.uiSettings?.buttonSettings?.action === 'edit',
|
|
384
|
-
);
|
|
385
|
-
expect(editCol.uiSettings.buttonSettings.icon).toBe('pen-tool');
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
it('respects custom icon from deleteConfig.deleteButtonSettings', () => {
|
|
389
|
-
const customDeleteConfig: TableCardDeleteConfig = {
|
|
390
|
-
...DELETE_CONFIG,
|
|
391
|
-
deleteButtonSettings: { icon: 'trash' },
|
|
392
|
-
};
|
|
393
|
-
const { component } = setup({ deleteConfig: customDeleteConfig });
|
|
394
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
395
|
-
const cols = (component as any).effectiveColumns();
|
|
396
|
-
const deleteCol = cols.find(
|
|
397
|
-
(c: TableFieldDefinition) =>
|
|
398
|
-
c.uiSettings?.buttonSettings?.action === 'delete',
|
|
399
|
-
);
|
|
400
|
-
expect(deleteCol.uiSettings.buttonSettings.icon).toBe('trash');
|
|
401
|
-
});
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
// -------------------------------------------------------------------------
|
|
405
|
-
// 8. editInitialValue() computed
|
|
406
|
-
// -------------------------------------------------------------------------
|
|
407
|
-
|
|
408
|
-
describe('editInitialValue()', () => {
|
|
409
|
-
it('returns empty object when pendingResource is null', () => {
|
|
410
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
411
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
412
|
-
expect((component as any).editInitialValue()).toEqual({});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
it('returns empty object when editConfig is not set', () => {
|
|
416
|
-
const { component } = setup();
|
|
417
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
418
|
-
expect((component as any).editInitialValue()).toEqual({});
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
it('builds initial values from pendingResource fields when editConfig is set', () => {
|
|
422
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
423
|
-
const resource = RESOURCES[0];
|
|
424
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
425
|
-
(component as any).pendingResource.set(resource);
|
|
426
|
-
|
|
427
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
428
|
-
const values = (component as any).editInitialValue();
|
|
429
|
-
expect(values['metadata.name']).toBe('pod-alpha');
|
|
430
|
-
expect(values['metadata.namespace']).toBe('default');
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
// -------------------------------------------------------------------------
|
|
435
|
-
// 9. onButtonClick()
|
|
436
|
-
// -------------------------------------------------------------------------
|
|
437
|
-
|
|
438
|
-
describe('onButtonClick()', () => {
|
|
439
|
-
it('intercepts action="edit": sets pendingResource and opens editDialogOpen', () => {
|
|
440
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
441
|
-
const resource = RESOURCES[0];
|
|
442
|
-
component.onButtonClick(makeEvent('edit', resource));
|
|
443
|
-
|
|
444
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
445
|
-
expect((component as any).pendingResource()).toBe(resource);
|
|
446
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
447
|
-
expect((component as any).editDialogOpen()).toBe(true);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
it('intercepts action="edit": does not emit actionButtonClick', () => {
|
|
451
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
452
|
-
const emitted: unknown[] = [];
|
|
453
|
-
component.actionButtonClick.subscribe((e) => emitted.push(e));
|
|
454
|
-
component.onButtonClick(makeEvent('edit', RESOURCES[0]));
|
|
455
|
-
expect(emitted).toHaveLength(0);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('intercepts action="delete": sets pendingResource and opens deleteDialogOpen', () => {
|
|
459
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
460
|
-
const resource = RESOURCES[1];
|
|
461
|
-
component.onButtonClick(makeEvent('delete', resource));
|
|
462
|
-
|
|
463
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
464
|
-
expect((component as any).pendingResource()).toBe(resource);
|
|
465
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
466
|
-
expect((component as any).deleteDialogOpen()).toBe(true);
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
it('intercepts action="delete": does not emit actionButtonClick', () => {
|
|
470
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
471
|
-
const emitted: unknown[] = [];
|
|
472
|
-
component.actionButtonClick.subscribe((e) => emitted.push(e));
|
|
473
|
-
component.onButtonClick(makeEvent('delete', RESOURCES[0]));
|
|
474
|
-
expect(emitted).toHaveLength(0);
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
it('forwards other actions via actionButtonClick output', () => {
|
|
478
|
-
const { component } = setup();
|
|
479
|
-
const emitted: ValueCellButtonClickEvent<GenericResource>[] = [];
|
|
480
|
-
component.actionButtonClick.subscribe((e) => emitted.push(e));
|
|
481
|
-
|
|
482
|
-
const event = makeEvent('navigate', RESOURCES[0]);
|
|
483
|
-
component.onButtonClick(event);
|
|
484
|
-
|
|
485
|
-
expect(emitted).toHaveLength(1);
|
|
486
|
-
expect(emitted[0]).toBe(event);
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
it('forwards action="edit" without a resource via actionButtonClick', () => {
|
|
490
|
-
const { component } = setup();
|
|
491
|
-
const emitted: unknown[] = [];
|
|
492
|
-
component.actionButtonClick.subscribe((e) => emitted.push(e));
|
|
493
|
-
component.onButtonClick(makeEvent('edit', undefined));
|
|
494
|
-
expect(emitted).toHaveLength(1);
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
it('forwards action="delete" without a resource via actionButtonClick', () => {
|
|
498
|
-
const { component } = setup();
|
|
499
|
-
const emitted: unknown[] = [];
|
|
500
|
-
component.actionButtonClick.subscribe((e) => emitted.push(e));
|
|
501
|
-
component.onButtonClick(makeEvent('delete', undefined));
|
|
502
|
-
expect(emitted).toHaveLength(1);
|
|
503
|
-
});
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
// -------------------------------------------------------------------------
|
|
507
|
-
// 10. form state and submit flow
|
|
508
|
-
// -------------------------------------------------------------------------
|
|
509
|
-
|
|
510
|
-
describe('form state and submit flow', () => {
|
|
511
|
-
const fieldChange: FormFieldChangeEvent = {
|
|
512
|
-
fieldProperty: 'metadata.name',
|
|
513
|
-
value: 'new-pod',
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
it('emits createFieldChange on field change', () => {
|
|
517
|
-
const { component } = setup({ createConfig: CREATE_CONFIG });
|
|
518
|
-
const emitted: FormFieldChangeEvent[] = [];
|
|
519
|
-
component.createFieldChange.subscribe((event) => emitted.push(event));
|
|
520
|
-
|
|
521
|
-
component.onCreateFieldChange(fieldChange);
|
|
522
|
-
|
|
523
|
-
expect(emitted).toEqual([fieldChange]);
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
it('emits editFieldChange with pending resource', () => {
|
|
527
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
528
|
-
const resource = RESOURCES[0];
|
|
529
|
-
const emitted: {
|
|
530
|
-
resource: GenericResource;
|
|
531
|
-
formChangeEvent: FormFieldChangeEvent;
|
|
532
|
-
}[] = [];
|
|
533
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
534
|
-
(component as any).pendingResource.set(resource);
|
|
535
|
-
component.editFieldChange.subscribe((event) => emitted.push(event));
|
|
536
|
-
|
|
537
|
-
component.onEditFieldChange(fieldChange);
|
|
538
|
-
|
|
539
|
-
expect(emitted).toEqual([{ resource, formChangeEvent: fieldChange }]);
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
it('does not emit editFieldChange without pending resource', () => {
|
|
543
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
544
|
-
const emitted: unknown[] = [];
|
|
545
|
-
component.editFieldChange.subscribe((event) => emitted.push(event));
|
|
546
|
-
|
|
547
|
-
component.onEditFieldChange(fieldChange);
|
|
548
|
-
|
|
549
|
-
expect(emitted).toHaveLength(0);
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
it('emits createSubmit and leaves create dialog open', () => {
|
|
553
|
-
const { component } = setup({ createConfig: CREATE_CONFIG });
|
|
554
|
-
const value = { metadata: { name: 'new-pod' } };
|
|
555
|
-
const emitted: Record<string, unknown>[] = [];
|
|
556
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
557
|
-
(component as any).createDialogOpen.set(true);
|
|
558
|
-
component.createSubmit.subscribe((event) => emitted.push(event));
|
|
559
|
-
|
|
560
|
-
component.onCreateSubmit(value);
|
|
561
|
-
|
|
562
|
-
expect(emitted).toEqual([value]);
|
|
563
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
564
|
-
expect((component as any).createDialogOpen()).toBe(true);
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
it('emits editSubmit with resource and leaves edit dialog open', () => {
|
|
568
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
569
|
-
const resource = RESOURCES[0];
|
|
570
|
-
const value = { metadata: { namespace: 'staging' } };
|
|
571
|
-
const emitted: {
|
|
572
|
-
resource: GenericResource;
|
|
573
|
-
value: Record<string, unknown>;
|
|
574
|
-
}[] = [];
|
|
575
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
576
|
-
(component as any).pendingResource.set(resource);
|
|
577
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
578
|
-
(component as any).editDialogOpen.set(true);
|
|
579
|
-
component.editSubmit.subscribe((event) => emitted.push(event));
|
|
580
|
-
|
|
581
|
-
component.onEditSubmit(value);
|
|
582
|
-
|
|
583
|
-
expect(emitted).toEqual([{ resource, value }]);
|
|
584
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
585
|
-
expect((component as any).editDialogOpen()).toBe(true);
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
it('does not emit editSubmit without pending resource', () => {
|
|
589
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
590
|
-
const emitted: unknown[] = [];
|
|
591
|
-
component.editSubmit.subscribe((event) => emitted.push(event));
|
|
592
|
-
|
|
593
|
-
component.onEditSubmit({ metadata: { namespace: 'staging' } });
|
|
594
|
-
|
|
595
|
-
expect(emitted).toHaveLength(0);
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
it('emits deleteSubmit and leaves delete dialog open', () => {
|
|
599
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
600
|
-
const resource = RESOURCES[0];
|
|
601
|
-
const emitted: GenericResource[] = [];
|
|
602
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
603
|
-
(component as any).pendingResource.set(resource);
|
|
604
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
605
|
-
(component as any).deleteDialogOpen.set(true);
|
|
606
|
-
component.deleteSubmit.subscribe((event) => emitted.push(event));
|
|
607
|
-
|
|
608
|
-
component.onDeleteSubmit();
|
|
609
|
-
|
|
610
|
-
expect(emitted).toEqual([resource]);
|
|
611
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
612
|
-
expect((component as any).deleteDialogOpen()).toBe(true);
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
// -------------------------------------------------------------------------
|
|
617
|
-
// 11. close methods
|
|
618
|
-
// -------------------------------------------------------------------------
|
|
619
|
-
|
|
620
|
-
describe('close methods', () => {
|
|
621
|
-
it('closeCreateDialog() closes the create dialog', () => {
|
|
622
|
-
const { component } = setup({ createConfig: CREATE_CONFIG });
|
|
623
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
624
|
-
(component as any).createDialogOpen.set(true);
|
|
625
|
-
|
|
626
|
-
component.closeCreateDialog();
|
|
627
|
-
|
|
628
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
629
|
-
expect((component as any).createDialogOpen()).toBe(false);
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
it('closeEditDialog() closes the edit dialog', () => {
|
|
633
|
-
const { component } = setup({ editConfig: EDIT_CONFIG });
|
|
634
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
635
|
-
(component as any).editDialogOpen.set(true);
|
|
636
|
-
|
|
637
|
-
component.closeEditDialog();
|
|
638
|
-
|
|
639
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
640
|
-
expect((component as any).editDialogOpen()).toBe(false);
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
it('closeDeleteDialog() closes the delete dialog', () => {
|
|
644
|
-
const { component } = setup({ deleteConfig: DELETE_CONFIG });
|
|
645
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
646
|
-
(component as any).deleteDialogOpen.set(true);
|
|
647
|
-
|
|
648
|
-
component.closeDeleteDialog();
|
|
649
|
-
|
|
650
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
651
|
-
expect((component as any).deleteDialogOpen()).toBe(false);
|
|
652
|
-
});
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
// -------------------------------------------------------------------------
|
|
656
|
-
// 12. runtime form state
|
|
657
|
-
// -------------------------------------------------------------------------
|
|
658
|
-
|
|
659
|
-
describe('runtime form state', () => {
|
|
660
|
-
it('disables the create submit button when fieldErrors has errors', () => {
|
|
661
|
-
const { fixture, component } = setup({
|
|
662
|
-
createConfig: CREATE_CONFIG,
|
|
663
|
-
createFormState: {
|
|
664
|
-
fieldErrors: { 'metadata.name': 'required' },
|
|
665
|
-
},
|
|
666
|
-
});
|
|
667
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
668
|
-
(component as any).createDialogOpen.set(true);
|
|
669
|
-
fixture.detectChanges();
|
|
670
|
-
|
|
671
|
-
const root: ShadowRoot | HTMLElement =
|
|
672
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
673
|
-
const submitButton = root.querySelector(
|
|
674
|
-
'.dialog__footer ui5-button[design="Emphasized"]',
|
|
675
|
-
) as HTMLElement & { disabled: boolean };
|
|
676
|
-
|
|
677
|
-
expect(submitButton.disabled).toBe(true);
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
it('enables the create submit button when fieldErrors is empty', () => {
|
|
681
|
-
const { fixture, component } = setup({
|
|
682
|
-
createConfig: CREATE_CONFIG,
|
|
683
|
-
createFormState: { fieldErrors: {} },
|
|
684
|
-
});
|
|
685
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
686
|
-
(component as any).createDialogOpen.set(true);
|
|
687
|
-
fixture.detectChanges();
|
|
688
|
-
|
|
689
|
-
const root: ShadowRoot | HTMLElement =
|
|
690
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
691
|
-
const submitButton = root.querySelector(
|
|
692
|
-
'.dialog__footer ui5-button[design="Emphasized"]',
|
|
693
|
-
) as HTMLElement & { disabled: boolean };
|
|
694
|
-
|
|
695
|
-
expect(submitButton.disabled).toBe(false);
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
it('disables the edit submit button when fieldErrors has errors', () => {
|
|
699
|
-
const { fixture, component } = setup({
|
|
700
|
-
editConfig: EDIT_CONFIG,
|
|
701
|
-
editFormState: {
|
|
702
|
-
fieldErrors: { 'metadata.name': 'required' },
|
|
703
|
-
},
|
|
704
|
-
});
|
|
705
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
706
|
-
(component as any).editDialogOpen.set(true);
|
|
707
|
-
fixture.detectChanges();
|
|
708
|
-
|
|
709
|
-
const root: ShadowRoot | HTMLElement =
|
|
710
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
711
|
-
const submitButton = root.querySelector(
|
|
712
|
-
'.dialog__footer ui5-button[design="Emphasized"]',
|
|
713
|
-
) as HTMLElement & { disabled: boolean };
|
|
714
|
-
|
|
715
|
-
expect(submitButton.disabled).toBe(true);
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
it('enables the edit submit button when fieldErrors is empty', () => {
|
|
719
|
-
const { fixture, component } = setup({
|
|
720
|
-
editConfig: EDIT_CONFIG,
|
|
721
|
-
editFormState: { fieldErrors: {} },
|
|
722
|
-
});
|
|
723
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
724
|
-
(component as any).editDialogOpen.set(true);
|
|
725
|
-
fixture.detectChanges();
|
|
726
|
-
|
|
727
|
-
const root: ShadowRoot | HTMLElement =
|
|
728
|
-
fixture.nativeElement.shadowRoot ?? fixture.nativeElement;
|
|
729
|
-
const submitButton = root.querySelector(
|
|
730
|
-
'.dialog__footer ui5-button[design="Emphasized"]',
|
|
731
|
-
) as HTMLElement & { disabled: boolean };
|
|
732
|
-
|
|
733
|
-
expect(submitButton.disabled).toBe(false);
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
// -------------------------------------------------------------------------
|
|
738
|
-
// 14. Pass-through outputs
|
|
739
|
-
// -------------------------------------------------------------------------
|
|
740
|
-
|
|
741
|
-
describe('pass-through outputs', () => {
|
|
742
|
-
it('exposes tableRowClicked output', () => {
|
|
743
|
-
const { component } = setup();
|
|
744
|
-
expect(typeof component.tableRowClicked.emit).toBe('function');
|
|
745
|
-
expect(typeof component.tableRowClicked.subscribe).toBe('function');
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
it('exposes loadMoreResources output', () => {
|
|
749
|
-
const { component } = setup();
|
|
750
|
-
expect(typeof component.loadMoreResources.emit).toBe('function');
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
it('exposes paginationLimitChanged output', () => {
|
|
754
|
-
const { component } = setup();
|
|
755
|
-
expect(typeof component.paginationLimitChanged.emit).toBe('function');
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
it('exposes searchChanged output', () => {
|
|
759
|
-
const { component } = setup();
|
|
760
|
-
expect(typeof component.searchChanged.emit).toBe('function');
|
|
761
|
-
});
|
|
762
|
-
});
|
|
763
|
-
|
|
764
|
-
// -------------------------------------------------------------------------
|
|
765
|
-
// 15. readConfig pagination pass-through
|
|
766
|
-
// -------------------------------------------------------------------------
|
|
767
|
-
|
|
768
|
-
describe('readConfig pagination', () => {
|
|
769
|
-
it('effectiveColumns() uses fields from readConfig', () => {
|
|
770
|
-
const customColumns: TableFieldDefinition[] = [
|
|
771
|
-
{ label: 'Phase', property: 'status.phase' },
|
|
772
|
-
];
|
|
773
|
-
const { component } = setup({
|
|
774
|
-
readConfig: {
|
|
775
|
-
fields: customColumns,
|
|
776
|
-
totalItemsCount: 42,
|
|
777
|
-
paginationLimit: 10,
|
|
778
|
-
hasMore: true,
|
|
779
|
-
},
|
|
780
|
-
});
|
|
781
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
782
|
-
const cols = (component as any).effectiveColumns();
|
|
783
|
-
expect(cols[0]).toEqual(customColumns[0]);
|
|
784
|
-
});
|
|
785
|
-
});
|
|
786
|
-
});
|