blob: 92b0d42b069283c0575f40d7ea9b131de7244645 [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 'dart:html' as html;
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/browser_detection.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 html.Element? _placeholder;
setUp(() {
EngineSemanticsOwner.instance.semanticsEnabled = false;
desktopSemanticsEnabler = DesktopSemanticsEnabler();
_placeholder = desktopSemanticsEnabler.prepareAccessibilityPlaceholder();
html.document.body!.append(_placeholder!);
});
tearDown(() {
expect(_placeholder, isNotNull,
reason: 'Expected the test to create a placeholder');
_placeholder!.remove();
EngineSemanticsOwner.instance.semanticsEnabled = false;
});
test('prepare accesibility placeholder', () async {
expect(_placeholder!.getAttribute('role'), 'button');
expect(_placeholder!.getAttribute('aria-live'), 'true');
expect(_placeholder!.getAttribute('tabindex'), '0');
html.document.body!.append(_placeholder!);
expect(html.document.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.
html.document.body!.append(_placeholder!);
html.Event event = html.MouseEvent('mousemove');
bool shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isTrue);
// Pointer events are not defined in webkit.
if (browserEngine != BrowserEngine.webkit) {
event = html.PointerEvent('pointermove');
shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isTrue);
}
});
test(
'Relevants events targeting placeholder should not be forwarded to the framework',
() async {
final html.Event event = html.MouseEvent('mousedown');
_placeholder!.dispatchEvent(event);
final bool shouldForwardToFramework =
desktopSemanticsEnabler.tryEnableSemantics(event);
expect(shouldForwardToFramework, isFalse);
});
test('disposes of the placeholder', () {
html.document.body!.append(_placeholder!);
expect(_placeholder!.isConnected, isTrue);
desktopSemanticsEnabler.dispose();
expect(_placeholder!.isConnected, isFalse);
});
}, skip: isMobile);
group(
'$MobileSemanticsEnabler',
() {
late MobileSemanticsEnabler mobileSemanticsEnabler;
html.Element? _placeholder;
setUp(() {
EngineSemanticsOwner.instance.semanticsEnabled = false;
mobileSemanticsEnabler = MobileSemanticsEnabler();
_placeholder = mobileSemanticsEnabler.prepareAccessibilityPlaceholder();
html.document.body!.append(_placeholder!);
});
tearDown(() {
_placeholder!.remove();
EngineSemanticsOwner.instance.semanticsEnabled = false;
});
test('prepare accesibility placeholder', () async {
expect(_placeholder!.getAttribute('role'), 'button');
// Placeholder should cover all the screen on a mobile device.
final num bodyHeight = html.window.innerHeight!;
final num bodyWidht = html.window.innerWidth!;
expect(_placeholder!.getBoundingClientRect().height, bodyHeight);
expect(_placeholder!.getBoundingClientRect().width, bodyWidht);
});
test('Non-relevant events should be forwarded to the framework',
() async {
html.Event event;
if (_defaultSupportDetector.hasPointerEvents) {
event = html.PointerEvent('pointermove');
} else if (_defaultSupportDetector.hasTouchEvents) {
event = html.TouchEvent('touchcancel');
} else {
event = html.MouseEvent('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(html.MouseEvent(
'click',
clientX: 0,
clientY: 0,
));
expect(mobileSemanticsEnabler.semanticsActivationTimer, isNull);
// Send a click at center
final html.Rectangle<num> 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(html.MouseEvent(
'click',
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,
);
}