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]

Reply via email to