mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-06 17:57:51 +02:00
✅(frontend) cover present from block
Exercise block-to-slide mapping and the editor side-menu action. Keep coverage scoped to starting the presenter from a block.
This commit is contained in:
@@ -382,6 +382,27 @@ test.describe('Presenter Mode', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('opens the presenter at the targeted slide from a block side menu', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await createDoc(page, 'presenter-side-menu', browserName, 1);
|
||||
await writeMultiSlideDoc(page);
|
||||
|
||||
await page
|
||||
.locator('.bn-block-outer')
|
||||
.filter({ hasText: 'Slide two' })
|
||||
.first()
|
||||
.hover();
|
||||
await page.locator('.bn-side-menu > button').last().click();
|
||||
await page.getByRole('menuitem', { name: 'Present from here' }).click();
|
||||
|
||||
const overlay = page.getByRole('dialog', { name: 'Presenter mode' });
|
||||
await expect(overlay).toBeVisible();
|
||||
await expect(overlay.getByText('3 / 4')).toBeVisible();
|
||||
await expect(overlay.getByText('Slide two')).toBeVisible();
|
||||
});
|
||||
|
||||
test('opens presenter deep-links and normalizes slide params', async ({
|
||||
page,
|
||||
browserName,
|
||||
|
||||
+137
-4
@@ -1,6 +1,10 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { getSlideTitle, splitBlocksIntoSlides } from '../hooks/useSlides';
|
||||
import {
|
||||
getContentSlideIndexForBlock,
|
||||
getSlideTitle,
|
||||
splitBlocksIntoSlides,
|
||||
} from '../hooks/useSlides';
|
||||
import type { PresenterBlock } from '../types';
|
||||
|
||||
type TestBlock = PresenterBlock;
|
||||
@@ -23,13 +27,14 @@ const textContent = (text: string) => ({
|
||||
type: 'text' as const,
|
||||
});
|
||||
|
||||
const para = (text = 'hello'): TestBlock =>
|
||||
const para = (text = 'hello', id?: string): TestBlock =>
|
||||
block('paragraph', {
|
||||
content: text === '' ? [] : [textContent(text)],
|
||||
...(id ? { id } : {}),
|
||||
});
|
||||
|
||||
const divider = (children: TestBlock[] = []): TestBlock =>
|
||||
block('divider', { children });
|
||||
const divider = (children: TestBlock[] = [], id?: string): TestBlock =>
|
||||
block('divider', { children, ...(id ? { id } : {}) });
|
||||
|
||||
const image = (): TestBlock => block('image', { props: { url: 'x' } });
|
||||
|
||||
@@ -201,6 +206,134 @@ describe('splitBlocksIntoSlides', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getContentSlideIndexForBlock', () => {
|
||||
test('returns the slide containing a regular block', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[para('a', 'a'), divider(), para('b', 'b'), para('c', 'c')],
|
||||
'c',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('returns the following slide for a divider', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[para('a', 'a'), divider(undefined, 'divider'), para('b', 'b')],
|
||||
'divider',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('returns the first non-empty following slide for consecutive dividers', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[
|
||||
para('a', 'a'),
|
||||
divider(undefined, 'first-divider'),
|
||||
divider(undefined, 'second-divider'),
|
||||
para('b', 'b'),
|
||||
],
|
||||
'first-divider',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('skips empty-only slides after dividers when mapping divider links', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[
|
||||
para('a', 'a'),
|
||||
divider(undefined, 'first-divider'),
|
||||
para('', 'empty-after-divider'),
|
||||
divider(undefined, 'second-divider'),
|
||||
para('b', 'b'),
|
||||
],
|
||||
'first-divider',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('maps a stripped empty block after a divider to the following content slide', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[
|
||||
para('a', 'a'),
|
||||
divider(undefined, 'divider'),
|
||||
para('', 'empty-after-divider'),
|
||||
para('b', 'b'),
|
||||
],
|
||||
'empty-after-divider',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('maps a stripped empty block before a divider to the previous content slide', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[
|
||||
para('a', 'a'),
|
||||
para('', 'empty-before-divider'),
|
||||
divider(undefined, 'divider'),
|
||||
para('b', 'b'),
|
||||
],
|
||||
'empty-before-divider',
|
||||
),
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('maps a stripped empty-only slide to the next rendered content slide', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[
|
||||
para('a', 'a'),
|
||||
divider(undefined, 'first-divider'),
|
||||
para('', 'empty-between-dividers'),
|
||||
divider(undefined, 'second-divider'),
|
||||
para('b', 'b'),
|
||||
],
|
||||
'empty-between-dividers',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('maps a leading divider to the first content slide', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[divider(undefined, 'divider'), para('a', 'a')],
|
||||
'divider',
|
||||
),
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('maps a trailing divider to the last rendered content slide', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[para('a', 'a'), divider(undefined, 'divider')],
|
||||
'divider',
|
||||
),
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('finds blocks nested under a structural divider', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[para('a', 'a'), divider([para('nested', 'nested')], 'divider')],
|
||||
'nested',
|
||||
),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('returns the first content slide when the block is missing', () => {
|
||||
expect(
|
||||
getContentSlideIndexForBlock(
|
||||
[para('a', 'a'), divider(), para('b', 'b')],
|
||||
'x',
|
||||
),
|
||||
).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
const heading = (text: string): TestBlock =>
|
||||
block('heading', { content: [textContent(text)] });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user