1111 */
1212
1313import { expect , Locator , Page } from '@playwright/test' ;
14- import { getCurrentPath , waitForUrlNotContaining } from '../utils' ;
1514import { BasePage } from './base-page' ;
1615
1716export class HomePage extends BasePage {
18- readonly welcomeHeading : Locator ;
1917 readonly notebookSection : Locator ;
2018 readonly helpSection : Locator ;
2119 readonly communitySection : Locator ;
22- readonly createNewNoteButton : Locator ;
23- readonly importNoteButton : Locator ;
24- readonly searchInput : Locator ;
25- readonly filterInput : Locator ;
2620 readonly zeppelinLogo : Locator ;
2721 readonly anonymousUserIndicator : Locator ;
2822 readonly welcomeSection : Locator ;
@@ -31,11 +25,12 @@ export class HomePage extends BasePage {
3125 readonly helpCommunityColumn : Locator ;
3226 readonly welcomeDescription : Locator ;
3327 readonly refreshNoteButton : Locator ;
34- readonly refreshIcon : Locator ;
35- readonly notebookList : Locator ;
3628 readonly notebookHeading : Locator ;
3729 readonly helpHeading : Locator ;
3830 readonly communityHeading : Locator ;
31+ readonly createNoteModal : Locator ;
32+ readonly createNoteButton : Locator ;
33+ readonly notebookNameInput : Locator ;
3934 readonly externalLinks : {
4035 documentation : Locator ;
4136 mailingList : Locator ;
@@ -52,27 +47,13 @@ export class HomePage extends BasePage {
5247 clearOutput : Locator ;
5348 moveToTrash : Locator ;
5449 } ;
55- folderActions : {
56- createNote : Locator ;
57- renameFolder : Locator ;
58- moveToTrash : Locator ;
59- } ;
60- trashActions : {
61- restoreAll : Locator ;
62- emptyAll : Locator ;
63- } ;
6450 } ;
6551
6652 constructor ( page : Page ) {
6753 super ( page ) ;
68- this . welcomeHeading = page . locator ( 'h1' , { hasText : 'Welcome to Zeppelin!' } ) ;
6954 this . notebookSection = page . locator ( 'text=Notebook' ) . first ( ) ;
7055 this . helpSection = page . locator ( 'text=Help' ) . first ( ) ;
7156 this . communitySection = page . locator ( 'text=Community' ) . first ( ) ;
72- this . createNewNoteButton = page . locator ( 'text=Create new Note' ) ;
73- this . importNoteButton = page . locator ( 'text=Import Note' ) ;
74- this . searchInput = page . locator ( 'textbox' , { hasText : 'Search' } ) ;
75- this . filterInput = page . locator ( 'input[placeholder*="Filter"]' ) ;
7657 this . zeppelinLogo = page . locator ( 'text=Zeppelin' ) . first ( ) ;
7758 this . anonymousUserIndicator = page . locator ( 'text=anonymous' ) ;
7859 this . welcomeSection = page . locator ( '.welcome' ) ;
@@ -81,11 +62,12 @@ export class HomePage extends BasePage {
8162 this . helpCommunityColumn = page . locator ( '[nz-col]' ) . last ( ) ;
8263 this . welcomeDescription = page . locator ( '.welcome' ) . getByText ( 'Zeppelin is web-based notebook' ) ;
8364 this . refreshNoteButton = page . locator ( 'a.refresh-note' ) ;
84- this . refreshIcon = page . locator ( 'a.refresh-note i[nz-icon]' ) ;
85- this . notebookList = page . locator ( 'zeppelin-node-list' ) ;
8665 this . notebookHeading = this . notebookColumn . locator ( 'h3' ) ;
8766 this . helpHeading = page . locator ( 'h3' ) . filter ( { hasText : 'Help' } ) ;
8867 this . communityHeading = page . locator ( 'h3' ) . filter ( { hasText : 'Community' } ) ;
68+ this . createNoteModal = page . locator ( 'div.ant-modal-content' ) ;
69+ this . createNoteButton = this . createNoteModal . locator ( 'button' , { hasText : 'Create' } ) ;
70+ this . notebookNameInput = this . createNoteModal . locator ( 'input[name="noteName"]' ) ;
8971
9072 this . externalLinks = {
9173 documentation : page . locator ( 'a[href*="zeppelin.apache.org/docs"]' ) ,
@@ -103,67 +85,30 @@ export class HomePage extends BasePage {
10385 renameNote : page . locator ( '.file .operation a[nztooltiptitle*="Rename note"]' ) ,
10486 clearOutput : page . locator ( '.file .operation a[nztooltiptitle*="Clear output"]' ) ,
10587 moveToTrash : page . locator ( '.file .operation a[nztooltiptitle*="Move note to Trash"]' )
106- } ,
107- folderActions : {
108- createNote : page . locator ( '.folder .operation a[nztooltiptitle*="Create new note"]' ) ,
109- renameFolder : page . locator ( '.folder .operation a[nztooltiptitle*="Rename folder"]' ) ,
110- moveToTrash : page . locator ( '.folder .operation a[nztooltiptitle*="Move folder to Trash"]' )
111- } ,
112- trashActions : {
113- restoreAll : page . locator ( '.folder .operation a[nztooltiptitle*="Restore all"]' ) ,
114- emptyAll : page . locator ( '.folder .operation a[nztooltiptitle*="Empty all"]' )
11588 }
11689 } ;
11790 }
11891
119- async navigateToHome ( ) : Promise < void > {
120- await this . page . goto ( '/' , { waitUntil : 'load' } ) ;
121- await this . waitForPageLoad ( ) ;
122- }
123-
12492 async navigateToLogin ( ) : Promise < void > {
125- await this . page . goto ( '/#/login' , { waitUntil : 'load' } ) ;
126- await this . waitForPageLoad ( ) ;
93+ await this . navigateToRoute ( '/login' ) ;
12794 // Wait for potential redirect to complete by checking URL change
128- await waitForUrlNotContaining ( this . page , '#/login' ) ;
95+ await this . waitForUrlNotContaining ( '#/login' ) ;
12996 }
13097
13198 async isHomeContentDisplayed ( ) : Promise < boolean > {
132- try {
133- await expect ( this . welcomeHeading ) . toBeVisible ( ) ;
134- return true ;
135- } catch {
136- return false ;
137- }
99+ return this . welcomeTitle . isVisible ( ) ;
138100 }
139101
140102 async isAnonymousUser ( ) : Promise < boolean > {
141- try {
142- await expect ( this . anonymousUserIndicator ) . toBeVisible ( ) ;
143- return true ;
144- } catch {
145- return false ;
146- }
103+ return this . anonymousUserIndicator . isVisible ( ) ;
147104 }
148105
149106 async clickZeppelinLogo ( ) : Promise < void > {
150- await this . zeppelinLogo . click ( ) ;
151- }
152-
153- async getCurrentURL ( ) : Promise < string > {
154- return this . page . url ( ) ;
155- }
156-
157- getCurrentPath ( ) : string {
158- return getCurrentPath ( this . page ) ;
159- }
160-
161- async getPageTitle ( ) : Promise < string > {
162- return this . page . title ( ) ;
107+ await this . zeppelinLogo . click ( { timeout : 15000 } ) ;
163108 }
164109
165110 async getWelcomeHeadingText ( ) : Promise < string > {
166- const text = await this . welcomeHeading . textContent ( ) ;
111+ const text = await this . welcomeTitle . textContent ( ) ;
167112 return text || '' ;
168113 }
169114
@@ -173,65 +118,48 @@ export class HomePage extends BasePage {
173118 }
174119
175120 async clickRefreshNotes ( ) : Promise < void > {
176- await this . refreshNoteButton . click ( ) ;
121+ await this . refreshNoteButton . click ( { timeout : 15000 } ) ;
177122 }
178123
179124 async isNotebookListVisible ( ) : Promise < boolean > {
180- return this . notebookList . isVisible ( ) ;
125+ return this . zeppelinNodeList . isVisible ( ) ;
181126 }
182127
183128 async clickCreateNewNote ( ) : Promise < void > {
184- await this . nodeList . createNewNoteLink . click ( ) ;
129+ await this . nodeList . createNewNoteLink . click ( { timeout : 15000 } ) ;
130+ await this . createNoteModal . waitFor ( { state : 'visible' } ) ;
185131 }
186132
187- async clickImportNote ( ) : Promise < void > {
188- await this . nodeList . importNoteLink . click ( ) ;
189- }
133+ async createNote ( notebookName : string ) : Promise < void > {
134+ await this . clickCreateNewNote ( ) ;
190135
191- async filterNotes ( searchTerm : string ) : Promise < void > {
192- await this . nodeList . filterInput . fill ( searchTerm ) ;
193- }
136+ // Wait for the modal form to be fully rendered with proper labels
137+ await this . page . waitForSelector ( 'nz-form-label' , { timeout : 10000 } ) ;
194138
195- async isRefreshIconSpinning ( ) : Promise < boolean > {
196- const spinAttribute = await this . refreshIcon . getAttribute ( 'nzSpin' ) ;
197- return spinAttribute === 'true' || spinAttribute === '' ;
198- }
139+ await this . waitForFormLabels ( [ 'Note Name' , 'Clone Note' ] ) ;
199140
200- async waitForRefreshToComplete ( ) : Promise < void > {
201- await this . page . waitForFunction (
202- ( ) => {
203- const icon = document . querySelector ( 'a.refresh-note i[nz-icon]' ) ;
204- return icon && ! icon . hasAttribute ( 'nzSpin' ) ;
205- } ,
206- { timeout : 10000 }
207- ) ;
141+ // Fill and verify the notebook name input
142+ await this . fillAndVerifyInput ( this . notebookNameInput , notebookName ) ;
143+
144+ // Click the 'Create' button in the modal
145+ await expect ( this . createNoteButton ) . toBeEnabled ( { timeout : 5000 } ) ;
146+ await this . createNoteButton . click ( { timeout : 15000 } ) ;
147+ await this . waitForPageLoad ( ) ;
208148 }
209149
210- async getDocumentationLinkHref ( ) : Promise < string | null > {
211- return this . externalLinks . documentation . getAttribute ( 'href' ) ;
150+ async clickImportNote ( ) : Promise < void > {
151+ await this . nodeList . importNoteLink . click ( { timeout : 15000 } ) ;
212152 }
213153
214- async areExternalLinksVisible ( ) : Promise < boolean > {
215- const links = [
216- this . externalLinks . documentation ,
217- this . externalLinks . mailingList ,
218- this . externalLinks . issuesTracking ,
219- this . externalLinks . github
220- ] ;
221-
222- for ( const link of links ) {
223- if ( ! ( await link . isVisible ( ) ) ) {
224- return false ;
225- }
226- }
227- return true ;
154+ async filterNotes ( searchTerm : string ) : Promise < void > {
155+ await this . nodeList . filterInput . fill ( searchTerm , { timeout : 15000 } ) ;
228156 }
229157
230- async isWelcomeSectionVisible ( ) : Promise < boolean > {
231- return this . welcomeSection . isVisible ( ) ;
158+ async waitForRefreshToComplete ( ) : Promise < void > {
159+ await this . waitForElementAttribute ( 'a.refresh-note i[nz-icon]' , 'nzSpin' , false ) ;
232160 }
233161
234- async isMoreInfoGridVisible ( ) : Promise < boolean > {
235- return this . moreInfoGrid . isVisible ( ) ;
162+ async getDocumentationLinkHref ( ) : Promise < string | null > {
163+ return this . externalLinks . documentation . getAttribute ( 'href' ) ;
236164 }
237165}
0 commit comments