Skip to content

Commit

Permalink
TINY-10871: replace placeholders with labels in Find & Replace dialog (
Browse files Browse the repository at this point in the history
…#9689)

* TINY-10871: change placeholders to labels and fix tests

* TINY-10871: changelog

* TINY-10871: improve phrasing in changelog

Co-authored-by: spocke <spocke@moxiecode.com>

* TINY-10871: use utils func in place

---------

Co-authored-by: spocke <spocke@moxiecode.com>
  • Loading branch information
ztomaszyk and spocke authored Jun 6, 2024
1 parent 6ce11b6 commit e7ef3b6
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 51 deletions.
7 changes: 7 additions & 0 deletions .changes/unreleased/tinymce-TINY-10871-2024-06-05.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project: tinymce
kind: Improved
body: Improved Find & Replace dialog accessibility by changing placeholders to
labels.
time: 2024-06-05T14:25:44.504736+02:00
custom:
Issue: TINY-10871
52 changes: 29 additions & 23 deletions modules/tinymce/src/plugins/searchreplace/main/ts/ui/Dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,37 +102,43 @@ const open = (editor: Editor, currentSearchState: Cell<Actions.SearchState>): vo
const getPanelItems = (error: boolean): Dialog.BodyComponentSpec[] => {
const items: Dialog.BodyComponentSpec[] = [
{
type: 'bar',
type: 'label',
label: 'Find',
for: 'findtext',
items: [
{
type: 'input',
name: 'findtext',
placeholder: 'Find',
maximized: true,
inputMode: 'search'
},
{
type: 'button',
name: 'prev',
text: 'Previous',
icon: 'action-prev',
enabled: false,
borderless: true
},
{
type: 'button',
name: 'next',
text: 'Next',
icon: 'action-next',
enabled: false,
borderless: true
type: 'bar',
items: [
{
type: 'input',
name: 'findtext',
maximized: true,
inputMode: 'search'
},
{
type: 'button',
name: 'prev',
text: 'Previous',
icon: 'action-prev',
enabled: false,
borderless: true
},
{
type: 'button',
name: 'next',
text: 'Next',
icon: 'action-next',
enabled: false,
borderless: true
}
]
}
]
},
{
type: 'input',
name: 'replacetext',
placeholder: 'Replace with',
label: 'Replace with',
inputMode: 'search'
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogCyclingTest',
base_url: '/project/tinymce/js/tinymce',
}, [ Plugin ]);

const findInputSelector = Utils.getFindInputSelector();

const assertMatchFound = (editor: Editor, index: number) => {
const matches = SelectorFilter.descendants(TinyDom.body(editor), '.mce-match-marker');
const elem = matches[index];
Expand All @@ -40,7 +42,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogCyclingTest',
editor.setContent('<p>fish fish fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 4);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'fish');
Utils.clickFind(editor);
assertMatchFound(editor, 0);
cycle(editor);
Expand All @@ -57,7 +59,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogCyclingTest',
editor.setContent('<p>fish Fish fish Fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 5, [ 0, 0 ], 9);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'Fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'Fish');
await Utils.pSelectPreference(editor, 'Match case');
Utils.clickFind(editor);
assertMatchFound(editor, 0);
Expand All @@ -74,7 +76,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogCyclingTest',
editor.setContent('<p>ttt TTT ttt ttttt</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 3);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'ttt');
await Utils.pAssertFieldValue(editor, findInputSelector, 'ttt');
await Utils.pSelectPreference(editor, 'Find whole words only');
Utils.clickFind(editor);
assertMatchFound(editor, 0);
Expand All @@ -93,7 +95,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogCyclingTest',
editor.setContent('<p>^^ ^^ ^^ fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 2);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', '^^');
await Utils.pAssertFieldValue(editor, findInputSelector, '^^');
Utils.clickFind(editor);
assertMatchFound(editor, 0);
cycle(editor);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApproxStructure, Assertions, UiFinder } from '@ephox/agar';
import { describe, it } from '@ephox/bedrock-client';
import { Css, Scroll } from '@ephox/sugar';
import { TinyAssertions, TinyDom, TinyHooks, TinySelections, TinyUiActions } from '@ephox/wrap-mcagar';
Expand All @@ -16,6 +17,8 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
base_url: '/project/tinymce/js/tinymce',
}, [ Plugin ]);

const findInputSelector = Utils.getFindInputSelector();

const assertFound = (editor: Editor, count: number) => TinyAssertions.assertContentPresence(editor, {
'.mce-match-marker': count
});
Expand All @@ -29,7 +32,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
const editor = hook.editor();
editor.setContent('<p>fish fish fish</p>');
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', '');
await Utils.pAssertFieldValue(editor, findInputSelector, '');
TinyUiActions.closeDialog(editor);
});

Expand All @@ -38,7 +41,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>fish fish fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 5, [ 0, 0 ], 9);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'fish');
findAndAssertFound(editor, 3);
TinyUiActions.closeDialog(editor);
});
Expand All @@ -48,7 +51,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>fish Fish fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 5, [ 0, 0 ], 9);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'Fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'Fish');
await Utils.pSelectPreference(editor, 'Match case');
findAndAssertFound(editor, 1);
await Utils.pSelectPreference(editor, 'Match case');
Expand All @@ -60,7 +63,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>ttt TTT ttt ttttt</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 3);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'ttt');
await Utils.pAssertFieldValue(editor, findInputSelector, 'ttt');
await Utils.pSelectPreference(editor, 'Find whole words only');
findAndAssertFound(editor, 3);
await Utils.pSelectPreference(editor, 'Find whole words only');
Expand All @@ -72,8 +75,8 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>ttt TTT ttt ttttt</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 7);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'ttt TTT');
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'ttt');
await Utils.pAssertFieldValue(editor, findInputSelector, 'ttt TTT');
await Utils.pSetFieldValue(editor, findInputSelector, 'ttt');
await Utils.pSelectPreference(editor, 'Find in selection');
findAndAssertFound(editor, 2);
TinyAssertions.assertSelection(editor, [ 0 ], 0, [ 0 ], 4);
Expand All @@ -86,7 +89,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>fish fish Fish fishy</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 5, [ 0, 0 ], 9);
await Utils.pOpenDialog(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'fish');
findAndAssertFound(editor, 4);
await Utils.pSelectPreference(editor, 'Match case');
assertFound(editor, 0);
Expand All @@ -101,7 +104,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
const editor = hook.editor();
editor.setContent('<p>fish fish fish</p>');
await Utils.pOpenDialogWithKeyboard(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', '');
await Utils.pAssertFieldValue(editor, findInputSelector, '');
TinyUiActions.closeDialog(editor);
});

Expand All @@ -110,7 +113,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
editor.setContent('<p>fish fish fish</p>');
TinySelections.setSelection(editor, [ 0, 0 ], 5, [ 0, 0 ], 9);
await Utils.pOpenDialogWithKeyboard(editor);
await Utils.pAssertFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pAssertFieldValue(editor, findInputSelector, 'fish');
findAndAssertFound(editor, 3);
TinyUiActions.closeDialog(editor);
});
Expand All @@ -130,7 +133,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
const editor = hook.editor();
editor.setContent('<p>tiny tiny tiny tiny</p>');
await Utils.pOpenDialog(editor);
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'tiny');
await Utils.pSetFieldValue(editor, findInputSelector, 'tiny');
findAndAssertFound(editor, 4);
await Utils.pSelectPreference(editor, 'Find in selection');
assertFound(editor, 0);
Expand All @@ -141,4 +144,87 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceDialogTest', () =>
assert.isFalse(await Utils.pAssertAlertInDialog(editor));
TinyUiActions.closeDialog(editor);
});

it('TINY-10871: Find label should point to the correct input through for attribute', async () => {
const editor = hook.editor();
editor.setContent('');
const dialog = await Utils.pOpenDialog(editor);

Assertions.assertStructure('Check dialog form content syructure',
ApproxStructure.build((s, str, arr) => s.element('div', {
classes: [ arr.has('tox-form') ],
children: [
s.element('div', {
classes: [ arr.has('tox-form__group') ],
children: [
s.element('label', {
attrs: {
for: str.startsWith('form-field')
},
children: [
s.text(str.is('Find'))
]
}),
s.element('div', {
classes: [ arr.has('tox-bar') ],
children: [
s.element('div', {
classes: [ arr.has('tox-form__group') ],
children: [
s.element('input', {
attrs: {
id: str.startsWith('form-field')
}
})
]
}),
s.element('div', {
classes: [ arr.has('tox-form__group') ],
children: [
s.element('button', {
attrs: {
'aria-label': str.is('Previous')
}
})
]
}),
s.element('div', {
classes: [ arr.has('tox-form__group') ],
children: [
s.element('button', {
attrs: {
'aria-label': str.is('Next')
}
})
]
})
]
})
]
}),
s.element('div', {
classes: [ arr.has('tox-form__group') ],
children: [
s.element('label', {
attrs: {
for: str.startsWith('form-field')
},
children: [
s.text(str.is('Replace with'))
]
}),
s.element('input', {
attrs: {
id: str.startsWith('form-field')
}
})
]
})
]
})),
UiFinder.findIn(dialog, '.tox-dialog__body-content .tox-form').getOrDie()
);

TinyUiActions.closeDialog(editor);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceKeyboardNavigationT

const doc = SugarDocument.getDocument();

const findInputSelector = Utils.getFindInputSelector();
const replaceWithInputSelector = Utils.getReplaceWithInputSelector();

const pressTab = (editor: Editor) => TinyUiActions.keydown(editor, Keys.tab());
const pressEsc = (editor: Editor) => TinyUiActions.keyup(editor, Keys.escape());
const pressDown = (editor: Editor) => TinyUiActions.keydown(editor, Keys.down());
Expand Down Expand Up @@ -50,9 +53,9 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceKeyboardNavigationT
it('TINY-3914: Dialog keyboard navigation', async () => {
const editor = hook.editor();
await Utils.pOpenDialog(editor);
await pAssertFocused('Find input', '.tox-textfield[placeholder="Find"]');
await pAssertFocused('Find input', findInputSelector);
pressTab(editor);
await pAssertFocused('Replace with input', '.tox-textfield[placeholder="Replace with"]');
await pAssertFocused('Replace with input', replaceWithInputSelector);
pressTab(editor);
await pAssertFocused('Placeholder menu button', '.tox-tbtn--select[aria-label="Preferences"]');
pressDown(editor);
Expand All @@ -68,33 +71,33 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplaceKeyboardNavigationT
const editor = hook.editor();
editor.setContent('<p>fish fish fish</p>');
await Utils.pOpenDialog(editor);
await pAssertFocused('Find input', '.tox-textfield[placeholder="Find"]');
await pAssertFocused('Find input', findInputSelector);
pressTab(editor);
await pAssertFocused('Replace with input', '.tox-textfield[placeholder="Replace with"]');
await pAssertFocused('Replace with input', replaceWithInputSelector);
pressTab(editor);
await pAssertFocused('Placeholder menu button', '.tox-tbtn--select[aria-label="Preferences"]');
pressTab(editor);
await pAssertFocused('Find button', '.tox-button[data-mce-name="Find"]');
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pSetFieldValue(editor, findInputSelector, 'fish');
pressEnter(editor);
pressTab(editor);
await pAssertFocused('Find button', '.tox-button[data-mce-name="Replace"]');
pressTab(editor);
await pAssertFocused('Find button', '.tox-button[data-mce-name="Replace all"]');
pressEnter(editor);
await pAssertFocused('Find input', '.tox-textfield[placeholder="Find"]');
await pAssertFocused('Find input', findInputSelector);
pressEsc(editor);
});

it('TINY-4014: Dialog keyboard focus is returned to find input after displaying an alert', async () => {
const editor = hook.editor();
editor.setContent('<p>fish fish fish</p>');
await Utils.pOpenDialog(editor);
await pAssertFocused('Find input', '.tox-textfield[placeholder="Find"]');
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'notfound');
await pAssertFocused('Find input', findInputSelector);
await Utils.pSetFieldValue(editor, findInputSelector, 'notfound');
pressEnter(editor);
await TinyUi(editor).pWaitForUi('.tox-notification.tox-notification--error:contains("Could not find the specified string.")');
await pAssertFocused('Find input', '.tox-textfield[placeholder="Find"]');
await pAssertFocused('Find input', findInputSelector);
pressEsc(editor);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplacePrevNextTest', () =
const editor = hook.editor();
editor.setContent('<p>fish fish fish</p>');
await Utils.pOpenDialog(editor);
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Find"]', 'fish');
await Utils.pSetFieldValue(editor, Utils.getFindInputSelector(), 'fish');
Utils.clickFind(editor);

// Initial button states for first match
Expand All @@ -51,7 +51,7 @@ describe('browser.tinymce.plugins.searchreplace.SearchReplacePrevNextTest', () =
await pAssertButtonsEnabled();

// replace all but one value and assert next/previous are disabled
await Utils.pSetFieldValue(editor, 'input.tox-textfield[placeholder="Replace with"]', 'squid');
await Utils.pSetFieldValue(editor, Utils.getReplaceWithInputSelector(), 'squid');
Utils.clickReplace(editor);
await pAssertButtonsEnabled();
Utils.clickReplace(editor);
Expand Down
Loading

0 comments on commit e7ef3b6

Please sign in to comment.