blob: 872784dfa06e9db4c19f6709ee26400553ead216 [file] [log] [blame]
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { expect, Locator, Page } from '@playwright/test';
import { getCurrentPath, waitForUrlNotContaining } from '../utils';
import { BasePage } from './base-page';
export class HomePage extends BasePage {
readonly welcomeHeading: Locator;
readonly notebookSection: Locator;
readonly helpSection: Locator;
readonly communitySection: Locator;
readonly createNewNoteButton: Locator;
readonly importNoteButton: Locator;
readonly searchInput: Locator;
readonly filterInput: Locator;
readonly zeppelinLogo: Locator;
readonly anonymousUserIndicator: Locator;
readonly welcomeSection: Locator;
readonly moreInfoGrid: Locator;
readonly notebookColumn: Locator;
readonly helpCommunityColumn: Locator;
readonly welcomeDescription: Locator;
readonly refreshNoteButton: Locator;
readonly refreshIcon: Locator;
readonly notebookList: Locator;
readonly notebookHeading: Locator;
readonly helpHeading: Locator;
readonly communityHeading: Locator;
readonly externalLinks: {
documentation: Locator;
mailingList: Locator;
issuesTracking: Locator;
github: Locator;
};
readonly nodeList: {
createNewNoteLink: Locator;
importNoteLink: Locator;
filterInput: Locator;
tree: Locator;
noteActions: {
renameNote: Locator;
clearOutput: Locator;
moveToTrash: Locator;
};
folderActions: {
createNote: Locator;
renameFolder: Locator;
moveToTrash: Locator;
};
trashActions: {
restoreAll: Locator;
emptyAll: Locator;
};
};
constructor(page: Page) {
super(page);
this.welcomeHeading = page.locator('h1', { hasText: 'Welcome to Zeppelin!' });
this.notebookSection = page.locator('text=Notebook').first();
this.helpSection = page.locator('text=Help').first();
this.communitySection = page.locator('text=Community').first();
this.createNewNoteButton = page.locator('text=Create new Note');
this.importNoteButton = page.locator('text=Import Note');
this.searchInput = page.locator('textbox', { hasText: 'Search' });
this.filterInput = page.locator('input[placeholder*="Filter"]');
this.zeppelinLogo = page.locator('text=Zeppelin').first();
this.anonymousUserIndicator = page.locator('text=anonymous');
this.welcomeSection = page.locator('.welcome');
this.moreInfoGrid = page.locator('.more-info');
this.notebookColumn = page.locator('[nz-col]').first();
this.helpCommunityColumn = page.locator('[nz-col]').last();
this.welcomeDescription = page.locator('.welcome').getByText('Zeppelin is web-based notebook');
this.refreshNoteButton = page.locator('a.refresh-note');
this.refreshIcon = page.locator('a.refresh-note i[nz-icon]');
this.notebookList = page.locator('zeppelin-node-list');
this.notebookHeading = this.notebookColumn.locator('h3');
this.helpHeading = page.locator('h3').filter({ hasText: 'Help' });
this.communityHeading = page.locator('h3').filter({ hasText: 'Community' });
this.externalLinks = {
documentation: page.locator('a[href*="zeppelin.apache.org/docs"]'),
mailingList: page.locator('a[href*="community.html"]'),
issuesTracking: page.locator('a[href*="issues.apache.org"]'),
github: page.locator('a[href*="github.com/apache/zeppelin"]')
};
this.nodeList = {
createNewNoteLink: page.locator('zeppelin-node-list a').filter({ hasText: 'Create new Note' }),
importNoteLink: page.locator('zeppelin-node-list a').filter({ hasText: 'Import Note' }),
filterInput: page.locator('zeppelin-node-list input[placeholder*="Filter"]'),
tree: page.locator('zeppelin-node-list nz-tree'),
noteActions: {
renameNote: page.locator('.file .operation a[nztooltiptitle*="Rename note"]'),
clearOutput: page.locator('.file .operation a[nztooltiptitle*="Clear output"]'),
moveToTrash: page.locator('.file .operation a[nztooltiptitle*="Move note to Trash"]')
},
folderActions: {
createNote: page.locator('.folder .operation a[nztooltiptitle*="Create new note"]'),
renameFolder: page.locator('.folder .operation a[nztooltiptitle*="Rename folder"]'),
moveToTrash: page.locator('.folder .operation a[nztooltiptitle*="Move folder to Trash"]')
},
trashActions: {
restoreAll: page.locator('.folder .operation a[nztooltiptitle*="Restore all"]'),
emptyAll: page.locator('.folder .operation a[nztooltiptitle*="Empty all"]')
}
};
}
async navigateToHome(): Promise<void> {
await this.page.goto('/', { waitUntil: 'load' });
await this.waitForPageLoad();
}
async navigateToLogin(): Promise<void> {
await this.page.goto('/#/login', { waitUntil: 'load' });
await this.waitForPageLoad();
// Wait for potential redirect to complete by checking URL change
await waitForUrlNotContaining(this.page, '#/login');
}
async isHomeContentDisplayed(): Promise<boolean> {
try {
await expect(this.welcomeHeading).toBeVisible();
return true;
} catch {
return false;
}
}
async isAnonymousUser(): Promise<boolean> {
try {
await expect(this.anonymousUserIndicator).toBeVisible();
return true;
} catch {
return false;
}
}
async clickZeppelinLogo(): Promise<void> {
await this.zeppelinLogo.click();
}
async getCurrentURL(): Promise<string> {
return this.page.url();
}
getCurrentPath(): string {
return getCurrentPath(this.page);
}
async getPageTitle(): Promise<string> {
return this.page.title();
}
async getWelcomeHeadingText(): Promise<string> {
const text = await this.welcomeHeading.textContent();
return text || '';
}
async getWelcomeDescriptionText(): Promise<string> {
const text = await this.welcomeDescription.textContent();
return text || '';
}
async clickRefreshNotes(): Promise<void> {
await this.refreshNoteButton.click();
}
async isNotebookListVisible(): Promise<boolean> {
return this.notebookList.isVisible();
}
async clickCreateNewNote(): Promise<void> {
await this.nodeList.createNewNoteLink.click();
}
async clickImportNote(): Promise<void> {
await this.nodeList.importNoteLink.click();
}
async filterNotes(searchTerm: string): Promise<void> {
await this.nodeList.filterInput.fill(searchTerm);
}
async isRefreshIconSpinning(): Promise<boolean> {
const spinAttribute = await this.refreshIcon.getAttribute('nzSpin');
return spinAttribute === 'true' || spinAttribute === '';
}
async waitForRefreshToComplete(): Promise<void> {
await this.page.waitForFunction(
() => {
const icon = document.querySelector('a.refresh-note i[nz-icon]');
return icon && !icon.hasAttribute('nzSpin');
},
{ timeout: 10000 }
);
}
async getDocumentationLinkHref(): Promise<string | null> {
return this.externalLinks.documentation.getAttribute('href');
}
async areExternalLinksVisible(): Promise<boolean> {
const links = [
this.externalLinks.documentation,
this.externalLinks.mailingList,
this.externalLinks.issuesTracking,
this.externalLinks.github
];
for (const link of links) {
if (!(await link.isVisible())) {
return false;
}
}
return true;
}
async isWelcomeSectionVisible(): Promise<boolean> {
return this.welcomeSection.isVisible();
}
async isMoreInfoGridVisible(): Promise<boolean> {
return this.moreInfoGrid.isVisible();
}
}