11import { Locator , Page } from "@playwright/test" ;
22
3- export abstract class AbstractPage {
4- protected page : Page ;
3+ export abstract class BaseComponent {
4+ constructor ( protected page : Page , protected rootLocator ?: Locator ) {
5+
6+ }
7+
8+ protected searcher ( ) : Page | Locator {
9+ if ( this . rootLocator ) {
10+ return this . rootLocator ;
11+ } else {
12+ return this . page ;
13+ }
14+ }
15+ }
16+
17+ export abstract class BasePage extends BaseComponent {
18+ constructor ( page : Page ) {
19+ super ( page ) ;
20+ }
21+ }
22+
23+ export class MainMenuComponent extends BaseComponent {
24+ private readonly workPackages : Locator ;
525
626 constructor ( page : Page ) {
7- this . page = page ;
27+ super ( page ) ;
28+ this . workPackages = page . locator ( "#main-menu-work-packages" ) ;
829 }
930
31+ async clickOnWorkPackagesItm ( ) : Promise < AllOpenWpPage > {
32+ await this . workPackages . click ( ) ;
33+ return new AllOpenWpPage ( this . page ) ;
34+ }
1035}
1136
12- export class OverviewPage extends AbstractPage {
37+ export class OverviewPage extends BasePage {
38+ public readonly mainMenu : MainMenuComponent ;
39+
40+ constructor ( page : Page ) {
41+ super ( page ) ;
42+ this . mainMenu = new MainMenuComponent ( page ) ;
43+ }
44+
45+ }
46+
47+ export class NewTaskPage extends BasePage {
48+ private readonly subjectTb : Locator ;
49+ private readonly estimatedTimeTb : Locator ;
50+ private readonly saveBtn : Locator ;
51+
52+ constructor ( page : Page ) {
53+ super ( page ) ;
54+ this . subjectTb = page . getByLabel ( 'Subject' , { exact : true } ) ;
55+ this . estimatedTimeTb = page . getByLabel ( 'Estimated time' , { exact : true } )
56+ this . saveBtn = page . getByRole ( 'button' , { name : 'Save' } ) ;
57+ }
58+
59+ async fillSubject ( subject : string ) : Promise < NewTaskPage > {
60+ await this . subjectTb . fill ( subject ) ;
61+ return this ;
62+ }
63+
64+ async fillEstimatedTime ( estimatedTime : string ) : Promise < NewTaskPage > {
65+ // await page.locator('#wp-new-inline-edit--field-assignee').getByRole('combobox').click();
66+ await this . estimatedTimeTb . fill ( estimatedTime ) ;
67+ return this ;
68+ }
69+
70+ async clickOnSaveBtn ( ) : Promise < OverviewPage > {
71+ await this . saveBtn . click ( ) ;
72+ return new OverviewPage ( this . page ) ;
73+ }
1374
1475}
1576
16- export class OpenProjectPage extends AbstractPage {
77+
78+ export class FilterComponent extends BaseComponent {
79+
80+ private readonly filterByTextTb : Locator ;
81+
82+ constructor ( page : Page ) {
83+ super ( page ) ;
84+ this . filterByTextTb = page . getByPlaceholder ( 'Subject, description, comments, ...' ) ;
85+ }
86+
87+ async fillFilterByText ( filterText : string ) : Promise < FilterComponent > {
88+ const responsePromise = this . page . waitForResponse ( '**/queries/**' ) ;
89+ await this . filterByTextTb . fill ( filterText ) ;
90+ const response = await responsePromise
91+ return this ;
92+ }
93+
94+ }
95+
96+ export class Table extends BaseComponent {
97+ constructor ( page : Page , rootLocator : Locator ) {
98+ super ( page , rootLocator ) ;
99+ }
100+
101+ async containsText ( text : string ) : Promise < boolean > {
102+ return await this . searcher ( ) . locator ( 'text=' + text ) . first ( ) . isVisible ( ) ;
103+ }
104+ }
105+
106+ export class ApplicationMenu extends BaseComponent {
107+
108+ private readonly signOutBtn : Locator ;
109+
110+ constructor ( page : Page , rootLocator : Locator ) {
111+ super ( page , rootLocator ) ;
112+ this . signOutBtn = this . searcher ( ) . getByRole ( 'link' , { name : 'Sign out' } ) ;
113+ }
114+
115+ async clickOnSignOutBtn ( ) : Promise < LoginPage > {
116+ await this . signOutBtn . click ( ) ;
117+ return new LoginPage ( this . page ) ;
118+ }
119+ }
120+
121+
122+ export class OpenProjectPage extends BasePage {
17123
18124 private readonly selectAProjectToggle : Locator ;
125+ private readonly applicationMenuLnk : Locator ;
126+ private readonly applicationMenuRoot : Locator ;
127+
128+
19129
20130 constructor ( page : Page ) {
21131 super ( page ) ;
22132 this . selectAProjectToggle = page . locator ( "#projects-menu i" ) ;
133+ this . applicationMenuLnk = page . locator ( "a[title='OpenProject Admin']" ) . locator ( ".op-app-menu--item-title" ) ;
134+ this . applicationMenuRoot = page . locator ( "#user-menu" ) ;
23135 }
24136
25137 async clickOnSelectAProjectToggle ( ) : Promise < OpenProjectPage > {
@@ -28,10 +140,15 @@ export class OpenProjectPage extends AbstractPage {
28140 }
29141
30142 async clickOnProjectName ( projectName : string ) : Promise < OverviewPage > {
31- await this . page . locator ( `#ui-id-5 >> text= ${ projectName } ` ) . click ( )
143+ await this . page . locator ( '.project-search-results' ) . getByRole ( 'link' , { name : projectName } ) . click ( ) ;
32144 return new OverviewPage ( this . page ) ;
33145 }
34146
147+ async clickOnUserMenu ( ) : Promise < ApplicationMenu > {
148+ await this . applicationMenuLnk . click ( ) ;
149+ return new ApplicationMenu ( this . page , this . applicationMenuRoot ) ;
150+ }
151+
35152 async doSelectProject ( projectName : string ) : Promise < OverviewPage > {
36153 await this . clickOnSelectAProjectToggle ( ) ;
37154 await this . clickOnProjectName ( projectName ) ;
@@ -40,7 +157,47 @@ export class OpenProjectPage extends AbstractPage {
40157
41158}
42159
43- export class LoginPage extends AbstractPage {
160+
161+ export class AllOpenWpPage extends OpenProjectPage {
162+
163+ private readonly createNewWpBtn : Locator ;
164+ private readonly taskBtn : Locator ;
165+ private readonly activateFilterBtn : Locator ;
166+ private readonly deactivateFilterBtn : Locator ;
167+ public readonly table : Table ;
168+
169+
170+ constructor ( page : Page ) {
171+ super ( page ) ;
172+ this . createNewWpBtn = page . locator ( 'wp-create-button' ) . getByLabel ( 'Create new work package' ) ;
173+ this . taskBtn = page . locator ( '#types-context-menu' ) . getByLabel ( 'Task' , { exact : true } ) ;
174+ this . activateFilterBtn = page . getByRole ( 'button' , { name : 'Activate Filter' } ) ;
175+ this . deactivateFilterBtn = page . getByRole ( 'button' , { name : 'Deactivate Filter' } ) ;
176+ this . table = new Table ( page , page . locator ( '.work-package-table' ) ) ;
177+ }
178+
179+ async clickOnCreateNewWorkPackageBtn ( ) : Promise < NewTaskPage > {
180+ await this . createNewWpBtn . click ( ) ;
181+ await this . taskBtn . click ( ) ;
182+ return new NewTaskPage ( this . page ) ;
183+ }
184+
185+ async clickOnActivateFilterBtn ( ) : Promise < FilterComponent > {
186+ await this . activateFilterBtn . click ( ) ;
187+ return new FilterComponent ( this . page ) ;
188+ }
189+
190+ async clickOnDeactivateFilterBtn ( ) : Promise < AllOpenWpPage > {
191+ await this . deactivateFilterBtn . click ( ) ;
192+ return new AllOpenWpPage ( this . page ) ;
193+ }
194+
195+
196+ }
197+
198+
199+
200+ export class LoginPage extends BasePage {
44201 /**
45202 * @param {import('playwright').Page } page
46203 */
0 commit comments