Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a801265
feat: add insertValue method
IslamRustamov Feb 1, 2026
7151d8d
fix: clamp start and end in insertValue
kacperzolkiewski Feb 10, 2026
ae3f3a2
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Feb 10, 2026
d54ccd5
fix: clamp start and end in insertValue on Android
kacperzolkiewski Feb 10, 2026
af3e5b6
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Mar 9, 2026
27cc3d5
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Mar 31, 2026
cd2cfa5
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Apr 2, 2026
8b6487b
fix: refactor inserting value
kacperzolkiewski Apr 2, 2026
e580611
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Jul 24, 2026
375e0f4
fix: inserting text into empty paragraph styled line
kacperzolkiewski Jul 27, 2026
1aee6c3
fix(android): inserting paragraph styles
kacperzolkiewski Jul 29, 2026
34fc2f1
fix: code review fixes
kacperzolkiewski Jul 29, 2026
5b46a8a
test: add e2e tests for insertValue
kacperzolkiewski Jul 29, 2026
dc6ef45
test: update screenshots for max test screen
kacperzolkiewski Jul 29, 2026
3f0bc33
docs: add insertValue description to api reference
kacperzolkiewski Jul 29, 2026
ebe9b00
feat(web): add support for insertValue
kacperzolkiewski Jul 31, 2026
6feacd3
test: add e2e web tests
kacperzolkiewski Jul 31, 2026
06f303f
Merge branch 'main' into feature/add-insert-text-method
kacperzolkiewski Jul 31, 2026
07568aa
test: update baseline
kacperzolkiewski Jul 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions .maestro/enrichedInput/flows/insert_value.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
appId: swmansion.enriched.example
---
# Verifies insertValue behaviour for different scenarios

- launchApp

- tapOn:
id: 'toggle-screen-button'

# ── Scenario 1: plain text into empty editor ─────────────────────────────────
- tapOn:
id: 'focus-button'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: 'Hello, world!'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_plain_into_empty'

# ── Scenario 2: plain text inherits active inline style ───────────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- inputText: 'before'
- tapOn:
id: 'toolbar-bold'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: 'BOLD'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_inherits_inline_style'

# ── Scenario 3: plain text into empty paragraph-styled line ───────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- tapOn:
id: 'toolbar-heading-1'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: 'Heading'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_into_empty_paragraph_style'

# ── Scenario 4: heading HTML into empty line ──────────────────────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: '<html><h2>Hello</h2></html>'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_heading_into_empty_line'

# ── Scenario 5: heading HTML into line with existing content ──────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- inputText: 'before'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: '<html><h3>inserted</h3></html>'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_heading_into_nonempty_line'

# ── Scenario 6: bold HTML blocked inside code block ───────────────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- tapOn:
id: 'toolbar-code-block'

- inputText: 'code'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: '<html><b>bold</b></html>'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_bold_blocked_in_codeblock'

# ── Scenario 7: multi-paragraph HTML at caret ─────────────────────────────────
- tapOn:
id: 'clear-button'
- tapOn:
id: 'focus-button'

- inputText: 'One'

- runFlow:
file: '../subflows/insert_editor_value.yaml'
env:
VALUE: '<html><h4>heading</h4><p>normal</p></html>'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'insert_value_multi_paragraph'
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions .maestro/enrichedInput/subflows/insert_editor_value.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
appId: swmansion.enriched.example
---
- tapOn:
id: 'insert-value-button'

- waitForAnimationToEnd
- extendedWaitUntil:
visible:
id: 'value-modal-input'
timeout: 10000

- tapOn:
id: 'value-modal-input'

- inputText: ${VALUE}

- tapOn:
id: 'value-modal-submit-button'
114 changes: 114 additions & 0 deletions .playwright/helpers/insertValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { expect, type Locator, type Page } from '@playwright/test';

import { toolbarButton } from './toolbar';

export const insertValueSelectors = {
editor: '[data-testid="insert-value-editor"]',
editorInner: '[data-testid="insert-value-editor"] .eti-editor',
htmlOutput: '[data-testid="insert-value-html-output"]',
setupHtmlInput: '[data-testid="setup-html-input"]',
setupSetValueButton: '[data-testid="setup-set-value-button"]',
selectionStart: '[data-testid="insert-value-selection-start"]',
selectionEnd: '[data-testid="insert-value-selection-end"]',
applySelectionButton: '[data-testid="insert-value-apply-selection-button"]',
insertInput: '[data-testid="insert-value-input"]',
insertSubmit: '[data-testid="insert-value-submit-button"]',
focusButton: '[data-testid="focus-button"]',
clearButton: '[data-testid="clear-button"]',
selectionEndResult: '[data-testid="insert-value-current-selection-end"]',
} as const;

export function insertValueEditorLocator(page: Page): Locator {
return page.locator(insertValueSelectors.editorInner);
}

export async function gotoInsertValue(page: Page): Promise<void> {
await page.goto('/test-insert-value');
await page.waitForSelector(insertValueSelectors.editorInner);
}

export async function focusInsertValueEditor(page: Page): Promise<Locator> {
await page.click(insertValueSelectors.focusButton);
const editor = insertValueEditorLocator(page);
await expect(
editor.locator('[contenteditable="true"]').first()
).toBeFocused();
return editor;
}

export async function clearInsertValueEditor(page: Page): Promise<void> {
await page.click(insertValueSelectors.clearButton);
await expect.poll(async () => getInsertValueHtml(page)).toBe('');
}

export async function getInsertValueHtml(page: Page): Promise<string> {
return (
(await page.locator(insertValueSelectors.htmlOutput).textContent()) ?? ''
);
}

export async function typeInInsertValueEditor(
page: Page,
text: string
): Promise<void> {
const editor = await focusInsertValueEditor(page);
await editor
.locator('[contenteditable="true"]')
.first()
.pressSequentially(text);
await expect
.poll(async () =>
page.locator(insertValueSelectors.selectionEndResult).textContent()
)
.toBe(String(text.length));
}

export async function setInsertValueEditorHtml(
page: Page,
html: string
): Promise<void> {
await page.fill(insertValueSelectors.setupHtmlInput, html);
await page.click(insertValueSelectors.setupSetValueButton);
await expect.poll(async () => getInsertValueHtml(page)).toMatch(/^<html>/);
}

export async function applyInsertValueSelection(
page: Page,
start: number,
end: number = start
): Promise<void> {
await page.fill(insertValueSelectors.selectionStart, String(start));
await page.fill(insertValueSelectors.selectionEnd, String(end));
await page.click(insertValueSelectors.applySelectionButton);
await expect
.poll(async () =>
page.locator(insertValueSelectors.selectionEndResult).textContent()
)
.toBe(String(end));
}

export async function insertValueAt(
page: Page,
value: string,
start: number,
end: number = start
): Promise<void> {
await applyInsertValueSelection(page, start, end);
await insertEditorValue(page, value);
}

export async function insertEditorValue(
page: Page,
value: string
): Promise<void> {
await page.fill(insertValueSelectors.insertInput, value);
await page.click(insertValueSelectors.insertSubmit);
await expect.poll(async () => getInsertValueHtml(page)).not.toBe('');
}

export async function resetInsertValueScenario(page: Page): Promise<void> {
await clearInsertValueEditor(page);
await focusInsertValueEditor(page);
}

export { toolbarButton };
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading