Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 19 additions & 35 deletions test/mobile/keyboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ import { PORTS, KEYBOARD, SELECTORS, BODY_CLASSES, WAIT } from './helpers/consta
import { createTestServer, stopTestServer } from './helpers/server.js';
import { createDevicePage, getBrowser, closeAllBrowsers } from './helpers/browser.js';
import {
showKeyboard, hideKeyboard,
showKeyboardViaCDP, hideKeyboardViaCDP,
showKeyboardViaMock, hideKeyboardViaMock,
showKeyboardViaDOM, hideKeyboardViaDOM,
showKeyboard,
hideKeyboard,
showKeyboardViaCDP,
hideKeyboardViaCDP,
showKeyboardViaMock,
hideKeyboardViaMock,
showKeyboardViaDOM,
hideKeyboardViaDOM,
setupViewportMock,
} from './helpers/keyboard-sim.js';
import { getCDP, setVisualViewportHeight } from './helpers/cdp.js';
import {
assertHasClass, assertNotHasClass,
assertVisible, assertHidden,
assertHasClass,
assertNotHasClass,
assertVisible,
assertHidden,
getCSSProperty,
} from './helpers/assertions.js';
import { REPRESENTATIVE_DEVICES } from './devices.js';
Expand Down Expand Up @@ -167,9 +173,7 @@ describe('Virtual Keyboard', () => {
const success = await showKeyboardViaMock(page, KEYBOARD.TYPICAL_IOS_HEIGHT);
expect(success).toBe(true);

const hasClass = await page.evaluate(() =>
document.body.classList.contains('keyboard-visible'),
);
const hasClass = await page.evaluate(() => document.body.classList.contains('keyboard-visible'));
expect(hasClass).toBe(true);
} finally {
await context.close();
Expand Down Expand Up @@ -280,12 +284,13 @@ describe('Virtual Keyboard', () => {
expect(mainPadding).toBe('');
});

it('accessory bar has 7 action buttons', async () => {
const count = await page.evaluate(() => {
const buttons = document.querySelectorAll('.keyboard-accessory-bar [data-action]');
return buttons.length;
it('accessory bar has the simple-mode action buttons', async () => {
const actions = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.keyboard-accessory-bar [data-action]')).map(
(button) => (button as HTMLElement).dataset.action
);
});
expect(count).toBe(7);
expect(actions).toEqual(['scroll-up', 'scroll-down', 'init', 'clear', 'paste', 'dismiss']);
});

it('double-tap confirm on /clear button', async () => {
Expand Down Expand Up @@ -321,27 +326,6 @@ describe('Virtual Keyboard', () => {
expect(text).toBe('Tap again');
});

it('double-tap confirm on /compact button', async () => {
await showKeyboard(page, KEYBOARD.TYPICAL_IOS_HEIGHT);
await page.waitForTimeout(WAIT.KEYBOARD_ANIMATION);

await page.evaluate(`
if (typeof app !== 'undefined') app.activeSessionId = 'test-session';
`);

await page.evaluate(() => {
const btn = document.querySelector('[data-action="compact"]') as HTMLElement;
btn?.click();
});
await page.waitForTimeout(100);

const confirming = await page.evaluate(() => {
const btn = document.querySelector('[data-action="compact"]');
return btn?.classList.contains('confirming') ?? false;
});
expect(confirming).toBe(true);
});

it('double-tap expires after 2s', async () => {
await showKeyboard(page, KEYBOARD.TYPICAL_IOS_HEIGHT);
await page.waitForTimeout(WAIT.KEYBOARD_ANIMATION);
Expand Down
20 changes: 13 additions & 7 deletions test/operation-lightspeed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ describe('Operation Lightspeed', () => {
await Promise.all(ids.map((id) => deleteSession(baseUrl, id)));
});

it('should correctly filter SSE under concurrent session lifecycle', async () => {
it('should broadcast lifecycle events while filtering concurrent session terminal streams', async () => {
// Create 2 sessions
const target = await createSession(baseUrl);
const other = await createSession(baseUrl);
Expand Down Expand Up @@ -1309,15 +1309,21 @@ describe('Operation Lightspeed', () => {

const events = parseSSEEvents(receivedData);

// Should see target's rename but not other's events
const targetUpdated = events.find((e) => e.event === 'session:updated' && (e.data as any).id === target);
// session:updated is a lifecycle event broadcast to all clients; the
// subscription filter applies only to high-volume terminal streams.
const updatedEvents = events.filter((e) => e.event === 'session:updated');
const targetUpdated = updatedEvents.find((e) => (e.data as any).id === target);
expect(targetUpdated).toBeDefined();

// Should NOT see other's events
const otherEvents = events.filter(
(e) => ((e.data as any)?.id === other || (e.data as any)?.sessionId === other) && e.event !== 'init'
const otherLifecycleEvents = events.filter(
(e) => e.event !== 'init' && e.event !== 'session:terminal' && (e.data as any)?.id === other
);
expect(otherLifecycleEvents.length).toBeGreaterThan(0);

const otherTerminalEvents = events.filter(
(e) => e.event === 'session:terminal' && (e.data as any)?.sessionId === other
);
expect(otherEvents.length).toBe(0);
expect(otherTerminalEvents.length).toBe(0);

await deleteSession(baseUrl, target);
});
Expand Down
Loading