blob: 56f940f37ee270989dcb84b60bb7bc4753f4820c [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:async';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import '../../common/test_initialization.dart';
import 'semantics_tester.dart';
void main() {
internalBootstrapBrowserTest(() {
return testMain;
});
}
Future<void> testMain() async {
await bootstrapAndRunApp();
test('Can create multiple views each with its own semantics tree', () async {
EngineSemantics.instance.semanticsEnabled = true;
final DomElement host1 = createDomElement('view-host');
domDocument.body!.append(host1);
final EngineFlutterView view1 = EngineFlutterView(EnginePlatformDispatcher.instance, host1);
EnginePlatformDispatcher.instance.viewManager.registerView(view1);
final SemanticsTester tester1 = SemanticsTester(view1.semantics);
final DomElement host2 = createDomElement('view-host');
domDocument.body!.append(host2);
final EngineFlutterView view2 = EngineFlutterView(EnginePlatformDispatcher.instance, host2);
EnginePlatformDispatcher.instance.viewManager.registerView(view2);
final SemanticsTester tester2 = SemanticsTester(view2.semantics);
tester1.updateNode(id: 0);
tester1.apply();
tester2.updateNode(id: 0);
tester2.apply();
// Check that we have both root nodes in the DOM (root nodes have id == 0)
expect(domDocument.querySelectorAll('flutter-view'), hasLength(2));
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view1.viewId}"]'), hasLength(1));
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view2.viewId}"]'), hasLength(1));
expect(domDocument.querySelectorAll('flt-semantics[id=flt-semantic-node-0]'), hasLength(2));
// Check that each is attached to its own view
expect(view1.semantics.semanticsHost, view1.dom.semanticsHost);
expect(view2.semantics.semanticsHost, view2.dom.semanticsHost);
// Check semantics
expectSemanticsTree(view1.semantics, '<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)"></sem>');
expectSemanticsTree(view2.semantics, '<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)"></sem>');
// Add some children
tester1.updateNode(
id: 0,
children: <SemanticsNodeUpdate>[
tester1.updateNode(
id: 1,
isFocusable: true,
hasTap: true,
hasEnabledState: true,
isEnabled: true,
isButton: true,
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
)
],
);
tester1.apply();
tester2.updateNode(
id: 0,
children: <SemanticsNodeUpdate>[
tester2.updateNode(
id: 2,
hasIncrease: true,
label: 'd',
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
),
],
);
tester2.apply();
// Test that each view renders its own semantics tree.
expectSemanticsTree(
view1.semantics,
'''
<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)">
<sem-c>
<sem flt-tappable="" role="button"></sem>
</sem-c>
</sem>''',
);
expectSemanticsTree(
view2.semantics,
'''
<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)">
<sem-c>
<sem aria-label="d"><input aria-valuemax="1" aria-valuemin="1" aria-valuenow="1" aria-valuetext="" role="slider"></sem>
</sem-c>
</sem>
''');
// Remove the first view, but keep the second one.
EnginePlatformDispatcher.instance.viewManager.disposeAndUnregisterView(view1.viewId);
expect(domDocument.querySelectorAll('flutter-view'), hasLength(1));
expect(domDocument.querySelectorAll('flt-semantics[id=flt-semantic-node-0]'), hasLength(1));
expect(domDocument.querySelectorAll('flt-semantics[id=flt-semantic-node-2]'), hasLength(1));
// Disable semantics; make sure the view is there but semantics is removed.
EngineSemantics.instance.semanticsEnabled = false;
expect(domDocument.querySelectorAll('flutter-view'), hasLength(1));
expect(domDocument.querySelectorAll('flt-semantics[id=flt-semantic-node-0]'), isEmpty);
});
}