| /* |
| * 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 { test, expect } from '@playwright/test'; |
| import { NoteTocPage } from '../../../models/note-toc-page'; |
| import { NoteTocPageUtil } from '../../../models/note-toc-page.util'; |
| import { addPageAnnotationBeforeEach, PAGES, waitForZeppelinReady, createTestNotebook } from '../../../utils'; |
| |
| test.describe('Note Table of Contents', () => { |
| // JUSTIFIED: page objects and notebook ids are stored in describe scope; fullyParallel can overwrite them. |
| test.describe.configure({ mode: 'default' }); |
| |
| let noteTocPage: NoteTocPage; |
| let noteTocUtil: NoteTocPageUtil; |
| let testNotebook: { noteId: string; paragraphId: string }; |
| |
| addPageAnnotationBeforeEach(PAGES.SHARE.NOTE_TOC); |
| |
| test.beforeEach(async ({ page }) => { |
| noteTocPage = new NoteTocPage(page); |
| noteTocUtil = new NoteTocPageUtil(noteTocPage); |
| |
| await page.goto('/#/'); |
| await waitForZeppelinReady(page); |
| |
| testNotebook = await createTestNotebook(page); |
| |
| // Use the more robust navigation method from parent class |
| await noteTocPage.navigateToNotebook(testNotebook.noteId); |
| |
| // Verify we're actually in a notebook with more specific checks |
| await expect(page).toHaveURL(new RegExp(`#/notebook/${testNotebook.noteId}`)); |
| // JUSTIFIED: test notebook always has exactly one paragraph |
| await expect(page.locator('zeppelin-notebook-paragraph').first()).toBeVisible({ timeout: 15000 }); |
| |
| // Only proceed if TOC button exists (confirms notebook context) |
| await expect(noteTocPage.tocToggleButton).toBeVisible({ timeout: 10000 }); |
| }); |
| |
| test('Given TOC panel is open, When checking panel title, Then title should display "Table of Contents"', async () => { |
| await noteTocUtil.verifyTocPanelOpens(); |
| await expect(noteTocPage.tocTitle).toBeVisible(); |
| await expect(noteTocPage.tocTitle).toHaveText('Table of Contents'); |
| }); |
| |
| test('Given TOC panel is open with no headings, When checking content, Then empty message should be displayed', async () => { |
| await noteTocUtil.verifyTocPanelOpens(); |
| await expect(noteTocPage.tocEmptyMessage).toBeVisible(); |
| }); |
| |
| test('Given TOC panel is open, When clicking close button, Then TOC panel should close', async () => { |
| await noteTocUtil.verifyTocPanelOpens(); |
| await noteTocUtil.verifyTocPanelCloses(); |
| }); |
| |
| test('Given TOC toggle button exists, When checking button visibility, Then button should be visible, enabled, and labeled', async () => { |
| await expect(noteTocPage.tocToggleButton).toBeVisible(); |
| await expect(noteTocPage.tocToggleButton).toBeEnabled(); |
| await expect(noteTocPage.tocToggleButton).toHaveAttribute('aria-label', 'Toggle Table of Contents'); |
| }); |
| |
| test('Given TOC panel can be toggled, When opening and closing multiple times, Then panel should respond consistently', async () => { |
| await noteTocUtil.verifyTocPanelOpens(); |
| await noteTocUtil.verifyTocPanelCloses(); |
| await noteTocUtil.verifyTocPanelOpens(); |
| await noteTocUtil.verifyTocPanelCloses(); |
| }); |
| }); |