super-productivity/e2e/tests/menu/menu-touch-submenu.spec.ts
Johannes Millan 9bfbc06b18 chore: address code review feedback
- Fix misleading comment in sync-wrapper.service.ts safeguard
- Add missing SCSS for pause-resume button in focus mode break
- Remove commented archive store code from feature-stores.module.ts
- Increase touch submenu test buffer from 350ms to 450ms for CI stability
- Remove redundant isEmojiIcon method in tag-toggle-menu-list component
2026-01-15 10:57:43 +01:00

109 lines
3.6 KiB
TypeScript

import { test, expect } from '../../fixtures/test.fixture';
/**
* Tests for mat-menu touch submenu fix.
*
* Issue: https://github.com/super-productivity/super-productivity/issues/4436
*
* When a submenu opens on a touch device near the screen edge, the submenu
* can appear under the user's finger, causing an immediate accidental selection.
* The fix adds a 300ms delay before clicks are processed on touch devices.
*
* NOTE: These tests use regular click events to verify the timing-based protection
* logic works correctly. The actual touch behavior on real devices depends on
* the IS_TOUCH_PRIMARY detection which isn't active in headless browsers.
*/
test.describe('Mat Menu Touch Submenu Fix', () => {
test('should allow selecting submenu item with sufficient delay', async ({
page,
workViewPage,
taskPage,
tagPage,
testPrefix,
}) => {
await workViewPage.waitForTaskList();
// Create a tag first
const tagName = `${testPrefix}-TouchTag`;
await tagPage.createTag(tagName);
// Create a task
const taskTitle = `${testPrefix}-TouchTask`;
await workViewPage.addTask(taskTitle);
await page.waitForSelector('task', { state: 'visible' });
// Get the task
const task = taskPage.getTaskByText(taskTitle);
await task.waitFor({ state: 'visible' });
// Open context menu
await task.click({ button: 'right' });
// Wait for context menu
const contextMenu = page.locator('.mat-mdc-menu-content');
await contextMenu.waitFor({ state: 'visible', timeout: 5000 });
// Click on Toggle Tags to open submenu
const toggleTagsBtn = page.locator(
'button.e2e-edit-tags-btn, button:has-text("Toggle Tags")',
);
await toggleTagsBtn.waitFor({ state: 'visible', timeout: 5000 });
await toggleTagsBtn.click();
// Wait for submenu to appear (the tag button in the menu)
const tagBtn = page.locator('.mat-mdc-menu-content button', { hasText: tagName });
await tagBtn.waitFor({ state: 'visible', timeout: 5000 });
// Wait for 300ms touch protection delay to expire, plus buffer for CI stability
// This is a timing-based protection feature being tested, so timeout is justified
await page.waitForTimeout(450);
// Click on the tag - should work after delay
await tagBtn.click();
// Wait for tag to appear on task (implicitly waits for menu action to complete)
const tagOnTask = tagPage.getTagOnTask(task, tagName);
await tagOnTask.waitFor({ state: 'visible', timeout: 5000 });
const hasTag = await tagPage.taskHasTag(task, tagName);
expect(hasTag).toBe(true);
});
test('should support toggling tags via submenu', async ({
page,
workViewPage,
taskPage,
tagPage,
testPrefix,
}) => {
await workViewPage.waitForTaskList();
// Create two tags
const tag1 = `${testPrefix}-Tag1`;
const tag2 = `${testPrefix}-Tag2`;
await tagPage.createTag(tag1);
await tagPage.createTag(tag2);
// Create a task
const taskTitle = `${testPrefix}-MultiTagTask`;
await workViewPage.addTask(taskTitle);
await page.waitForSelector('task', { state: 'visible' });
const task = taskPage.getTaskByText(taskTitle);
// Assign first tag via context menu
await tagPage.assignTagToTask(task, tag1);
// Verify first tag is on task
let hasTag1 = await tagPage.taskHasTag(task, tag1);
expect(hasTag1).toBe(true);
// Assign second tag
await tagPage.assignTagToTask(task, tag2);
// Verify both tags are on task
hasTag1 = await tagPage.taskHasTag(task, tag1);
const hasTag2 = await tagPage.taskHasTag(task, tag2);
expect(hasTag1).toBe(true);
expect(hasTag2).toBe(true);
});
});