ep_headings2 0.2.110 → 0.2.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "Adds heading support to Etherpad Lite. Includes improved suppot for export, i18n etc.",
3
3
  "name": "ep_headings2",
4
- "version": "0.2.110",
4
+ "version": "0.2.112",
5
5
  "author": {
6
6
  "name": "John McLear",
7
7
  "email": "john@mclear.co.uk"
@@ -34,7 +34,7 @@
34
34
  "url": "https://github.com/ether/ep_headings2/issues"
35
35
  },
36
36
  "dependencies": {
37
- "ep_plugin_helpers": "^0.2.7"
37
+ "ep_plugin_helpers": "^0.2.8"
38
38
  },
39
39
  "devDependencies": {
40
40
  "eslint": "^8.57.1",
@@ -0,0 +1,76 @@
1
+ import {expect, test} from '@playwright/test';
2
+ import {clearPadContent, getPadBody, goToNewPad, writeToPad}
3
+ from 'ep_etherpad-lite/tests/frontend-new/helper/padHelper';
4
+
5
+ test.beforeEach(async ({page}) => {
6
+ await goToNewPad(page);
7
+ });
8
+
9
+ test.describe('ep_headings2 - Set Heading and ensure its removed properly', () => {
10
+ test('Heading select has aria-label for accessibility', async ({page}) => {
11
+ const select = page.locator('#heading-selection');
12
+ await expect(select).toHaveAttribute('aria-label', /.+/);
13
+ });
14
+
15
+ test('Focus returns to editor after selecting a heading', async ({page}) => {
16
+ const padBody = await getPadBody(page);
17
+ await padBody.click();
18
+ await clearPadContent(page);
19
+ await writeToPad(page, 'Test focus');
20
+
21
+ // Pick H1 in the heading-selection <select>; the niceSelect wrapper
22
+ // intercepts native change events so we set the value on the
23
+ // underlying element and dispatch change manually, matching what
24
+ // the legacy spec did with chrome$('#heading-selection').change().
25
+ await page.evaluate(() => {
26
+ const sel = document.querySelector<HTMLSelectElement>('#heading-selection')!;
27
+ sel.value = '0';
28
+ sel.dispatchEvent(new Event('change', {bubbles: true}));
29
+ });
30
+
31
+ // The line gains an <h1> wrapper.
32
+ await expect(padBody.locator('div').first().locator('h1')).toHaveCount(1);
33
+
34
+ // Focus should return to the inner ace iframe (not the toolbar
35
+ // <select> the user just clicked). Verify by checking activeElement
36
+ // in the outer document is the ace_inner iframe.
37
+ const focusedFrameName = await page.evaluate(() => {
38
+ const ae = document.activeElement as HTMLElement | null;
39
+ return (ae?.tagName === 'IFRAME' && (ae as HTMLIFrameElement).name) || null;
40
+ });
41
+ expect(focusedFrameName).toBe('ace_outer');
42
+ });
43
+
44
+ test('Option select is changed when heading is changed', async ({page}) => {
45
+ const padBody = await getPadBody(page);
46
+ await padBody.click();
47
+ await clearPadContent(page);
48
+ await writeToPad(page, 'First Line!');
49
+
50
+ // Apply H1 to the first line.
51
+ await page.evaluate(() => {
52
+ const sel = document.querySelector<HTMLSelectElement>('#heading-selection')!;
53
+ sel.value = '0';
54
+ sel.dispatchEvent(new Event('change', {bubbles: true}));
55
+ });
56
+ await expect(padBody.locator('div').first().locator('h1')).toHaveCount(1);
57
+
58
+ // Move to a fresh second line — the selector should reset to
59
+ // "no heading" (-1) because the cursor is no longer on an H1.
60
+ await page.keyboard.press('End');
61
+ await page.keyboard.press('Enter');
62
+ await page.keyboard.type('Second Line');
63
+
64
+ // Wait for the selector to update to "-1" (Etherpad polls the
65
+ // current line's heading attribute on caret moves).
66
+ await expect.poll(async () =>
67
+ page.evaluate(() =>
68
+ (document.querySelector<HTMLSelectElement>('#heading-selection')!).value),
69
+ {timeout: 10_000}).toBe('-1');
70
+
71
+ // Second line is plain text, not wrapped in <h1>.
72
+ const second = padBody.locator('div').nth(1);
73
+ await expect(second.locator('h1')).toHaveCount(0);
74
+ await expect(second).toHaveText('Second Line');
75
+ });
76
+ });
@@ -1,73 +0,0 @@
1
- 'use strict';
2
-
3
- describe('ep_headings2 - Set Heading and ensure its removed properly', function () {
4
- // create a new pad before each test run
5
- beforeEach(function (cb) {
6
- helper.newPad(cb);
7
- this.timeout(60000);
8
- });
9
-
10
- // Create Pad
11
- // Check Default Text has no Heading
12
- // Set Line 1 heading and check it's set
13
- // Set Line 2 to null heading value and check it's set
14
-
15
- it('Heading select has aria-label for accessibility', async function () {
16
- this.timeout(60000);
17
- const chrome$ = helper.padChrome$;
18
- const $select = chrome$('#heading-selection');
19
- expect($select.attr('aria-label')).to.not.be(undefined);
20
- expect($select.attr('aria-label').length).to.be.greaterThan(0);
21
- });
22
-
23
- it('Focus returns to editor after selecting a heading', async function () {
24
- this.timeout(60000);
25
- const chrome$ = helper.padChrome$;
26
- const inner$ = helper.padInner$;
27
-
28
- // Type some text
29
- const $firstTextElement = inner$('div').first();
30
- $firstTextElement.sendkeys('{selectall}');
31
- $firstTextElement.sendkeys('Test focus');
32
-
33
- // Select heading 1
34
- chrome$('#heading-selection').val('0');
35
- chrome$('#heading-selection').change();
36
-
37
- // Wait for heading to be applied, then check focus is back in the editor
38
- await helper.waitForPromise(() => inner$('div').first().find('h1').length === 1);
39
-
40
- // The editor iframe should have focus, not the toolbar
41
- const editorHasFocus = inner$('div').first().is(':focus') ||
42
- inner$.document.hasFocus() ||
43
- $(helper.padOuter$.document).find('iframe[name="ace_inner"]').is(':focus');
44
- expect(editorHasFocus).to.be(true);
45
- });
46
-
47
- it('Option select is changed when heading is changed', async function () {
48
- this.timeout(60000);
49
- const chrome$ = helper.padChrome$;
50
- const inner$ = helper.padInner$;
51
-
52
- const $firstTextElement = inner$('div').first();
53
-
54
- const $editorContents = inner$('div');
55
- $editorContents.sendkeys('{selectall}');
56
- $firstTextElement.sendkeys('First Line!');
57
-
58
- // sets first line to h1
59
- chrome$('#heading-selection').val('0');
60
- chrome$('#heading-selection').change();
61
-
62
- $firstTextElement.sendkeys('{enter}');
63
-
64
- await helper.waitForPromise(() => chrome$('#heading-selection').val() === '0');
65
- inner$('div').first().sendkeys('{selectall}');
66
- const $secondElement = inner$('div').first().next();
67
- $secondElement.sendkeys('Second Line');
68
- $secondElement.sendkeys('{selectall}');
69
- await helper.waitForPromise(() => chrome$('#heading-selection').val() === '-1');
70
- expect($secondElement.find('h1').length).to.be(0);
71
- expect($secondElement.text()).to.be('Second Line');
72
- });
73
- });