This commit resolves the issue with the `:active` pseudo-class not
activating in mobile Safari on iOS devices. It introduces a workaround
specifically for mobile Safari on iOS/iPadOS to enable the `:active`
pseudo-class. This ensures a consistent and responsive user interface
in response to touch states on mobile Safari.
Other supporting changes:
- Introduce new test utility functions such as `createWindowEventSpies`
and `formatAssertionMessage` to improve code reusability and
maintainability.
- Improve browser detection:
- Add detection for iPadOS and Windows 10 Mobile.
- Add touch support detection to correctly determine iPadOS vs macOS.
- Fix misidentification of some Windows 10 Mobile platforms as Windows
Phone.
- Improve test coverage and refactor tests.
66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { BrowserTouchSupportAccessor, isTouchEnabledDevice } from '@/infrastructure/RuntimeEnvironment/TouchSupportDetection';
|
|
|
|
describe('TouchSupportDetection', () => {
|
|
describe('isTouchEnabledDevice', () => {
|
|
const testScenarios: ReadonlyArray<{
|
|
readonly description: string;
|
|
readonly accessor: BrowserTouchSupportAccessor;
|
|
readonly expectedTouch: boolean;
|
|
}> = [
|
|
{
|
|
description: 'detects no touch capabilities',
|
|
accessor: createMockAccessor(),
|
|
expectedTouch: false,
|
|
},
|
|
{
|
|
description: 'detects touch capability with defined document.ontouchend',
|
|
accessor: createMockAccessor({ documentOntouchend: () => 'not-undefined' }),
|
|
expectedTouch: true,
|
|
},
|
|
{
|
|
description: 'detects touch capability with navigator.maxTouchPoints > 0',
|
|
accessor: createMockAccessor({ navigatorMaxTouchPoints: () => 1 }),
|
|
expectedTouch: true,
|
|
},
|
|
{
|
|
description: 'detects touch capability when matchMedia for pointer coarse is true',
|
|
accessor: createMockAccessor({
|
|
windowMatchMediaMatches: (query: string) => {
|
|
return query === '(any-pointer: coarse)';
|
|
},
|
|
}),
|
|
expectedTouch: true,
|
|
},
|
|
{
|
|
description: 'detects touch capability with defined window.TouchEvent',
|
|
expectedTouch: true,
|
|
accessor: createMockAccessor({ windowTouchEvent: () => class {} }),
|
|
},
|
|
];
|
|
testScenarios.forEach(({ description, accessor, expectedTouch }) => {
|
|
it(`${description} - returns ${expectedTouch}`, () => {
|
|
// act
|
|
const isTouchDetected = isTouchEnabledDevice(accessor);
|
|
// assert
|
|
expect(isTouchDetected).to.equal(expectedTouch);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
function createMockAccessor(
|
|
touchSupportFeatures: Partial<BrowserTouchSupportAccessor> = {},
|
|
): BrowserTouchSupportAccessor {
|
|
const defaultTouchSupport: BrowserTouchSupportAccessor = {
|
|
navigatorMaxTouchPoints: () => undefined,
|
|
windowMatchMediaMatches: () => false,
|
|
documentOntouchend: () => undefined,
|
|
windowTouchEvent: () => undefined,
|
|
};
|
|
return {
|
|
...defaultTouchSupport,
|
|
...touchSupportFeatures,
|
|
};
|
|
}
|