blob: 2a6f5c64da0e5129e58d65a84f3475f18a5ec597 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/browser_detection.dart';
import 'package:ui/src/engine/dom.dart';
import 'package:ui/src/engine/pointer_binding.dart';
import 'package:ui/src/engine/semantics.dart';
const PointerSupportDetector _defaultSupportDetector = PointerSupportDetector();
void main() {
internalBootstrapBrowserTest(() => testMain);
}
void testMain() {
group('$DesktopSemanticsEnabler', () {
late DesktopSemanticsEnabler desktopSemanticsEnabler;
late DomElement? placeholder;
setUp(() {
EngineSemanticsOwner.instance.semanticsEnabled = false;
desktopSemanticsEnabler = DesktopSemanticsEnabler();
placeholder = desktopSemanticsEnabler.prepareAccessibilityPlaceholder();
domDocument.body!.append(placeholder!);
});
tearDown(() {
expect(placeholder, isNotNull,
reason: 'Expected the test to create a placeholder');
placeholder!.remove();
EngineSemanticsOwner.instance.semanticsEnabled = false;
});
test('prepare accessibility placeholder', () async {
expect(placeholder!.getAttribute('role'), 'button');
expect(placeholder!.getAttribute('aria-live'), 'polite');
expect(placeholder!.getAttribute('tabindex'), '0');
domDocument.body!.append(placeholder!);
expect(domDocument.getElementsByTagName('flt-semantics-placeholder'),
isNotEmpty);
expect(placeholder!.getBoundingClientRect().height, 1);
expect(placeholder!.getBoundingClientRect().width, 1);
expect(placeholder!.getBoundingClientRect().top, -1);
expect(placeholder!.getBoundingClientRect().left, -1);
});
test('Not relevant events should be forwarded to the framework', () async {
// Attach the placeholder to dom.
domDocument.body!.append(placeholder!);
DomEvent event = createDomEvent('Event', 'mousemove');
bool shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isTrue);
// Pointer events are not defined in webkit.
if (browserEngine != BrowserEngine.webkit) {
event = createDomEvent('Event', 'pointermove');
shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isTrue);
}
});
test(
'Relevant events targeting placeholder should not be forwarded to the framework',
() async {
final DomEvent event = createDomEvent('Event', 'mousedown');
placeholder!.dispatchEvent(event);
final bool shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isFalse);
});
test('disposes of the placeholder', () {
domDocument.body!.append(placeholder!);
expect(placeholder!.isConnected, isTrue);
desktopSemanticsEnabler.dispose();
expect(placeholder!.isConnected, isFalse);
});
}, skip: isMobile);
group(
'$MobileSemanticsEnabler',
() {
late MobileSemanticsEnabler mobileSemanticsEnabler;
DomElement? placeholder;
setUp(() {
EngineSemanticsOwner.instance.semanticsEnabled = false;
mobileSemanticsEnabler = MobileSemanticsEnabler();
placeholder = mobileSemanticsEnabler.prepareAccessibilityPlaceholder();
domDocument.body!.append(placeholder!);
});
tearDown(() {
placeholder!.remove();
EngineSemanticsOwner.instance.semanticsEnabled = false;
});
test('prepare accessibility placeholder', () async {
expect(placeholder!.getAttribute('role'), 'button');
// Placeholder should cover all the screen on a mobile device.
final num bodyHeight = domWindow.innerHeight!;
final num bodyWidth = domWindow.innerWidth!;
expect(placeholder!.getBoundingClientRect().height, bodyHeight);
expect(placeholder!.getBoundingClientRect().width, bodyWidth);
});
test('Non-relevant events should be forwarded to the framework',
() async {
DomEvent event;
if (_defaultSupportDetector.hasPointerEvents) {
event = createDomPointerEvent('pointermove');
} else if (_defaultSupportDetector.hasTouchEvents) {
event = createDomTouchEvent('touchcancel');
} else {
event = createDomMouseEvent('mousemove');
}
final bool shouldForwardToFramework =
mobileSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isTrue);
});
test('Enables semantics when receiving a relevant event', () {
expect(mobileSemanticsEnabler.semanticsActivationTimer, isNull);
// Send a click off center
placeholder!.dispatchEvent(createDomMouseEvent(
'click',
<Object?, Object?>{
'clientX': 0,
'clientY': 0,
}
));
expect(mobileSemanticsEnabler.semanticsActivationTimer, isNull);
// Send a click at center
final DomRect activatingElementRect =
placeholder!.getBoundingClientRect();
final int midX = (activatingElementRect.left +
(activatingElementRect.right - activatingElementRect.left) / 2)
.toInt();
final int midY = (activatingElementRect.top +
(activatingElementRect.bottom - activatingElementRect.top) / 2)
.toInt();
placeholder!.dispatchEvent(createDomMouseEvent(
'click',
<Object?, Object?>{
'clientX': midX,
'clientY': midY,
}
));
expect(mobileSemanticsEnabler.semanticsActivationTimer, isNotNull);
});
},
// We can run `MobileSemanticsEnabler` tests in mobile browsers and in desktop Chrome.
skip: isDesktop && browserEngine != BrowserEngine.blink,
);
}