Skip to content

Commit bd11f16

Browse files
committed
refactor: extract testing utility files
4 parents 1f755a1 + b14dfc9 + 0c2bb47 + 21ab5c8 commit bd11f16

File tree

7 files changed

+510
-94
lines changed

7 files changed

+510
-94
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
import { HttpTestingController } from '@angular/common/http/testing';
2+
import { DebugElement } from '@angular/core';
3+
import {
4+
discardPeriodicTasks,
5+
flush,
6+
tick,
7+
} from '@angular/core/testing';
8+
import { By } from '@angular/platform-browser';
9+
10+
import { EventGenerator } from '../utilities/event-generator';
11+
import {
12+
FixtureTestingUtils,
13+
IStubEndpoint,
14+
} from '../utilities/fixture-testing-utils';
15+
16+
const selectors = {
17+
grid: 'ui-grid',
18+
inlineMenu: '[data-cy="grid-action-menu"]',
19+
};
20+
21+
export class GridUtils<T> {
22+
constructor(
23+
private _utils: FixtureTestingUtils<T>,
24+
) { }
25+
26+
flush = (stub: IStubEndpoint, httpClient: HttpTestingController) => {
27+
this._utils.fixture.detectChanges();
28+
tick(500);
29+
this._utils.fixture.detectChanges();
30+
31+
this._utils.expectAndFlush(stub, httpClient);
32+
this._utils.fixture.detectChanges();
33+
34+
flush();
35+
discardPeriodicTasks();
36+
};
37+
38+
/**
39+
*
40+
* @param rowNumber The Grid row
41+
*
42+
* ---
43+
*
44+
* @param startColumn The beginning of the specified portion of the array.
45+
* @param endColumn The end of the specified portion of the array. This is exclusive of the element at the index 'end'.
46+
*/
47+
getCellsText = (
48+
rowNumber: number,
49+
{
50+
startColumn,
51+
endColumn,
52+
gridSelector,
53+
debugEl,
54+
getter = (cellEl: DebugElement) => cellEl.nativeElement.innerText as string,
55+
}: {
56+
startColumn?: number;
57+
endColumn?: number;
58+
gridSelector?: string;
59+
debugEl?: DebugElement;
60+
getter?: (cellEl: DebugElement, index: number, array: DebugElement[]) => string;
61+
} = {
62+
getter: (cellEl: DebugElement) => cellEl.nativeElement.innerText as string,
63+
},
64+
) => {
65+
const rowEl = this._utils.getDebugElement(`${gridSelector ?? selectors.grid} [data-row-index="${rowNumber - 1}"]`, debugEl);
66+
return rowEl
67+
.queryAll(By.css('.ui-grid-cell'))
68+
.slice(startColumn, endColumn)
69+
.map(getter);
70+
};
71+
72+
getHeaders = (gridSelector = selectors.grid, debugEl = this._utils.fixture.debugElement) => this._utils.getAllDebugElements(`${gridSelector} .ui-grid-header-cell`, debugEl)
73+
.filter(el => this._utils.getDebugElement('.ui-grid-header-title:not(ui-grid ui-grid .ui-grid-header-title)', el));
74+
75+
getColumnsProperties = (gridSelector = selectors.grid, debugEl = this._utils.fixture.debugElement) => this._utils.getAllDebugElements(`${gridSelector} .ui-grid-header-cell`, debugEl)
76+
.filter(el => this._utils.getDebugElement('.ui-grid-header-title', el))
77+
.map(el => el.attributes['data-property']);
78+
79+
getHeaderCell = (property: string, debugEl = this._utils.fixture.debugElement) =>
80+
this._utils.getDebugElement(`.ui-grid-header-cell[data-property="${property}"]`, debugEl);
81+
82+
getHeaderTitle = (property: string, debugEl = this._utils.fixture.debugElement) =>
83+
this.getHeaderCell(property, debugEl).query(By.css('.ui-grid-header-title'));
84+
85+
isSortable = (property: string, debugEl = this._utils.fixture.debugElement) => {
86+
const headerCell = this.getHeaderCell(property, debugEl);
87+
88+
return !!headerCell.nativeElement.classList.contains('ui-grid-header-cell-sortable');
89+
};
90+
91+
getRowItem = (
92+
rowNumber: number,
93+
selector: string,
94+
{
95+
gridSelector,
96+
debugEl,
97+
}: {
98+
gridSelector?: string;
99+
debugEl?: DebugElement;
100+
} = {}) => this._utils.getDebugElement(
101+
`${gridSelector ?? selectors.grid} [data-row-index="${rowNumber}"] ${selector}`,
102+
debugEl ?? this._utils.fixture.debugElement,
103+
);
104+
105+
getMenuDictionary = (
106+
rowNumber: number,
107+
cfg: {
108+
gridSelector?: string;
109+
menu?: string;
110+
debugEl?: DebugElement;
111+
} = {},
112+
) => {
113+
const menuItems = this.getMenuItems(rowNumber, cfg);
114+
return menuItems.reduce((acc, step) => ({
115+
...acc,
116+
[step.text]: step,
117+
}), {} as Record<string, { text: string; href: string | undefined }>);
118+
};
119+
120+
getMenuItems = (
121+
rowNumber: number,
122+
{
123+
gridSelector,
124+
menu,
125+
debugEl,
126+
}: {
127+
gridSelector?: string;
128+
menu?: string;
129+
debugEl?: DebugElement;
130+
} = {},
131+
) => {
132+
gridSelector = gridSelector ?? selectors.grid;
133+
menu = menu ?? selectors.inlineMenu;
134+
135+
this._utils.click(`${gridSelector} [data-row-index="${rowNumber}"] ${menu}`, debugEl);
136+
this._utils.fixture.detectChanges();
137+
const nodes = this._utils.getAllDebugElements('.cdk-overlay-container .mat-menu-item', debugEl);
138+
139+
return nodes.map(item => ({
140+
text: item.query(By.css('span')).nativeElement.innerText,
141+
href: (item.nativeElement as HTMLAnchorElement).href as string | undefined,
142+
node: item.nativeElement,
143+
}));
144+
};
145+
146+
clickMenuItem = (
147+
rowIndex: number,
148+
actionSelector: string,
149+
{
150+
gridSelector,
151+
inlineMenuSelector,
152+
debugEl,
153+
}: {
154+
gridSelector?: string;
155+
inlineMenuSelector?: string;
156+
debugEl?: DebugElement;
157+
} = {},
158+
) => {
159+
inlineMenuSelector = inlineMenuSelector ?? selectors.inlineMenu;
160+
161+
this.clickRowItem(rowIndex, inlineMenuSelector, {
162+
gridSelector,
163+
debugEl,
164+
});
165+
this._utils.fixture.detectChanges();
166+
167+
this._utils.click(actionSelector, debugEl);
168+
this._utils.fixture.detectChanges();
169+
};
170+
171+
clickRowItem = (
172+
rowNumber: number,
173+
selector: string,
174+
{
175+
gridSelector,
176+
debugEl,
177+
}: {
178+
gridSelector?: string;
179+
debugEl?: DebugElement;
180+
} = {}) => this.getRowItem(rowNumber, selector, {
181+
debugEl,
182+
gridSelector,
183+
}).nativeElement
184+
.dispatchEvent(EventGenerator.click);
185+
186+
getRowCheckbox = (rowNumber: number, gridSelector = selectors.grid, debugEl = this._utils.fixture.debugElement) => {
187+
const rowEl = this._utils.getDebugElement(`${gridSelector} [data-row-index="${rowNumber - 1}"]`, debugEl);
188+
189+
const rowCheckbox = this._utils.getDebugElement('mat-checkbox input', rowEl);
190+
191+
return rowCheckbox;
192+
};
193+
194+
checkRow = (rowNumber: number, gridSelector = selectors.grid, debugEl = this._utils.fixture.debugElement) => {
195+
this.getRowCheckbox(rowNumber, gridSelector, debugEl).nativeElement.dispatchEvent(EventGenerator.click);
196+
this._utils.fixture.detectChanges();
197+
};
198+
199+
openContextMenu = (rowNumber: number) => {
200+
const selector = `${`[data-row-index="${rowNumber - 1}"]`} ${'[data-cy="grid-action-menu"]'}`;
201+
const button = this._utils.fixture.debugElement.query(By.css(selector));
202+
button.nativeElement.dispatchEvent(EventGenerator.click);
203+
};
204+
205+
openSearchFilter = ({
206+
columnName,
207+
}: {
208+
columnName: string;
209+
}) => {
210+
const selector = `[data-cy="ui-grid-search-filter-${columnName}"] [role="combobox"]`;
211+
const button = this._utils.fixture.debugElement.query(By.css(selector));
212+
213+
button.nativeElement.dispatchEvent(EventGenerator.click);
214+
this._utils.fixture.detectChanges();
215+
tick(300);
216+
};
217+
218+
filterData = ({
219+
columnName,
220+
nth,
221+
overlayContainerElement,
222+
}: {
223+
columnName: string;
224+
nth: number;
225+
overlayContainerElement: HTMLElement;
226+
}) => {
227+
const selector = `[data-column-name="ui-grid-dropdown-filter-${columnName}"]`;
228+
const button = this._utils.fixture.debugElement.query(By.css(selector));
229+
button.nativeElement.dispatchEvent(EventGenerator.click);
230+
this._utils.fixture.detectChanges();
231+
232+
const labelButton = overlayContainerElement.querySelectorAll('button.mat-menu-item');
233+
labelButton[nth].dispatchEvent(EventGenerator.click);
234+
235+
this._utils.fixture.detectChanges();
236+
tick(500);
237+
this._utils.fixture.detectChanges();
238+
};
239+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './grid-testing-utils';
2+
export * from './suggest-testing-utils';

projects/angular/testing/src/component-utils/suggest-testing-utils.ts

Lines changed: 22 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,40 @@ import { DebugElement } from '@angular/core';
33
import { tick } from '@angular/core/testing';
44
import { By } from '@angular/platform-browser';
55
import { UiSuggestComponent } from '@uipath/angular/components/ui-suggest';
6+
7+
import { EventGenerator } from '../utilities/event-generator';
68
import {
7-
EventGenerator,
8-
Key,
9-
} from '@uipath/angular/testing';
9+
FixtureTestingUtils,
10+
IStubEndpoint,
11+
} from '../utilities/fixture-testing-utils';
12+
import { Key } from '../utilities/key';
13+
14+
export interface ISuggestTestingOptions {
15+
debounce?: number;
16+
}
1017

11-
import { SUGGEST_DEBOUNCE } from './constants';
18+
const DEFAULT_SUGGEST_TESTING_OPTIONS: ISuggestTestingOptions = {
19+
debounce: 300,
20+
};
1221

1322
export class SuggestUtils<T> {
1423
dropdownSelector = '.ui-suggest-dropdown-item-list-container';
1524

1625
constructor(
17-
private _utils: IntegrationUtils<T>,
18-
) { }
26+
private _utils: FixtureTestingUtils<T>,
27+
private _options = DEFAULT_SUGGEST_TESTING_OPTIONS,
28+
) {
29+
}
1930

20-
openAndFlush = (selector: string, httpRequest: Function) => {
31+
openAndFlush = (selector: string, httpRequest: () => void) => {
2132
this._utils.click('.display', this._utils.getDebugElement(selector));
2233
this._utils.fixture.detectChanges();
2334
httpRequest();
2435
this._utils.fixture.detectChanges();
2536
};
2637

2738
// eslint-disable-next-line complexity
28-
searchAndSelect = (selector: string, httpRequest?: Function, searchStr = '', nth = 0, debugEl?: DebugElement) => {
39+
searchAndSelect = (selector: string, httpRequest?: () => void, searchStr = '', nth = 0, debugEl?: DebugElement) => {
2940
const suggest = this._utils.getDebugElement(selector, debugEl);
3041
const multiple = this.isMultiple(selector);
3142
const strategy = this.getFetchStrategy(selector, debugEl);
@@ -66,7 +77,7 @@ export class SuggestUtils<T> {
6677
}
6778

6879
this._utils.setInput('input', searchStr, parentContainer);
69-
tick(SUGGEST_DEBOUNCE);
80+
tick(this._options.debounce);
7081
this._utils.fixture.detectChanges();
7182

7283
if (httpRequest) { httpRequest(); }
@@ -93,7 +104,8 @@ export class SuggestUtils<T> {
93104
getFetchStrategy = (selector: string, debugEl?: DebugElement) => {
94105
const suggest = this._utils.getDebugElement(selector, debugEl);
95106
// maybe add a getter along the setter for fetchStrategy ?
96-
return (suggest.componentInstance as UiSuggestComponent)._fetchStrategy$?.value ?? 'eager';
107+
const fetchStrategyKey = '_fetchStrategy$';
108+
return (suggest.componentInstance as UiSuggestComponent)[fetchStrategyKey]?.value ?? 'eager';
97109
};
98110

99111
selectNthItem = (selector: string, nth = 0, config?: {
@@ -156,87 +168,3 @@ export class SuggestUtils<T> {
156168
clear = (selector: string) =>
157169
this._utils.getNativeElement(`${selector} [role=button].mat-icon`)?.dispatchEvent(EventGenerator.click);
158170
}
159-
160-
class KVPUtils<T> {
161-
constructor(
162-
private _utils: IntegrationUtils<T>,
163-
) { }
164-
165-
/**
166-
* Creates a new key value pair and populates it with the specified values
167-
*
168-
* @param keySearchText key suggest text to be selected
169-
* @param valueSearchText value suggest text to be selected
170-
*/
171-
addAndPopulateKVPInput = (keySearchText: string, valueSearchText: string, keyHttpRequest?: Function, valueHttpRequest?: Function) => {
172-
this._utils.click('[data-cy=ui-kvp-add-new-entry]');
173-
this._utils.fixture.detectChanges();
174-
175-
this._utils.suggest.searchAndSelect(this._nthKeySuggestSelector(0), keyHttpRequest, keySearchText);
176-
this._utils.fixture.detectChanges();
177-
tick(1000);
178-
this._utils.fixture.detectChanges();
179-
180-
this._utils.suggest.searchAndSelect(this._nthValueSuggestSelector(0), valueHttpRequest, valueSearchText);
181-
this._utils.fixture.detectChanges();
182-
tick(1);
183-
this._utils.fixture.detectChanges();
184-
185-
tick(1000);
186-
this._utils.fixture.detectChanges();
187-
};
188-
189-
/**
190-
* Existing number of key value pairs.
191-
*
192-
* @param debugEl
193-
* @returns
194-
*/
195-
currentKVPCount(debugEl = this._utils.fixture.debugElement) {
196-
const selector = 'ui-key-value-input';
197-
return this._utils.getAllDebugElements(selector, debugEl).length;
198-
}
199-
200-
/**
201-
* Retrive a reference to the nth key suggest.
202-
* Index starts at 1.
203-
*
204-
* @param debugEl
205-
* @returns
206-
*/
207-
nthKeySuggest(index: number, debugEl = this._utils.fixture.debugElement) {
208-
const selector = this._nthKeySuggestSelector(index);
209-
return this._utils.getDebugElement(selector, debugEl);
210-
}
211-
212-
/**
213-
* Retrive a reference to the nth value suggest.
214-
* Index starts at 1.
215-
*
216-
* @param debugEl
217-
* @returns
218-
*/
219-
nthValueSuggest(index: number, debugEl = this._utils.fixture.debugElement) {
220-
const selector = this._nthValueSuggestSelector(index);
221-
return this._utils.getDebugElement(selector, debugEl);
222-
}
223-
224-
/**
225-
* Removes the nth key value pair.
226-
* Index starts at 1.
227-
*
228-
* @param debugEl
229-
* @returns
230-
*/
231-
removeNthKVP(index: number, debugEl = this._utils.fixture.debugElement) {
232-
const selector = this._nthRemoveButtonSelector(index);
233-
this._utils.click(selector, debugEl);
234-
235-
tick(1000);
236-
this._utils.fixture.detectChanges();
237-
}
238-
239-
private _nthKeySuggestSelector(index: number) { return `[data-cy=ui-kvp-input-nr-${index}] [data-cy=ui-kvp-key-suggest]`; }
240-
private _nthValueSuggestSelector(index: number) { return `[data-cy=ui-kvp-input-nr-${index}] [data-cy=ui-kvp-value-suggest]`; }
241-
private _nthRemoveButtonSelector(index: number) { return `[data-cy=ui-kvp-input-nr-${index}] [data-cy=ui-kvp-remove-button]`; }
242-
}

0 commit comments

Comments
 (0)