tbonelee commented on code in PR #5101: URL: https://github.com/apache/zeppelin/pull/5101#discussion_r2571568264
########## zeppelin-web-angular/e2e/models/notebook-action-bar-page.ts: ########## @@ -0,0 +1,130 @@ +/* + * 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 { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class NotebookActionBarPage extends BasePage { + readonly titleEditor: Locator; + readonly runAllButton: Locator; + readonly showHideCodeButton: Locator; + readonly showHideOutputButton: Locator; + readonly clearOutputButton: Locator; + readonly cloneButton: Locator; + readonly exportButton: Locator; + readonly reloadButton: Locator; + readonly collaborationModeToggle: Locator; + readonly personalModeButton: Locator; + readonly collaborationModeButton: Locator; + readonly commitButton: Locator; + readonly commitPopover: Locator; + readonly commitMessageInput: Locator; + readonly commitConfirmButton: Locator; + readonly setRevisionButton: Locator; + readonly compareRevisionsButton: Locator; + readonly revisionDropdown: Locator; + readonly revisionDropdownMenu: Locator; + readonly schedulerButton: Locator; + readonly schedulerDropdown: Locator; + readonly cronInput: Locator; + readonly cronPresets: Locator; + readonly shortcutInfoButton: Locator; + readonly interpreterSettingsButton: Locator; + readonly permissionsButton: Locator; + readonly lookAndFeelDropdown: Locator; + + constructor(page: Page) { + super(page); + this.titleEditor = page.locator('zeppelin-elastic-input'); + this.runAllButton = page.locator('button[nzTooltipTitle="Run all paragraphs"]'); + this.showHideCodeButton = page.locator('button[nzTooltipTitle="Show/hide the code"]'); + this.showHideOutputButton = page.locator('button[nzTooltipTitle="Show/hide the output"]'); + this.clearOutputButton = page.locator('button[nzTooltipTitle="Clear all output"]'); + this.cloneButton = page.locator('button[nzTooltipTitle="Clone this note"]'); + this.exportButton = page.locator('button[nzTooltipTitle="Export this note"]'); + this.reloadButton = page.locator('button[nzTooltipTitle="Reload from note file"]'); + this.collaborationModeToggle = page.locator('ng-container[ngSwitch="note.config.personalizedMode"]'); + this.personalModeButton = page.getByRole('button', { name: 'Personal' }); + this.collaborationModeButton = page.getByRole('button', { name: 'Collaboration' }); + this.commitButton = page.getByRole('button', { name: 'Commit' }); + this.commitPopover = page.locator('.ant-popover'); + this.commitMessageInput = page.locator('input[placeholder*="commit message"]'); + this.commitConfirmButton = page.locator('.ant-popover').getByRole('button', { name: 'OK' }); + this.setRevisionButton = page.getByRole('button', { name: 'Set as default revision' }); + this.compareRevisionsButton = page.getByRole('button', { name: 'Compare with current revision' }); + this.revisionDropdown = page.locator('button[nz-dropdown]').filter({ hasText: 'Revision' }); + this.revisionDropdownMenu = page.locator('nz-dropdown-menu'); + this.schedulerButton = page.locator('button[nz-dropdown]').filter({ hasText: 'Scheduler' }); + this.schedulerDropdown = page.locator('.scheduler-dropdown'); + this.cronInput = page.locator('input[placeholder*="cron"]'); + this.cronPresets = page.locator('.cron-preset'); + this.shortcutInfoButton = page.locator('.setting button:has(i[nzType="info-circle"])'); + this.interpreterSettingsButton = page.locator('.setting button:has(i[nzType="setting"])'); + this.permissionsButton = page.locator('.setting button:has(i[nzType="lock"])'); + this.lookAndFeelDropdown = page.locator('.setting button[nz-dropdown]:has(i[nzType="down"])'); + } + + async clickRunAll(): Promise<void> { + await this.runAllButton.click(); + } + + async toggleCodeVisibility(): Promise<void> { + await this.showHideCodeButton.click(); + } + + async toggleOutputVisibility(): Promise<void> { + await this.showHideOutputButton.click(); + } + + async clickClearOutput(): Promise<void> { + await this.clearOutputButton.click(); + } + async switchToPersonalMode(): Promise<void> { + await this.personalModeButton.click(); + } + + async switchToCollaborationMode(): Promise<void> { + await this.collaborationModeButton.click(); + } + + async openCommitPopover(): Promise<void> { + await this.commitButton.click(); + } + + async enterCommitMessage(message: string): Promise<void> { + await this.commitMessageInput.fill(message); + } + + async confirmCommit(): Promise<void> { + await this.commitConfirmButton.click(); + } + async openRevisionDropdown(): Promise<void> { + await this.revisionDropdown.click(); + } + + async openSchedulerDropdown(): Promise<void> { + await this.schedulerButton.click(); + } + + async isCodeVisible(): Promise<boolean> { + const icon = this.showHideCodeButton.locator('i[nz-icon] svg'); + const iconType = await icon.getAttribute('data-icon'); + console.log(icon, iconType); Review Comment: ```suggestion ``` ########## zeppelin-web-angular/e2e/models/folder-rename-page.ts: ########## @@ -0,0 +1,161 @@ +/* + * 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 { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class FolderRenamePage extends BasePage { + readonly folderList: Locator; + readonly renameMenuItem: Locator; + readonly renameModal: Locator; + readonly renameInput: Locator; + readonly confirmButton: Locator; + readonly cancelButton: Locator; + readonly validationError: Locator; + readonly deleteConfirmation: Locator; + readonly deleteConfirmButton: Locator; + readonly deleteCancelButton: Locator; + + constructor(page: Page) { + super(page); + this.folderList = page.locator('zeppelin-node-list'); + this.renameMenuItem = page.locator('a[nz-tooltip][nztooltiptitle="Rename folder"]').first(); + this.renameModal = page.locator('.ant-modal'); + this.renameInput = page.locator('input[placeholder="Insert New Name"]'); + this.confirmButton = page.getByRole('button', { name: 'Rename' }); + this.cancelButton = page.locator('.ant-modal-close-x'); // Modal close button + this.validationError = page.locator( + '.ant-form-item-explain, .error-message, .validation-error, .ant-form-item-explain-error' + ); + this.deleteConfirmation = page.locator('.ant-popover').filter({ hasText: 'This folder will be moved to trash.' }); + this.deleteConfirmButton = page.getByRole('button', { name: 'OK' }).last(); + this.deleteCancelButton = page.getByRole('button', { name: 'Cancel' }).last(); + } + + async hoverOverFolder(folderName: string): Promise<void> { + // Wait for the folder list to be loaded + await this.folderList.waitFor({ state: 'visible' }); + + // Find the folder node by locating the .node that contains the specific folder name + // Use a more reliable selector that targets the folder name exactly + const folderNode = this.page + .locator('.node') + .filter({ + has: this.page.locator('.folder .name', { hasText: folderName }) + }) + .first(); + + // Wait for the folder to be visible and hover over the entire .node container + await folderNode.waitFor({ state: 'visible' }); + await folderNode.hover(); + + // Wait for hover effects to take place by checking for interactive elements + await folderNode + .locator('a[nz-tooltip], i[nztype], button') + .first() + .waitFor({ + state: 'visible', + timeout: 2000 + }) + .catch(() => { + console.log('No interactive elements found after hover, continuing...'); + }); + } + + async clickDeleteIcon(folderName: string): Promise<void> { + // First hover over the folder to reveal the delete icon + await this.hoverOverFolder(folderName); + + // Find the specific folder node and its delete button + const folderNode = this.page + .locator('.node') + .filter({ + has: this.page.locator('.folder .name', { hasText: folderName }) + }) + .first(); + + const deleteIcon = folderNode.locator('a[nz-tooltip][nztooltiptitle="Move folder to Trash"]'); + await deleteIcon.click(); + } + + async clickRenameMenuItem(folderName: string): Promise<void> { + if (folderName) { + // Ensure the specific folder is hovered first + await this.hoverOverFolder(folderName); + + // Find the specific folder node and its rename button + const folderNode = this.page + .locator('.node') + .filter({ + has: this.page.locator('.folder .name', { hasText: folderName }) + }) + .first(); + + const renameIcon = folderNode.locator('a[nz-tooltip][nztooltiptitle="Rename folder"]'); + await renameIcon.click(); + + // Wait for modal to appear by checking for its presence + await this.renameModal.waitFor({ state: 'visible', timeout: 3000 }); + } else { + // Fallback to generic rename button (now using .first() to avoid strict mode) + await this.renameMenuItem.click(); + await this.renameModal.waitFor({ state: 'visible', timeout: 3000 }); + } + } + + async enterNewName(name: string): Promise<void> { + await this.renameInput.fill(name); + } + + async clearNewName(): Promise<void> { + await this.renameInput.clear(); + } + + async clickConfirm(): Promise<void> { + await this.confirmButton.click(); + + // Wait for validation or submission to process by monitoring modal state + await this.page + .waitForFunction( + () => { + // Check if modal is still open or if validation errors appeared + const modal = document.querySelector('.ant-modal-wrap'); + const validationErrors = document.querySelectorAll('.ant-form-item-explain-error, .has-error'); + + // If modal closed or validation errors appeared, processing is complete + return !modal || validationErrors.length > 0 || (modal && getComputedStyle(modal).display === 'none'); + }, + { timeout: 2000 } + ) + .catch(() => { + console.log('Modal state check timeout, continuing...'); + }); + } + + async clickCancel(): Promise<void> { + await this.cancelButton.click(); + } + + async isRenameModalVisible(): Promise<boolean> { + return this.renameModal.isVisible(); + } Review Comment: ```suggestion ``` ########## zeppelin-web-angular/pom.xml: ########## @@ -151,9 +151,15 @@ <configuration> <skip>${web.e2e.disabled}</skip> <target unless="skipTests"> - <exec executable="./zeppelin-daemon.sh" dir="${zeppelin.daemon.package.base}" spawn="false"> - <arg value="start" /> - </exec> + <condition property="zeppelin.notebook.dir" value="${env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR}"> + <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> + </condition> Review Comment: ```suggestion <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> </condition> ``` ########## zeppelin-web-angular/pom.xml: ########## @@ -151,9 +151,15 @@ <configuration> <skip>${web.e2e.disabled}</skip> <target unless="skipTests"> - <exec executable="./zeppelin-daemon.sh" dir="${zeppelin.daemon.package.base}" spawn="false"> - <arg value="start" /> - </exec> + <condition property="zeppelin.notebook.dir" value="${env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR}"> + <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> + </condition> Review Comment: ```suggestion <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> </condition> ``` ########## zeppelin-web-angular/e2e/models/notebook-action-bar-page.ts: ########## @@ -0,0 +1,130 @@ +/* + * 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 { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class NotebookActionBarPage extends BasePage { + readonly titleEditor: Locator; + readonly runAllButton: Locator; + readonly showHideCodeButton: Locator; + readonly showHideOutputButton: Locator; + readonly clearOutputButton: Locator; + readonly cloneButton: Locator; + readonly exportButton: Locator; + readonly reloadButton: Locator; + readonly collaborationModeToggle: Locator; + readonly personalModeButton: Locator; + readonly collaborationModeButton: Locator; + readonly commitButton: Locator; + readonly commitPopover: Locator; + readonly commitMessageInput: Locator; + readonly commitConfirmButton: Locator; + readonly setRevisionButton: Locator; + readonly compareRevisionsButton: Locator; + readonly revisionDropdown: Locator; + readonly revisionDropdownMenu: Locator; + readonly schedulerButton: Locator; + readonly schedulerDropdown: Locator; + readonly cronInput: Locator; + readonly cronPresets: Locator; + readonly shortcutInfoButton: Locator; + readonly interpreterSettingsButton: Locator; + readonly permissionsButton: Locator; + readonly lookAndFeelDropdown: Locator; + + constructor(page: Page) { + super(page); + this.titleEditor = page.locator('zeppelin-elastic-input'); + this.runAllButton = page.locator('button[nzTooltipTitle="Run all paragraphs"]'); + this.showHideCodeButton = page.locator('button[nzTooltipTitle="Show/hide the code"]'); + this.showHideOutputButton = page.locator('button[nzTooltipTitle="Show/hide the output"]'); + this.clearOutputButton = page.locator('button[nzTooltipTitle="Clear all output"]'); + this.cloneButton = page.locator('button[nzTooltipTitle="Clone this note"]'); + this.exportButton = page.locator('button[nzTooltipTitle="Export this note"]'); + this.reloadButton = page.locator('button[nzTooltipTitle="Reload from note file"]'); + this.collaborationModeToggle = page.locator('ng-container[ngSwitch="note.config.personalizedMode"]'); + this.personalModeButton = page.getByRole('button', { name: 'Personal' }); + this.collaborationModeButton = page.getByRole('button', { name: 'Collaboration' }); + this.commitButton = page.getByRole('button', { name: 'Commit' }); + this.commitPopover = page.locator('.ant-popover'); + this.commitMessageInput = page.locator('input[placeholder*="commit message"]'); + this.commitConfirmButton = page.locator('.ant-popover').getByRole('button', { name: 'OK' }); + this.setRevisionButton = page.getByRole('button', { name: 'Set as default revision' }); + this.compareRevisionsButton = page.getByRole('button', { name: 'Compare with current revision' }); + this.revisionDropdown = page.locator('button[nz-dropdown]').filter({ hasText: 'Revision' }); + this.revisionDropdownMenu = page.locator('nz-dropdown-menu'); + this.schedulerButton = page.locator('button[nz-dropdown]').filter({ hasText: 'Scheduler' }); + this.schedulerDropdown = page.locator('.scheduler-dropdown'); + this.cronInput = page.locator('input[placeholder*="cron"]'); + this.cronPresets = page.locator('.cron-preset'); + this.shortcutInfoButton = page.locator('.setting button:has(i[nzType="info-circle"])'); + this.interpreterSettingsButton = page.locator('.setting button:has(i[nzType="setting"])'); + this.permissionsButton = page.locator('.setting button:has(i[nzType="lock"])'); + this.lookAndFeelDropdown = page.locator('.setting button[nz-dropdown]:has(i[nzType="down"])'); + } + + async clickRunAll(): Promise<void> { + await this.runAllButton.click(); + } + + async toggleCodeVisibility(): Promise<void> { + await this.showHideCodeButton.click(); + } + + async toggleOutputVisibility(): Promise<void> { + await this.showHideOutputButton.click(); + } + + async clickClearOutput(): Promise<void> { + await this.clearOutputButton.click(); + } + async switchToPersonalMode(): Promise<void> { + await this.personalModeButton.click(); + } + + async switchToCollaborationMode(): Promise<void> { + await this.collaborationModeButton.click(); + } + + async openCommitPopover(): Promise<void> { + await this.commitButton.click(); + } + + async enterCommitMessage(message: string): Promise<void> { + await this.commitMessageInput.fill(message); + } + + async confirmCommit(): Promise<void> { + await this.commitConfirmButton.click(); + } Review Comment: ```suggestion } ``` ########## zeppelin-web-angular/pom.xml: ########## @@ -151,9 +151,15 @@ <configuration> <skip>${web.e2e.disabled}</skip> <target unless="skipTests"> - <exec executable="./zeppelin-daemon.sh" dir="${zeppelin.daemon.package.base}" spawn="false"> - <arg value="start" /> - </exec> + <condition property="zeppelin.notebook.dir" value="${env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR}"> + <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> + </condition> Review Comment: ```suggestion <isset property="env.ZEPPELIN_E2E_TEST_NOTEBOOK_DIR" /> </condition> ``` ########## zeppelin-web-angular/e2e/models/notebook-action-bar-page.ts: ########## @@ -0,0 +1,130 @@ +/* + * 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 { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class NotebookActionBarPage extends BasePage { + readonly titleEditor: Locator; + readonly runAllButton: Locator; + readonly showHideCodeButton: Locator; + readonly showHideOutputButton: Locator; + readonly clearOutputButton: Locator; + readonly cloneButton: Locator; + readonly exportButton: Locator; + readonly reloadButton: Locator; + readonly collaborationModeToggle: Locator; + readonly personalModeButton: Locator; + readonly collaborationModeButton: Locator; + readonly commitButton: Locator; + readonly commitPopover: Locator; + readonly commitMessageInput: Locator; + readonly commitConfirmButton: Locator; + readonly setRevisionButton: Locator; + readonly compareRevisionsButton: Locator; + readonly revisionDropdown: Locator; + readonly revisionDropdownMenu: Locator; + readonly schedulerButton: Locator; + readonly schedulerDropdown: Locator; + readonly cronInput: Locator; + readonly cronPresets: Locator; + readonly shortcutInfoButton: Locator; + readonly interpreterSettingsButton: Locator; + readonly permissionsButton: Locator; + readonly lookAndFeelDropdown: Locator; + + constructor(page: Page) { + super(page); + this.titleEditor = page.locator('zeppelin-elastic-input'); + this.runAllButton = page.locator('button[nzTooltipTitle="Run all paragraphs"]'); + this.showHideCodeButton = page.locator('button[nzTooltipTitle="Show/hide the code"]'); + this.showHideOutputButton = page.locator('button[nzTooltipTitle="Show/hide the output"]'); + this.clearOutputButton = page.locator('button[nzTooltipTitle="Clear all output"]'); + this.cloneButton = page.locator('button[nzTooltipTitle="Clone this note"]'); + this.exportButton = page.locator('button[nzTooltipTitle="Export this note"]'); + this.reloadButton = page.locator('button[nzTooltipTitle="Reload from note file"]'); + this.collaborationModeToggle = page.locator('ng-container[ngSwitch="note.config.personalizedMode"]'); + this.personalModeButton = page.getByRole('button', { name: 'Personal' }); + this.collaborationModeButton = page.getByRole('button', { name: 'Collaboration' }); + this.commitButton = page.getByRole('button', { name: 'Commit' }); + this.commitPopover = page.locator('.ant-popover'); + this.commitMessageInput = page.locator('input[placeholder*="commit message"]'); + this.commitConfirmButton = page.locator('.ant-popover').getByRole('button', { name: 'OK' }); + this.setRevisionButton = page.getByRole('button', { name: 'Set as default revision' }); + this.compareRevisionsButton = page.getByRole('button', { name: 'Compare with current revision' }); + this.revisionDropdown = page.locator('button[nz-dropdown]').filter({ hasText: 'Revision' }); + this.revisionDropdownMenu = page.locator('nz-dropdown-menu'); + this.schedulerButton = page.locator('button[nz-dropdown]').filter({ hasText: 'Scheduler' }); + this.schedulerDropdown = page.locator('.scheduler-dropdown'); + this.cronInput = page.locator('input[placeholder*="cron"]'); + this.cronPresets = page.locator('.cron-preset'); + this.shortcutInfoButton = page.locator('.setting button:has(i[nzType="info-circle"])'); + this.interpreterSettingsButton = page.locator('.setting button:has(i[nzType="setting"])'); + this.permissionsButton = page.locator('.setting button:has(i[nzType="lock"])'); + this.lookAndFeelDropdown = page.locator('.setting button[nz-dropdown]:has(i[nzType="down"])'); + } + + async clickRunAll(): Promise<void> { + await this.runAllButton.click(); + } + + async toggleCodeVisibility(): Promise<void> { + await this.showHideCodeButton.click(); + } + + async toggleOutputVisibility(): Promise<void> { + await this.showHideOutputButton.click(); + } + + async clickClearOutput(): Promise<void> { + await this.clearOutputButton.click(); + } Review Comment: ```suggestion } ``` ########## zeppelin-web-angular/e2e/models/notebook-action-bar-page.ts: ########## @@ -0,0 +1,130 @@ +/* + * 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 { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class NotebookActionBarPage extends BasePage { + readonly titleEditor: Locator; + readonly runAllButton: Locator; + readonly showHideCodeButton: Locator; + readonly showHideOutputButton: Locator; + readonly clearOutputButton: Locator; + readonly cloneButton: Locator; + readonly exportButton: Locator; + readonly reloadButton: Locator; + readonly collaborationModeToggle: Locator; + readonly personalModeButton: Locator; + readonly collaborationModeButton: Locator; + readonly commitButton: Locator; + readonly commitPopover: Locator; + readonly commitMessageInput: Locator; + readonly commitConfirmButton: Locator; + readonly setRevisionButton: Locator; + readonly compareRevisionsButton: Locator; + readonly revisionDropdown: Locator; + readonly revisionDropdownMenu: Locator; + readonly schedulerButton: Locator; + readonly schedulerDropdown: Locator; + readonly cronInput: Locator; + readonly cronPresets: Locator; + readonly shortcutInfoButton: Locator; + readonly interpreterSettingsButton: Locator; + readonly permissionsButton: Locator; + readonly lookAndFeelDropdown: Locator; + + constructor(page: Page) { + super(page); + this.titleEditor = page.locator('zeppelin-elastic-input'); + this.runAllButton = page.locator('button[nzTooltipTitle="Run all paragraphs"]'); + this.showHideCodeButton = page.locator('button[nzTooltipTitle="Show/hide the code"]'); + this.showHideOutputButton = page.locator('button[nzTooltipTitle="Show/hide the output"]'); + this.clearOutputButton = page.locator('button[nzTooltipTitle="Clear all output"]'); + this.cloneButton = page.locator('button[nzTooltipTitle="Clone this note"]'); + this.exportButton = page.locator('button[nzTooltipTitle="Export this note"]'); + this.reloadButton = page.locator('button[nzTooltipTitle="Reload from note file"]'); + this.collaborationModeToggle = page.locator('ng-container[ngSwitch="note.config.personalizedMode"]'); + this.personalModeButton = page.getByRole('button', { name: 'Personal' }); + this.collaborationModeButton = page.getByRole('button', { name: 'Collaboration' }); + this.commitButton = page.getByRole('button', { name: 'Commit' }); + this.commitPopover = page.locator('.ant-popover'); + this.commitMessageInput = page.locator('input[placeholder*="commit message"]'); + this.commitConfirmButton = page.locator('.ant-popover').getByRole('button', { name: 'OK' }); + this.setRevisionButton = page.getByRole('button', { name: 'Set as default revision' }); + this.compareRevisionsButton = page.getByRole('button', { name: 'Compare with current revision' }); + this.revisionDropdown = page.locator('button[nz-dropdown]').filter({ hasText: 'Revision' }); + this.revisionDropdownMenu = page.locator('nz-dropdown-menu'); + this.schedulerButton = page.locator('button[nz-dropdown]').filter({ hasText: 'Scheduler' }); + this.schedulerDropdown = page.locator('.scheduler-dropdown'); + this.cronInput = page.locator('input[placeholder*="cron"]'); + this.cronPresets = page.locator('.cron-preset'); + this.shortcutInfoButton = page.locator('.setting button:has(i[nzType="info-circle"])'); + this.interpreterSettingsButton = page.locator('.setting button:has(i[nzType="setting"])'); + this.permissionsButton = page.locator('.setting button:has(i[nzType="lock"])'); + this.lookAndFeelDropdown = page.locator('.setting button[nz-dropdown]:has(i[nzType="down"])'); + } + + async clickRunAll(): Promise<void> { + await this.runAllButton.click(); + } + + async toggleCodeVisibility(): Promise<void> { + await this.showHideCodeButton.click(); + } + + async toggleOutputVisibility(): Promise<void> { + await this.showHideOutputButton.click(); + } + + async clickClearOutput(): Promise<void> { + await this.clearOutputButton.click(); + } Review Comment: ```suggestion } ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
