@ngneers/controls-playwright 0.0.1-pre1

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 (164) hide show
  1. package/README.md +20 -0
  2. package/awesome-publish.config.ts +6 -0
  3. package/dist/components/accordion.d.ts +21 -0
  4. package/dist/components/accordion.d.ts.map +1 -0
  5. package/dist/components/accordion.js +42 -0
  6. package/dist/components/avatar.d.ts +9 -0
  7. package/dist/components/avatar.d.ts.map +1 -0
  8. package/dist/components/avatar.js +16 -0
  9. package/dist/components/breadcrumb.d.ts +20 -0
  10. package/dist/components/breadcrumb.d.ts.map +1 -0
  11. package/dist/components/breadcrumb.js +15 -0
  12. package/dist/components/button-group.d.ts +10 -0
  13. package/dist/components/button-group.d.ts.map +1 -0
  14. package/dist/components/button-group.js +16 -0
  15. package/dist/components/button.d.ts +6 -0
  16. package/dist/components/button.d.ts.map +1 -0
  17. package/dist/components/button.js +6 -0
  18. package/dist/components/calendar.d.ts +101 -0
  19. package/dist/components/calendar.d.ts.map +1 -0
  20. package/dist/components/calendar.js +56 -0
  21. package/dist/components/chip.d.ts +15 -0
  22. package/dist/components/chip.d.ts.map +1 -0
  23. package/dist/components/chip.js +38 -0
  24. package/dist/components/edit-inplace.d.ts +18 -0
  25. package/dist/components/edit-inplace.d.ts.map +1 -0
  26. package/dist/components/edit-inplace.js +29 -0
  27. package/dist/components/filter.d.ts +186 -0
  28. package/dist/components/filter.d.ts.map +1 -0
  29. package/dist/components/filter.js +55 -0
  30. package/dist/components/hint.d.ts +10 -0
  31. package/dist/components/hint.d.ts.map +1 -0
  32. package/dist/components/hint.js +22 -0
  33. package/dist/components/index.d.ts +38 -0
  34. package/dist/components/index.d.ts.map +1 -0
  35. package/dist/components/index.js +37 -0
  36. package/dist/components/inplace.d.ts +12 -0
  37. package/dist/components/inplace.d.ts.map +1 -0
  38. package/dist/components/inplace.js +29 -0
  39. package/dist/components/input-field.d.ts +12 -0
  40. package/dist/components/input-field.d.ts.map +1 -0
  41. package/dist/components/input-field.js +11 -0
  42. package/dist/components/input.d.ts +12 -0
  43. package/dist/components/input.d.ts.map +1 -0
  44. package/dist/components/input.js +25 -0
  45. package/dist/components/item-view.d.ts +18 -0
  46. package/dist/components/item-view.d.ts.map +1 -0
  47. package/dist/components/item-view.js +39 -0
  48. package/dist/components/list-box.d.ts +20 -0
  49. package/dist/components/list-box.d.ts.map +1 -0
  50. package/dist/components/list-box.js +24 -0
  51. package/dist/components/mask-input.d.ts +62 -0
  52. package/dist/components/mask-input.d.ts.map +1 -0
  53. package/dist/components/mask-input.js +109 -0
  54. package/dist/components/menu.d.ts +16 -0
  55. package/dist/components/menu.d.ts.map +1 -0
  56. package/dist/components/menu.js +26 -0
  57. package/dist/components/message.d.ts +10 -0
  58. package/dist/components/message.d.ts.map +1 -0
  59. package/dist/components/message.js +22 -0
  60. package/dist/components/popover.d.ts +12 -0
  61. package/dist/components/popover.d.ts.map +1 -0
  62. package/dist/components/popover.js +33 -0
  63. package/dist/components/progress.d.ts +17 -0
  64. package/dist/components/progress.d.ts.map +1 -0
  65. package/dist/components/progress.js +46 -0
  66. package/dist/components/radio.d.ts +16 -0
  67. package/dist/components/radio.d.ts.map +1 -0
  68. package/dist/components/radio.js +35 -0
  69. package/dist/components/scroller.d.ts +20 -0
  70. package/dist/components/scroller.d.ts.map +1 -0
  71. package/dist/components/scroller.js +58 -0
  72. package/dist/components/select-button.d.ts +30 -0
  73. package/dist/components/select-button.d.ts.map +1 -0
  74. package/dist/components/select-button.js +46 -0
  75. package/dist/components/select.d.ts +46 -0
  76. package/dist/components/select.d.ts.map +1 -0
  77. package/dist/components/select.js +74 -0
  78. package/dist/components/slider.d.ts +26 -0
  79. package/dist/components/slider.d.ts.map +1 -0
  80. package/dist/components/slider.js +73 -0
  81. package/dist/components/snackbar.d.ts +27 -0
  82. package/dist/components/snackbar.d.ts.map +1 -0
  83. package/dist/components/snackbar.js +70 -0
  84. package/dist/components/spinner.d.ts +11 -0
  85. package/dist/components/spinner.d.ts.map +1 -0
  86. package/dist/components/spinner.js +22 -0
  87. package/dist/components/state.d.ts +31 -0
  88. package/dist/components/state.d.ts.map +1 -0
  89. package/dist/components/state.js +31 -0
  90. package/dist/components/switch.d.ts +12 -0
  91. package/dist/components/switch.d.ts.map +1 -0
  92. package/dist/components/switch.js +39 -0
  93. package/dist/components/tabs.d.ts +22 -0
  94. package/dist/components/tabs.d.ts.map +1 -0
  95. package/dist/components/tabs.js +42 -0
  96. package/dist/components/tag.d.ts +10 -0
  97. package/dist/components/tag.d.ts.map +1 -0
  98. package/dist/components/tag.js +22 -0
  99. package/dist/components/toast.d.ts +27 -0
  100. package/dist/components/toast.d.ts.map +1 -0
  101. package/dist/components/toast.js +68 -0
  102. package/dist/components/toggle-button.d.ts +10 -0
  103. package/dist/components/toggle-button.d.ts.map +1 -0
  104. package/dist/components/toggle-button.js +29 -0
  105. package/dist/components/tooltip.d.ts +12 -0
  106. package/dist/components/tooltip.d.ts.map +1 -0
  107. package/dist/components/tooltip.js +32 -0
  108. package/dist/components/tree.d.ts +47 -0
  109. package/dist/components/tree.d.ts.map +1 -0
  110. package/dist/components/tree.js +85 -0
  111. package/dist/components/upload.d.ts +27 -0
  112. package/dist/components/upload.d.ts.map +1 -0
  113. package/dist/components/upload.js +47 -0
  114. package/dist/index.d.ts +2 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +1 -0
  117. package/dist/utils/classes.d.ts +119 -0
  118. package/dist/utils/classes.d.ts.map +1 -0
  119. package/dist/utils/classes.js +31 -0
  120. package/dist/utils/theme.d.ts +3 -0
  121. package/dist/utils/theme.d.ts.map +1 -0
  122. package/dist/utils/theme.js +41 -0
  123. package/package.json +38 -0
  124. package/src/components/accordion.ts +50 -0
  125. package/src/components/avatar.ts +17 -0
  126. package/src/components/breadcrumb.ts +17 -0
  127. package/src/components/button-group.ts +18 -0
  128. package/src/components/button.ts +5 -0
  129. package/src/components/calendar.ts +67 -0
  130. package/src/components/chip.ts +43 -0
  131. package/src/components/edit-inplace.ts +34 -0
  132. package/src/components/filter.ts +70 -0
  133. package/src/components/hint.ts +25 -0
  134. package/src/components/index.ts +37 -0
  135. package/src/components/inplace.ts +33 -0
  136. package/src/components/input-field.ts +16 -0
  137. package/src/components/input.ts +32 -0
  138. package/src/components/item-view.ts +48 -0
  139. package/src/components/list-box.ts +25 -0
  140. package/src/components/mask-input.ts +119 -0
  141. package/src/components/menu.ts +29 -0
  142. package/src/components/message.ts +25 -0
  143. package/src/components/popover.ts +39 -0
  144. package/src/components/progress.ts +53 -0
  145. package/src/components/radio.ts +42 -0
  146. package/src/components/scroller.ts +68 -0
  147. package/src/components/select-button.ts +57 -0
  148. package/src/components/select.ts +81 -0
  149. package/src/components/slider.ts +84 -0
  150. package/src/components/snackbar.ts +84 -0
  151. package/src/components/spinner.ts +27 -0
  152. package/src/components/state.ts +37 -0
  153. package/src/components/switch.ts +43 -0
  154. package/src/components/tabs.ts +50 -0
  155. package/src/components/tag.ts +25 -0
  156. package/src/components/toast.ts +82 -0
  157. package/src/components/toggle-button.ts +33 -0
  158. package/src/components/tooltip.ts +38 -0
  159. package/src/components/tree.ts +98 -0
  160. package/src/components/upload.ts +63 -0
  161. package/src/index.ts +1 -0
  162. package/src/utils/classes.ts +32 -0
  163. package/src/utils/theme.ts +44 -0
  164. package/tsconfig.lib.json +20 -0
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@ngneers/controls-playwright",
3
+ "version": "0.0.1-pre1",
4
+ "description": "Playwright testing harness with page-object helpers for @ngneers/controls components.",
5
+ "license": "MIT",
6
+ "homepage": "https://ngneers.dev",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/NGneers/controls.git",
10
+ "directory": "packages/playwright"
11
+ },
12
+ "keywords": [
13
+ "angular",
14
+ "playwright",
15
+ "testing",
16
+ "e2e",
17
+ "page-object",
18
+ "ngneers-controls"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "scripts": {
24
+ "prebuild": "pnpm rimraf ./dist",
25
+ "build": "pnpm prebuild && tsc -p ./tsconfig.lib.json"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "peerDependencies": {
31
+ "@ngneers/controls": "workspace:*",
32
+ "@ngneers/controls-themes": "workspace:*"
33
+ },
34
+ "devDependencies": {
35
+ "rimraf": "^6.1.3",
36
+ "typescript": "catalog:"
37
+ }
38
+ }
@@ -0,0 +1,50 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { accordionControlTemplate } from '@ngneers/controls-themes/templates/accordion';
4
+ import { accordionPanelControlTemplate } from '@ngneers/controls-themes/templates/accordion-panel';
5
+
6
+ export class NgnAccordionHarness {
7
+ public readonly classes = themeClasses(accordionPanelControlTemplate);
8
+
9
+ public readonly panels: Locator;
10
+
11
+ constructor(public locator: Locator) {
12
+ this.panels = this.locator.locator(this.classes['root']);
13
+ }
14
+
15
+ public getPanelByIndex(index: number): NgnAccordionPanelHarness {
16
+ return new NgnAccordionPanelHarness(this.panels.nth(index));
17
+ }
18
+
19
+ public expectPanelCount(count: number) {
20
+ return expect(this.panels).toHaveCount(count);
21
+ }
22
+ }
23
+
24
+ export class NgnAccordionPanelHarness {
25
+ public readonly classes = themeClasses(accordionPanelControlTemplate);
26
+
27
+ public readonly header: Locator;
28
+ public readonly content: Locator;
29
+
30
+ constructor(public locator: Locator) {
31
+ this.header = this.locator.locator(this.classes['header']);
32
+ this.content = this.locator.locator(this.classes['content']);
33
+ }
34
+
35
+ public expectHeaderText(expected: string) {
36
+ return expect(this.header).toHaveText(expected);
37
+ }
38
+
39
+ public expectExpanded(expanded = true) {
40
+ return expect(this.header).toHaveAttribute('aria-expanded', String(expanded));
41
+ }
42
+
43
+ public expectDisabled(disabled = true) {
44
+ return expect(this.header).toBeDisabled();
45
+ }
46
+
47
+ public async toggle() {
48
+ await this.header.click();
49
+ }
50
+ }
@@ -0,0 +1,17 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { avatarControlTemplate } from '@ngneers/controls-themes/templates/avatar';
4
+
5
+ export class NgnAvatarHarness {
6
+ public readonly classes = themeClasses(avatarControlTemplate);
7
+
8
+ constructor(public locator: Locator) {}
9
+
10
+ public expectInitials(expected: string) {
11
+ return expect(this.locator.locator(this.classes.initials)).toHaveText(expected);
12
+ }
13
+
14
+ public expectImageSrc(expected: string) {
15
+ return expect(this.locator.locator(this.classes.image)).toHaveAttribute('src', expected);
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ import type { Locator } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { breadcrumbControlTemplate } from '@ngneers/controls-themes/templates/breadcrumb';
4
+ import { NgnItemViewHarness } from './item-view';
5
+ import { NgnMenuHarness } from './menu';
6
+
7
+ export class NgnBreadcrumbHarness {
8
+ public readonly classes = themeClasses(breadcrumbControlTemplate);
9
+
10
+ public readonly itemView: NgnItemViewHarness;
11
+ public readonly overflowMenu: NgnMenuHarness;
12
+
13
+ constructor(public locator: Locator) {
14
+ this.itemView = new NgnItemViewHarness(this.locator.locator(this.classes['item-view']['root']));
15
+ this.overflowMenu = new NgnMenuHarness(this.locator.locator(this.classes['menu']['root']));
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ import { expect, type Locator } from '@playwright/test';
2
+ import { NgnButtonHarness } from './button';
3
+
4
+ export class NgnButtonGroupHarness {
5
+ public readonly buttons: Locator;
6
+
7
+ constructor(public locator: Locator) {
8
+ this.buttons = locator.locator('button[ngnButton]');
9
+ }
10
+
11
+ public async expectItemCount(count: number) {
12
+ await expect(this.buttons).toHaveCount(count);
13
+ }
14
+
15
+ public getButtonAt(index: number): NgnButtonHarness {
16
+ return new NgnButtonHarness(this.buttons.nth(index));
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ import type { Locator } from '@playwright/test';
2
+
3
+ export class NgnButtonHarness {
4
+ constructor(public locator: Locator) {}
5
+ }
@@ -0,0 +1,67 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { calendarControlTemplate } from '@ngneers/controls-themes/templates/calendar';
3
+ import { themeClasses } from '../utils/theme';
4
+ import { NgnSelectHarness } from './select';
5
+ import type { WeekDay } from '@ngneers/controls/calendar';
6
+ import { en } from '@ngneers/controls/i18n/translations/en';
7
+
8
+ export class NgnCalendarHarness {
9
+ public readonly classes = themeClasses(calendarControlTemplate);
10
+
11
+ public readonly backButton: Locator;
12
+ public readonly nextButton: Locator;
13
+ public readonly currentMonth: NgnSelectHarness;
14
+ public readonly currentYear: NgnSelectHarness;
15
+ public readonly days: Locator;
16
+ public readonly day: Locator;
17
+ public readonly daySameMonth: Locator;
18
+ public readonly dayOtherMonth: Locator;
19
+ public readonly daySelected: Locator;
20
+ public readonly weekDay: Locator;
21
+
22
+ constructor(public locator: Locator) {
23
+ this.backButton = locator.locator(this.classes.previous['root']);
24
+ this.nextButton = locator.locator(this.classes.next['root']);
25
+ this.currentMonth = new NgnSelectHarness(
26
+ locator.locator(this.classes['current-month']['root'])
27
+ );
28
+ this.currentYear = new NgnSelectHarness(locator.locator(this.classes['current-year']['root']));
29
+ this.days = locator.locator(this.classes.days);
30
+ this.day = locator.locator(this.classes.day);
31
+ this.daySameMonth = locator.locator(
32
+ `${this.classes.day}:not(${this.classes['day-other-month']})`
33
+ );
34
+ this.dayOtherMonth = locator.locator(`${this.classes.day}${this.classes['day-other-month']}`);
35
+ this.daySelected = locator.locator(this.classes['day-selected']);
36
+ this.weekDay = locator.locator(this.classes['week-day']);
37
+ }
38
+
39
+ public expectDate(year: string, month: string, day: string) {
40
+ return Promise.all([
41
+ this.currentYear.inputEditable.expectValue(year),
42
+ this.currentMonth.expectSelectedItemText(month),
43
+ expect(this.daySelected).toHaveText(day),
44
+ ]);
45
+ }
46
+
47
+ public expectFirstWeekday(weekday: WeekDay) {
48
+ return expect(this.weekDay.first()).toHaveText(en.calendar.weekdaysShort[weekday]);
49
+ }
50
+
51
+ public selectDay(day: number) {
52
+ return this.daySameMonth.nth(day - 1).click();
53
+ }
54
+
55
+ /**
56
+ * Select a month in the calendar while in months view
57
+ * @param month the month to select (1-12)
58
+ */
59
+ public async selectMonth(month: number) {
60
+ await this.currentMonth.open();
61
+ await this.currentMonth.clickItemByIndex(month - 1);
62
+ }
63
+
64
+ public async selectDayFromOtherMonth(day: number) {
65
+ return this.dayOtherMonth.filter({ hasText: new RegExp(`^\\s*${day}\\s*$`) }).click();
66
+ }
67
+ }
@@ -0,0 +1,43 @@
1
+ import { chipControlTemplate } from '@ngneers/controls-themes/templates/chip';
2
+ import { themeClasses } from '../utils/theme';
3
+ import test, { expect, type Locator } from '@playwright/test';
4
+
5
+ export class NgnChipHarness {
6
+ public readonly classes = themeClasses(chipControlTemplate);
7
+
8
+ public readonly locator: Locator;
9
+ public readonly content: Locator;
10
+ public readonly closeButton: Locator;
11
+
12
+ constructor(locator: Locator) {
13
+ this.locator = locator;
14
+ this.content = locator.locator(this.classes.content);
15
+ this.closeButton = locator.locator(this.classes['close-button']);
16
+ }
17
+
18
+ public async click() {
19
+ await this.content.click();
20
+ }
21
+
22
+ public async close() {
23
+ await this.closeButton.click();
24
+ }
25
+
26
+ public async expectState(state: { actionable?: boolean; closable?: boolean }) {
27
+ if (state.actionable !== undefined) {
28
+ if (state.actionable) {
29
+ await expect(this.locator).toHaveClass(this.classes.actionable);
30
+ } else {
31
+ await expect(this.locator).not.toHaveClass(this.classes.actionable);
32
+ }
33
+ }
34
+
35
+ if (state.closable !== undefined) {
36
+ if (state.closable) {
37
+ await expect(this.locator).toHaveClass(this.classes.closable);
38
+ } else {
39
+ await expect(this.locator).not.toHaveClass(this.classes.closable);
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,34 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { editInplaceControlTemplate } from '@ngneers/controls-themes/templates/edit-inplace';
4
+ import { NgnInplaceHarness } from './inplace';
5
+
6
+ export class NgnEditInplaceHarness {
7
+ public readonly classes = themeClasses(editInplaceControlTemplate);
8
+
9
+ public readonly inplace: NgnInplaceHarness;
10
+ public readonly input: Locator;
11
+ public readonly closeButton: Locator;
12
+
13
+ constructor(public locator: Locator) {
14
+ this.inplace = new NgnInplaceHarness(this.locator.locator(this.classes['inplace']['root']));
15
+ this.input = this.locator.locator(this.classes['default-edit-input']);
16
+ this.closeButton = this.locator.locator(this.classes['default-edit-close-button']);
17
+ }
18
+
19
+ public async fillInput(value: string) {
20
+ await this.input.fill(value);
21
+ }
22
+
23
+ public async expectInputValue(value: string) {
24
+ await expect(this.input).toHaveValue(value);
25
+ }
26
+
27
+ public async clickCloseButton() {
28
+ await this.closeButton.click();
29
+ }
30
+
31
+ public async pressEnter() {
32
+ await this.input.press('Enter');
33
+ }
34
+ }
@@ -0,0 +1,70 @@
1
+ import { expect, type Locator } from '@playwright/test';
2
+ import { filterControlTemplate } from '@ngneers/controls-themes/templates/filter';
3
+ import { themeClasses } from '../utils/theme';
4
+ import { NGN_CLASSES } from '../utils/classes';
5
+ import { NgnInputHarness } from './input';
6
+ import { NgnSelectHarness } from './select';
7
+
8
+ export class NgnFilterHarness {
9
+ public readonly classes = themeClasses(filterControlTemplate);
10
+
11
+ public readonly trigger: Locator;
12
+ public readonly popoverContent: Locator;
13
+
14
+ constructor(public locator: Locator) {
15
+ this.trigger = locator.locator(this.classes['input-field']['root']);
16
+ this.popoverContent = locator.locator(this.classes['popover-content']);
17
+ }
18
+
19
+ public async expectOpened(opened = true): Promise<void> {
20
+ await expect(this.popoverContent).toBeVisible({ visible: opened });
21
+ }
22
+
23
+ public async open(): Promise<void> {
24
+ await this.trigger.click();
25
+ await this.expectOpened(true);
26
+ }
27
+
28
+ public row(index: number): Locator {
29
+ return this.locator.locator(this.classes['row']).nth(index);
30
+ }
31
+
32
+ public operatorSelect(index: number): NgnSelectHarness {
33
+ return new NgnSelectHarness(this.row(index).locator(this.classes['operator']['root']));
34
+ }
35
+
36
+ /** Select inside row using the 'value' ptClass (e.g. boolean operator or list select). */
37
+ public valueSelect(index: number): NgnSelectHarness {
38
+ return new NgnSelectHarness(this.row(index).locator(this.classes['value']['root']));
39
+ }
40
+
41
+ public valueInput(index: number): NgnInputHarness {
42
+ return new NgnInputHarness(
43
+ this.row(index).locator(`${this.classes['value']['root']} ${NGN_CLASSES.input['root']}`)
44
+ );
45
+ }
46
+
47
+ public removeButton(index: number): Locator {
48
+ return this.row(index).locator(this.classes['remove-btn']['root']);
49
+ }
50
+
51
+ public addConditionButton(): Locator {
52
+ return this.locator.locator('[data-testid="filter-add-rule"]');
53
+ }
54
+
55
+ public matchModeDivider(): Locator {
56
+ return this.locator.locator('[data-testid="filter-match-mode"]');
57
+ }
58
+
59
+ public clearButton(): Locator {
60
+ return this.locator.locator('[data-testid="filter-clear"]');
61
+ }
62
+
63
+ public applyButton(): Locator {
64
+ return this.locator.locator('[data-testid="filter-apply"]');
65
+ }
66
+
67
+ public cancelButton(): Locator {
68
+ return this.locator.locator('[data-testid="filter-cancel"]');
69
+ }
70
+ }
@@ -0,0 +1,25 @@
1
+ import { hintControlTemplate } from '@ngneers/controls-themes/templates/hint';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { expect, type Locator } from '@playwright/test';
4
+
5
+ export class NgnHintHarness {
6
+ public readonly classes = themeClasses(hintControlTemplate);
7
+
8
+ public readonly locator: Locator;
9
+ public readonly content: Locator;
10
+ public readonly icon: Locator;
11
+
12
+ constructor(locator: Locator) {
13
+ this.locator = locator;
14
+ this.content = locator.locator(this.classes.content);
15
+ this.icon = locator.locator(this.classes.icon);
16
+ }
17
+
18
+ public async expectIcon(hasIcon: boolean) {
19
+ if (hasIcon) {
20
+ await expect(this.icon).toBeVisible();
21
+ } else {
22
+ await expect(this.icon).not.toBeVisible();
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,37 @@
1
+ export * from './accordion';
2
+ export * from './avatar';
3
+ export * from './breadcrumb';
4
+ export * from './button-group';
5
+ export * from './button';
6
+ export * from './calendar';
7
+ export * from './chip';
8
+ export * from './edit-inplace';
9
+ export * from './inplace';
10
+ export * from './filter';
11
+ export * from './hint';
12
+ export * from './input';
13
+ export * from './input-field';
14
+ export * from './mask-input';
15
+ export * from './item-view';
16
+ export * from './list-box';
17
+ export * from './menu';
18
+ export * from './message';
19
+ export * from './popover';
20
+ export * from './progress';
21
+ export * from './radio';
22
+ export * from './scroller';
23
+ export * from './filter';
24
+ export * from './select';
25
+ export * from './select-button';
26
+ export * from './slider';
27
+ export * from './snackbar';
28
+ export * from './spinner';
29
+ export * from './state';
30
+ export * from './switch';
31
+ export * from './tabs';
32
+ export * from './tag';
33
+ export * from './toast';
34
+ export * from './toggle-button';
35
+ export * from './tooltip';
36
+ export * from './tree';
37
+ export * from './upload';
@@ -0,0 +1,33 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { inplaceControlTemplate } from '@ngneers/controls-themes/templates/inplace';
4
+
5
+ export class NgnInplaceHarness {
6
+ public readonly classes = themeClasses(inplaceControlTemplate);
7
+
8
+ public readonly display: Locator;
9
+ public readonly content: Locator;
10
+
11
+ constructor(public locator: Locator) {
12
+ this.display = this.locator.locator(this.classes['display']);
13
+ this.content = this.locator.locator(this.classes['content']);
14
+ }
15
+
16
+ public expectDisplayVisible(visible = true) {
17
+ if (visible) {
18
+ return expect(this.display).toBeVisible();
19
+ }
20
+ return expect(this.display).not.toBeVisible();
21
+ }
22
+
23
+ public expectContentVisible(visible = true) {
24
+ if (visible) {
25
+ return expect(this.content).toBeVisible();
26
+ }
27
+ return expect(this.content).not.toBeVisible();
28
+ }
29
+
30
+ public async clickDisplay() {
31
+ await this.display.click();
32
+ }
33
+ }
@@ -0,0 +1,16 @@
1
+ import type { Locator } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/input-field';
4
+
5
+ export class NgnInputFieldHarness<T extends Record<string, any> = Record<string, any>> {
6
+ public readonly classes = themeClasses(inputFieldControlTemplate);
7
+
8
+ public readonly children: T;
9
+
10
+ constructor(
11
+ public locator: Locator,
12
+ children?: (locator: Locator) => T
13
+ ) {
14
+ this.children = children?.(locator) ?? ({} as T);
15
+ }
16
+ }
@@ -0,0 +1,32 @@
1
+ import { type Locator, expect } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { inputControlTemplate } from '@ngneers/controls-themes/templates/input';
4
+
5
+ export class NgnInputHarness {
6
+ public readonly classes = themeClasses(inputControlTemplate);
7
+
8
+ public readonly locator: Locator;
9
+
10
+ constructor(locator: Locator) {
11
+ this.locator = locator;
12
+ }
13
+
14
+ public expectValue(value: string): Promise<void> {
15
+ return expect(this.locator).toHaveValue(value);
16
+ }
17
+ public clear(): Promise<void> {
18
+ return this.locator.clear();
19
+ }
20
+
21
+ public fill(value: string): Promise<void> {
22
+ return this.locator.fill(value);
23
+ }
24
+
25
+ public pressSequentially(text: string): Promise<void> {
26
+ return this.locator.pressSequentially(text, { delay: 5 });
27
+ }
28
+
29
+ public press(key: string): Promise<void> {
30
+ return this.locator.press(key);
31
+ }
32
+ }
@@ -0,0 +1,48 @@
1
+ import { expect, type Locator } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { itemViewControlTemplate } from '@ngneers/controls-themes/templates/item-view';
4
+
5
+ export class NgnItemViewHarness {
6
+ public readonly classes = themeClasses(itemViewControlTemplate);
7
+ public readonly item: Locator;
8
+ public readonly itemVisible: Locator;
9
+ public readonly itemOverflowing: Locator;
10
+ public readonly overflowItem: Locator;
11
+
12
+ constructor(public locator: Locator) {
13
+ this.item = locator.locator(this.classes['item']);
14
+ this.itemVisible = locator.locator(
15
+ `${this.classes['item']}:not(${this.classes['item-overflowing']})`
16
+ );
17
+ this.itemOverflowing = locator.locator(this.classes['item-overflowing']);
18
+ this.overflowItem = locator.locator(this.classes['more-items']);
19
+ }
20
+
21
+ public async expectItemCount(count: number) {
22
+ await expect(this.item).toHaveCount(count);
23
+ }
24
+
25
+ public async expectItemVisibleCount(count: number) {
26
+ await expect(this.itemVisible).toHaveCount(count);
27
+ }
28
+
29
+ public async expectItemOverflowingCount(count: number) {
30
+ await expect(this.itemOverflowing).toHaveCount(count);
31
+ }
32
+
33
+ public async expectItemTexts(texts: string[]) {
34
+ await expect(this.item).toHaveText(texts);
35
+ }
36
+
37
+ public async expectItemVisibleTexts(texts: string[]) {
38
+ await expect(this.itemVisible).toHaveText(texts);
39
+ }
40
+
41
+ public async expectItemOverflowingTexts(texts: string[]) {
42
+ await expect(this.itemOverflowing).toHaveText(texts);
43
+ }
44
+
45
+ public getItemByIndex(index: number) {
46
+ return this.itemVisible.nth(index);
47
+ }
48
+ }
@@ -0,0 +1,25 @@
1
+ import { expect, type Locator } from '@playwright/test';
2
+ import { themeClasses } from '../utils/theme';
3
+ import { listBoxControlTemplate } from '@ngneers/controls-themes/templates/list-box';
4
+ import { NgnScrollerHarness } from './scroller';
5
+
6
+ export class NgnListBoxHarness {
7
+ public readonly classes = themeClasses(listBoxControlTemplate);
8
+ public readonly group: Locator;
9
+ public readonly item: Locator;
10
+ public readonly itemHighlighted: Locator;
11
+ public readonly itemSelected: Locator;
12
+ public readonly scroller: NgnScrollerHarness;
13
+
14
+ constructor(public locator: Locator) {
15
+ this.group = locator.locator(this.classes['group']);
16
+ this.item = locator.locator(this.classes['item']);
17
+ this.itemHighlighted = locator.locator(this.classes['item-highlighted']);
18
+ this.itemSelected = locator.locator(this.classes['item-selected']);
19
+ this.scroller = new NgnScrollerHarness(locator.locator(this.classes['scroller']['root']));
20
+ }
21
+
22
+ public expectItemsCount(count: number) {
23
+ return expect(this.item).toHaveCount(count);
24
+ }
25
+ }