mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] Explicit initialization of the implicit view (flutter/engine#47921)
- An explicit API for initializing the implicit view (aka `window`).
- The explicit API is being called during the engine initialization for now, but we could simply remove that or make it conditional.
- Remove direct usages of `window` in tests:
- Most of the usages were being delegated to `PlatformDispatcher` anyway (e.g. `sendPlatformMessage`).
- This makes it **_clearer_** which tests depend on the implicit view (there are still hidden/indirect dependencies though).
Part of https://github.com/flutter/flutter/issues/134443
This commit is contained in:
parent
ae786cb22a
commit
44cbbf526f
@ -5,7 +5,7 @@
|
||||
import 'package:ui/src/engine/safe_browser_api.dart';
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../engine.dart' show buildMode, renderer, window;
|
||||
import '../engine.dart' show buildMode, renderer;
|
||||
import 'browser_detection.dart';
|
||||
import 'configuration.dart';
|
||||
import 'dom.dart';
|
||||
@ -18,6 +18,7 @@ import 'view_embedder/dimensions_provider/dimensions_provider.dart';
|
||||
import 'view_embedder/dom_manager.dart';
|
||||
import 'view_embedder/embedding_strategy/embedding_strategy.dart';
|
||||
import 'view_embedder/style_manager.dart';
|
||||
import 'window.dart';
|
||||
|
||||
/// Controls the placement and lifecycle of a Flutter view on the web page.
|
||||
///
|
||||
@ -309,9 +310,13 @@ FlutterViewEmbedder get flutterViewEmbedder {
|
||||
FlutterViewEmbedder? _flutterViewEmbedder;
|
||||
|
||||
/// Initializes the [FlutterViewEmbedder], if it's not already initialized.
|
||||
FlutterViewEmbedder ensureFlutterViewEmbedderInitialized() =>
|
||||
_flutterViewEmbedder ??=
|
||||
FlutterViewEmbedder(hostElement: configuration.hostElement);
|
||||
FlutterViewEmbedder ensureFlutterViewEmbedderInitialized() {
|
||||
// FlutterViewEmbedder needs the implicit view to be initialized because it
|
||||
// uses some of its methods e.g. `configureDimensionsProvider`, `onResize`.
|
||||
ensureImplicitViewInitialized();
|
||||
return _flutterViewEmbedder ??=
|
||||
FlutterViewEmbedder(hostElement: configuration.hostElement);
|
||||
}
|
||||
|
||||
/// Creates a node to host text editing elements and applies a stylesheet
|
||||
/// to Flutter nodes that exist outside of the shadowDOM.
|
||||
|
||||
@ -226,6 +226,7 @@ Future<void> initializeEngineUi() async {
|
||||
_initializationState = DebugEngineInitializationState.initializingUi;
|
||||
|
||||
RawKeyboard.initialize(onMacOs: operatingSystem == OperatingSystem.macOs);
|
||||
ensureImplicitViewInitialized();
|
||||
ensureFlutterViewEmbedderInitialized();
|
||||
_initializationState = DebugEngineInitializationState.initialized;
|
||||
}
|
||||
|
||||
@ -135,6 +135,13 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
viewData[view.viewId] = view;
|
||||
}
|
||||
|
||||
/// Removes [view] from the platform dispatcher's registry of [views].
|
||||
///
|
||||
/// Nothing happens if the view is not already registered.
|
||||
void unregisterView(EngineFlutterView view) {
|
||||
viewData.remove(view.viewId);
|
||||
}
|
||||
|
||||
/// The current list of windows.
|
||||
@override
|
||||
Iterable<EngineFlutterView> get views => viewData.values;
|
||||
|
||||
@ -7,6 +7,7 @@ import 'dart:async';
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
import 'package:ui/ui.dart' as ui show Size;
|
||||
|
||||
import '../../display.dart';
|
||||
import '../../dom.dart';
|
||||
import 'custom_element_dimensions_provider.dart';
|
||||
import 'full_page_dimensions_provider.dart';
|
||||
@ -39,7 +40,7 @@ abstract class DimensionsProvider {
|
||||
/// Returns the DPI reported by the browser.
|
||||
double getDevicePixelRatio() {
|
||||
// This is overridable in tests.
|
||||
return window.devicePixelRatio;
|
||||
return EngineFlutterDisplay.instance.devicePixelRatio;
|
||||
}
|
||||
|
||||
/// Returns the [ui.Size] of the "viewport".
|
||||
|
||||
@ -573,8 +573,22 @@ final class EngineFlutterWindow extends EngineFlutterView implements ui.Singleto
|
||||
/// `dart:ui` window delegates to this value. However, this value has a wider
|
||||
/// API surface, providing Web-specific functionality that the standard
|
||||
/// `dart:ui` version does not.
|
||||
final EngineFlutterWindow window =
|
||||
EngineFlutterWindow(kImplicitViewId, EnginePlatformDispatcher.instance);
|
||||
EngineFlutterWindow get window {
|
||||
assert(
|
||||
_window != null,
|
||||
'Trying to access the implicit FlutterView, but it is not available.\n'
|
||||
'Note: the implicit FlutterView is not available in multi-view mode.',
|
||||
);
|
||||
return _window!;
|
||||
}
|
||||
EngineFlutterWindow? _window;
|
||||
|
||||
/// Initializes the [window] (aka the implicit view), if it's not already
|
||||
/// initialized.
|
||||
EngineFlutterWindow ensureImplicitViewInitialized() {
|
||||
return _window ??=
|
||||
EngineFlutterWindow(kImplicitViewId, EnginePlatformDispatcher.instance);
|
||||
}
|
||||
|
||||
/// The Web implementation of [ui.ViewPadding].
|
||||
class ViewPadding implements ui.ViewPadding {
|
||||
|
||||
@ -31,6 +31,7 @@ bool get debugEmulateFlutterTesterEnvironment =>
|
||||
set debugEmulateFlutterTesterEnvironment(bool value) {
|
||||
_debugEmulateFlutterTesterEnvironment = value;
|
||||
if (_debugEmulateFlutterTesterEnvironment) {
|
||||
ensureImplicitViewInitialized();
|
||||
const ui.Size logicalSize = ui.Size(800.0, 600.0);
|
||||
window.debugPhysicalSizeOverride = logicalSize * window.devicePixelRatio;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ const ui.Rect region = ui.Rect.fromLTRB(0, 0, 500, 500);
|
||||
void testMain() {
|
||||
group('BackdropFilter', () {
|
||||
setUpCanvasKitTest();
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
|
||||
test('blur renders to the edges', () async {
|
||||
// Make a checkerboard picture so we can see the blur.
|
||||
|
||||
@ -85,7 +85,7 @@ Future<bool> matchImage(ui.Image left, ui.Image right) async {
|
||||
/// Sends a platform message to create a Platform View with the given id and viewType.
|
||||
Future<void> createPlatformView(int id, String viewType) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'create',
|
||||
@ -102,7 +102,7 @@ Future<void> createPlatformView(int id, String viewType) {
|
||||
/// Disposes of the platform view with the given [id].
|
||||
Future<void> disposePlatformView(int id) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall('dispose', id)),
|
||||
(dynamic _) => completer.complete(),
|
||||
|
||||
@ -13,6 +13,9 @@ import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
|
||||
import 'common.dart';
|
||||
import 'test_data.dart';
|
||||
|
||||
EngineFlutterWindow get implicitView =>
|
||||
EnginePlatformDispatcher.instance.implicitView!;
|
||||
|
||||
DomElement get platformViewsHost {
|
||||
return EnginePlatformDispatcher.instance.implicitView!.dom.platformViewsHost;
|
||||
}
|
||||
@ -26,7 +29,7 @@ void testMain() {
|
||||
setUpCanvasKitTest();
|
||||
|
||||
setUp(() {
|
||||
window.debugOverrideDevicePixelRatio(1);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1);
|
||||
});
|
||||
|
||||
test('embeds interactive platform views', () async {
|
||||
@ -238,7 +241,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('converts device pixels to logical pixels (no clips)', () async {
|
||||
window.debugOverrideDevicePixelRatio(4);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(4);
|
||||
ui_web.platformViewRegistry.registerViewFactory(
|
||||
'test-platform-view',
|
||||
(int viewId) => createDomHTMLDivElement()..id = 'view-0',
|
||||
@ -263,7 +266,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('converts device pixels to logical pixels (with clips)', () async {
|
||||
window.debugOverrideDevicePixelRatio(4);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(4);
|
||||
ui_web.platformViewRegistry.registerViewFactory(
|
||||
'test-platform-view',
|
||||
(int viewId) => createDomHTMLDivElement()..id = 'view-0',
|
||||
@ -417,7 +420,7 @@ void testMain() {
|
||||
for (final int id in platformViewIds) {
|
||||
const StandardMethodCodec codec = StandardMethodCodec();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'dispose',
|
||||
@ -637,8 +640,8 @@ void testMain() {
|
||||
sb.addPicture(ui.Offset.zero, picture);
|
||||
sb.addPlatformView(0, width: 10, height: 10);
|
||||
|
||||
window.debugPhysicalSizeOverride = const ui.Size(100, 100);
|
||||
window.debugForceResize();
|
||||
implicitView.debugPhysicalSizeOverride = const ui.Size(100, 100);
|
||||
implicitView.debugForceResize();
|
||||
CanvasKitRenderer.instance.rasterizer.draw(sb.build().layerTree);
|
||||
_expectSceneMatches(<_EmbeddedViewMarker>[
|
||||
_overlay,
|
||||
@ -646,8 +649,8 @@ void testMain() {
|
||||
_overlay,
|
||||
]);
|
||||
|
||||
window.debugPhysicalSizeOverride = const ui.Size(200, 200);
|
||||
window.debugForceResize();
|
||||
implicitView.debugPhysicalSizeOverride = const ui.Size(200, 200);
|
||||
implicitView.debugForceResize();
|
||||
CanvasKitRenderer.instance.rasterizer.draw(sb.build().layerTree);
|
||||
_expectSceneMatches(<_EmbeddedViewMarker>[
|
||||
_overlay,
|
||||
@ -655,8 +658,8 @@ void testMain() {
|
||||
_overlay,
|
||||
]);
|
||||
|
||||
window.debugPhysicalSizeOverride = null;
|
||||
window.debugForceResize();
|
||||
implicitView.debugPhysicalSizeOverride = null;
|
||||
implicitView.debugForceResize();
|
||||
// ImageDecoder is not supported in Safari or Firefox.
|
||||
}, skip: isSafari || isFirefox);
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ void testMain() {
|
||||
group('CanvasKit', () {
|
||||
setUpCanvasKitTest();
|
||||
setUp(() async {
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
});
|
||||
|
||||
Future<DomImageBitmap> newBitmap(int width, int height) async {
|
||||
@ -43,7 +43,7 @@ void testMain() {
|
||||
|
||||
// Increase device-pixel ratio: this makes CSS pixels bigger, so we need
|
||||
// fewer of them to cover the browser window.
|
||||
window.debugOverrideDevicePixelRatio(2.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(2.0);
|
||||
canvas.render(await newBitmap(10, 16));
|
||||
expect(canvas.canvasElement.width, 10);
|
||||
expect(canvas.canvasElement.height, 16);
|
||||
@ -52,7 +52,7 @@ void testMain() {
|
||||
|
||||
// Decrease device-pixel ratio: this makes CSS pixels smaller, so we need
|
||||
// more of them to cover the browser window.
|
||||
window.debugOverrideDevicePixelRatio(0.5);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(0.5);
|
||||
canvas.render(await newBitmap(10, 16));
|
||||
expect(canvas.canvasElement.width, 10);
|
||||
expect(canvas.canvasElement.height, 16);
|
||||
|
||||
@ -19,7 +19,7 @@ void testMain() {
|
||||
group('CanvasKit', () {
|
||||
setUpCanvasKitTest();
|
||||
setUp(() {
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
});
|
||||
|
||||
test('Surface allocates canvases efficiently', () {
|
||||
@ -90,7 +90,7 @@ void testMain() {
|
||||
|
||||
// Doubling the DPR should halve the CSS width, height, and translation of the canvas.
|
||||
// This tests https://github.com/flutter/flutter/issues/77084
|
||||
window.debugOverrideDevicePixelRatio(2.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(2.0);
|
||||
final CkSurface dpr2Surface2 =
|
||||
surface.acquireFrame(const ui.Size(5, 15)).skiaSurface;
|
||||
final DomOffscreenCanvas dpr2Canvas = surface.debugOffscreenCanvas!;
|
||||
@ -168,7 +168,7 @@ void testMain() {
|
||||
|
||||
// Increase device-pixel ratio: this makes CSS pixels bigger, so we need
|
||||
// fewer of them to cover the browser window.
|
||||
window.debugOverrideDevicePixelRatio(2.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(2.0);
|
||||
final CkSurface highDpr =
|
||||
surface.acquireFrame(const ui.Size(10, 16)).skiaSurface;
|
||||
expect(highDpr.width(), 10);
|
||||
@ -178,7 +178,7 @@ void testMain() {
|
||||
|
||||
// Decrease device-pixel ratio: this makes CSS pixels smaller, so we need
|
||||
// more of them to cover the browser window.
|
||||
window.debugOverrideDevicePixelRatio(0.5);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(0.5);
|
||||
final CkSurface lowDpr =
|
||||
surface.acquireFrame(const ui.Size(10, 16)).skiaSurface;
|
||||
expect(lowDpr.width(), 10);
|
||||
@ -187,7 +187,7 @@ void testMain() {
|
||||
expect(surface.debugOffscreenCanvas!.height, 16);
|
||||
|
||||
// See https://github.com/flutter/flutter/issues/77084#issuecomment-1120151172
|
||||
window.debugOverrideDevicePixelRatio(2.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(2.0);
|
||||
final CkSurface changeRatioAndSize =
|
||||
surface.acquireFrame(const ui.Size(9.9, 15.9)).skiaSurface;
|
||||
expect(changeRatioAndSize.width(), 10);
|
||||
|
||||
@ -97,7 +97,9 @@ void testMain() {
|
||||
group('test fonts in flutterTester environment', () {
|
||||
final bool resetValue = ui_web.debugEmulateFlutterTesterEnvironment;
|
||||
ui_web.debugEmulateFlutterTesterEnvironment = true;
|
||||
tearDownAll(() => ui_web.debugEmulateFlutterTesterEnvironment = resetValue);
|
||||
tearDownAll(() {
|
||||
ui_web.debugEmulateFlutterTesterEnvironment = resetValue;
|
||||
});
|
||||
const List<String> testFonts = <String>['FlutterTest', 'Ahem'];
|
||||
|
||||
test('The default test font is used when a non-test fontFamily is specified', () {
|
||||
|
||||
@ -12,28 +12,28 @@ import 'package:ui/ui.dart' as ui;
|
||||
/// See CanvasKit-specific and HTML-specific test files `frame_timings_test.dart`.
|
||||
Future<void> runFrameTimingsTest() async {
|
||||
List<ui.FrameTiming>? timings;
|
||||
ui.window.onReportTimings = (List<ui.FrameTiming> data) {
|
||||
ui.PlatformDispatcher.instance.onReportTimings = (List<ui.FrameTiming> data) {
|
||||
timings = data;
|
||||
};
|
||||
Completer<void> frameDone = Completer<void>();
|
||||
ui.window.onDrawFrame = () {
|
||||
ui.PlatformDispatcher.instance.onDrawFrame = () {
|
||||
final ui.SceneBuilder sceneBuilder = ui.SceneBuilder();
|
||||
sceneBuilder
|
||||
..pushOffset(0, 0)
|
||||
..pop();
|
||||
ui.window.render(sceneBuilder.build());
|
||||
ui.PlatformDispatcher.instance.render(sceneBuilder.build());
|
||||
frameDone.complete();
|
||||
};
|
||||
|
||||
// Frame 1.
|
||||
ui.window.scheduleFrame();
|
||||
ui.PlatformDispatcher.instance.scheduleFrame();
|
||||
await frameDone.future;
|
||||
expect(timings, isNull, reason: "100 ms hasn't passed yet");
|
||||
await Future<void>.delayed(const Duration(milliseconds: 150));
|
||||
|
||||
// Frame 2.
|
||||
frameDone = Completer<void>();
|
||||
ui.window.scheduleFrame();
|
||||
ui.PlatformDispatcher.instance.scheduleFrame();
|
||||
await frameDone.future;
|
||||
expect(timings, hasLength(2), reason: '100 ms passed. 2 frames pumped.');
|
||||
for (final ui.FrameTiming timing in timings!) {
|
||||
|
||||
@ -53,8 +53,8 @@ class PlatformMessagesSpy {
|
||||
));
|
||||
};
|
||||
|
||||
_backup = window.onPlatformMessage;
|
||||
window.onPlatformMessage = _callback;
|
||||
_backup = PlatformDispatcher.instance.onPlatformMessage;
|
||||
PlatformDispatcher.instance.onPlatformMessage = _callback;
|
||||
}
|
||||
|
||||
/// Stop spying on platform messages and clear all intercepted messages.
|
||||
@ -62,11 +62,11 @@ class PlatformMessagesSpy {
|
||||
/// Make sure this is called after each test that uses [PlatformMessagesSpy].
|
||||
void tearDown() {
|
||||
assert(_isActive);
|
||||
// Make sure [window.onPlatformMessage] wasn't tampered with.
|
||||
assert(window.onPlatformMessage == _callback);
|
||||
// Make sure [PlatformDispatcher.instance.onPlatformMessage] wasn't tampered with.
|
||||
assert(PlatformDispatcher.instance.onPlatformMessage == _callback);
|
||||
_callback = null;
|
||||
messages.clear();
|
||||
window.onPlatformMessage = _backup;
|
||||
PlatformDispatcher.instance.onPlatformMessage = _backup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,10 @@ void setUpUnitTests({
|
||||
}) {
|
||||
late final FakeAssetScope debugFontsScope;
|
||||
setUpAll(() async {
|
||||
// The implicit view is needed for `debugEmulateFlutterTesterEnvironment`,
|
||||
// `flutterViewEmbedder`, and `debugPhysicalSizeOverride`.
|
||||
engine.ensureImplicitViewInitialized();
|
||||
|
||||
if (emulateTesterEnvironment) {
|
||||
ui_web.debugEmulateFlutterTesterEnvironment = true;
|
||||
}
|
||||
@ -31,8 +35,8 @@ void setUpUnitTests({
|
||||
// we don't have an embedder yet this is the lowest-most layer we can put
|
||||
// this stuff in.
|
||||
const double devicePixelRatio = 3.0;
|
||||
engine.window.debugOverrideDevicePixelRatio(devicePixelRatio);
|
||||
engine.window.debugPhysicalSizeOverride =
|
||||
engine.EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(devicePixelRatio);
|
||||
engine.EnginePlatformDispatcher.instance.implicitView!.debugPhysicalSizeOverride =
|
||||
const ui.Size(800 * devicePixelRatio, 600 * devicePixelRatio);
|
||||
engine.scheduleFrameCallback = () {};
|
||||
}
|
||||
|
||||
@ -15,6 +15,10 @@ void main() {
|
||||
}
|
||||
|
||||
void testMain() {
|
||||
setUpAll(() {
|
||||
ensureImplicitViewInitialized();
|
||||
});
|
||||
|
||||
test('populates flt-renderer and flt-build-mode', () {
|
||||
FlutterViewEmbedder();
|
||||
expect(domDocument.body!.getAttribute('flt-renderer'),
|
||||
|
||||
@ -7,16 +7,15 @@ import 'dart:async';
|
||||
import 'package:quiver/testing/async.dart';
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine.dart' show window;
|
||||
import 'package:ui/src/engine/dom.dart' show DomEvent, createDomPopStateEvent;
|
||||
import 'package:ui/src/engine/navigation/history.dart';
|
||||
import 'package:ui/src/engine/services.dart';
|
||||
import 'package:ui/src/engine/test_embedding.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
import 'package:ui/ui_web/src/ui_web.dart';
|
||||
|
||||
import '../common/matchers.dart';
|
||||
import '../common/spy.dart';
|
||||
|
||||
EngineFlutterWindow get implicitView =>
|
||||
EnginePlatformDispatcher.instance.implicitView!;
|
||||
|
||||
Map<String, dynamic> _wrapOriginState(dynamic state) {
|
||||
return <String, dynamic>{'origin': true, 'state': state};
|
||||
}
|
||||
@ -38,6 +37,10 @@ void main() {
|
||||
}
|
||||
|
||||
void testMain() {
|
||||
setUpAll(() {
|
||||
ensureImplicitViewInitialized();
|
||||
});
|
||||
|
||||
test('createHistoryForExistingState', () {
|
||||
TestUrlStrategy strategy;
|
||||
BrowserHistory history;
|
||||
@ -91,14 +94,14 @@ void testMain() {
|
||||
|
||||
tearDown(() async {
|
||||
spy.tearDown();
|
||||
await window.resetHistory();
|
||||
await implicitView.resetHistory();
|
||||
});
|
||||
|
||||
test('basic setup works', () async {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
// There should be two entries: origin and flutter.
|
||||
expect(strategy.history, hasLength(2));
|
||||
@ -127,7 +130,7 @@ void testMain() {
|
||||
);
|
||||
expect(strategy.listeners, isEmpty);
|
||||
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
|
||||
// There should be one `popstate` listener and two history entries.
|
||||
@ -139,7 +142,7 @@ void testMain() {
|
||||
expect(strategy.history[1].url, '/initial');
|
||||
|
||||
FakeAsync().run((FakeAsync fakeAsync) {
|
||||
window.browserHistory.dispose();
|
||||
implicitView.browserHistory.dispose();
|
||||
// The `TestUrlStrategy` implementation uses microtasks to schedule the
|
||||
// removal of event listeners.
|
||||
fakeAsync.flushMicrotasks();
|
||||
@ -156,7 +159,7 @@ void testMain() {
|
||||
|
||||
// An extra call to dispose should be safe.
|
||||
FakeAsync().run((FakeAsync fakeAsync) {
|
||||
expect(() => window.browserHistory.dispose(), returnsNormally);
|
||||
expect(() => implicitView.browserHistory.dispose(), returnsNormally);
|
||||
fakeAsync.flushMicrotasks();
|
||||
});
|
||||
|
||||
@ -169,22 +172,22 @@ void testMain() {
|
||||
expect(strategy.history[1].url, '/initial');
|
||||
|
||||
// Can still teardown after being disposed.
|
||||
await window.browserHistory.tearDown();
|
||||
await implicitView.browserHistory.tearDown();
|
||||
expect(strategy.history, hasLength(2));
|
||||
expect(strategy.currentEntry.state, unwrappedOriginState);
|
||||
expect(strategy.currentEntry.url, '/initial');
|
||||
});
|
||||
|
||||
test('disposes gracefully when url strategy is null', () async {
|
||||
await window.debugInitializeHistory(null, useSingle: true);
|
||||
expect(() => window.browserHistory.dispose(), returnsNormally);
|
||||
await implicitView.debugInitializeHistory(null, useSingle: true);
|
||||
expect(() => implicitView.browserHistory.dispose(), returnsNormally);
|
||||
});
|
||||
|
||||
test('browser back button pops routes correctly', () async {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry(null, null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
// Initially, we should be on the flutter entry.
|
||||
expect(strategy.history, hasLength(2));
|
||||
@ -219,7 +222,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry(null, null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
await routeUpdated('/page1');
|
||||
await routeUpdated('/page2');
|
||||
@ -285,7 +288,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry(null, null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
await strategy.simulateUserTypingUrl('/page3');
|
||||
// This delay is necessary to wait for [BrowserHistory] because it
|
||||
@ -326,7 +329,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry(null, null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
|
||||
await strategy.simulateUserTypingUrl('/unknown');
|
||||
// This delay is necessary to wait for [BrowserHistory] because it
|
||||
@ -356,14 +359,14 @@ void testMain() {
|
||||
|
||||
tearDown(() async {
|
||||
spy.tearDown();
|
||||
await window.resetHistory();
|
||||
await implicitView.resetHistory();
|
||||
});
|
||||
|
||||
test('basic setup works', () async {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
// There should be only one entry.
|
||||
expect(strategy.history, hasLength(1));
|
||||
@ -383,7 +386,7 @@ void testMain() {
|
||||
);
|
||||
expect(strategy.listeners, isEmpty);
|
||||
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
|
||||
// There should be one `popstate` listener and one history entry.
|
||||
@ -393,7 +396,7 @@ void testMain() {
|
||||
expect(strategy.history.single.url, '/initial');
|
||||
|
||||
FakeAsync().run((FakeAsync fakeAsync) {
|
||||
window.browserHistory.dispose();
|
||||
implicitView.browserHistory.dispose();
|
||||
// The `TestUrlStrategy` implementation uses microtasks to schedule the
|
||||
// removal of event listeners.
|
||||
fakeAsync.flushMicrotasks();
|
||||
@ -408,7 +411,7 @@ void testMain() {
|
||||
|
||||
// An extra call to dispose should be safe.
|
||||
FakeAsync().run((FakeAsync fakeAsync) {
|
||||
expect(() => window.browserHistory.dispose(), returnsNormally);
|
||||
expect(() => implicitView.browserHistory.dispose(), returnsNormally);
|
||||
fakeAsync.flushMicrotasks();
|
||||
});
|
||||
|
||||
@ -419,22 +422,22 @@ void testMain() {
|
||||
expect(strategy.history.single.url, '/initial');
|
||||
|
||||
// Can still teardown after being disposed.
|
||||
await window.browserHistory.tearDown();
|
||||
await implicitView.browserHistory.tearDown();
|
||||
expect(strategy.history, hasLength(1));
|
||||
expect(strategy.history.single.state, untaggedState);
|
||||
expect(strategy.history.single.url, '/initial');
|
||||
});
|
||||
|
||||
test('disposes gracefully when url strategy is null', () async {
|
||||
await window.debugInitializeHistory(null, useSingle: false);
|
||||
expect(() => window.browserHistory.dispose(), returnsNormally);
|
||||
await implicitView.debugInitializeHistory(null, useSingle: false);
|
||||
expect(() => implicitView.browserHistory.dispose(), returnsNormally);
|
||||
});
|
||||
|
||||
test('browser back button push route information correctly', () async {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
// Initially, we should be on the flutter entry.
|
||||
expect(strategy.history, hasLength(1));
|
||||
@ -473,7 +476,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
await routeInformationUpdated('/page1', 'page1 state');
|
||||
await routeInformationUpdated('/page2', 'page2 state');
|
||||
@ -522,7 +525,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
await strategy.simulateUserTypingUrl('/page3');
|
||||
// This delay is necessary to wait for [BrowserHistory] because it
|
||||
@ -565,7 +568,7 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/home'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: false);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: false);
|
||||
|
||||
await routeInformationUpdated('/page1', 'page1 state');
|
||||
await routeInformationUpdated('/page2', 'page2 state');
|
||||
@ -743,7 +746,7 @@ void testMain() {
|
||||
|
||||
Future<void> routeUpdated(String routeName) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
implicitView.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'routeUpdated',
|
||||
@ -756,7 +759,7 @@ Future<void> routeUpdated(String routeName) {
|
||||
|
||||
Future<void> routeInformationUpdated(String location, dynamic state) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
implicitView.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -769,7 +772,7 @@ Future<void> routeInformationUpdated(String location, dynamic state) {
|
||||
|
||||
Future<void> systemNavigatorPop() {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
implicitView.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(const MethodCall('SystemNavigator.pop')),
|
||||
(_) => completer.complete(),
|
||||
|
||||
@ -8,9 +8,14 @@ import 'dart:typed_data';
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine.dart' as engine;
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
const engine.MethodCodec codec = engine.JSONMethodCodec();
|
||||
|
||||
engine.EngineFlutterWindow get implicitView =>
|
||||
engine.EnginePlatformDispatcher.instance.implicitView!;
|
||||
|
||||
void emptyCallback(ByteData date) {}
|
||||
|
||||
void main() {
|
||||
@ -20,19 +25,23 @@ void main() {
|
||||
void testMain() {
|
||||
engine.TestUrlStrategy? strategy;
|
||||
|
||||
setUpAll(() {
|
||||
ensureImplicitViewInitialized();
|
||||
});
|
||||
|
||||
setUp(() async {
|
||||
strategy = engine.TestUrlStrategy();
|
||||
await engine.window.debugInitializeHistory(strategy, useSingle: true);
|
||||
await implicitView.debugInitializeHistory(strategy, useSingle: true);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
strategy = null;
|
||||
await engine.window.resetHistory();
|
||||
await implicitView.resetHistory();
|
||||
});
|
||||
|
||||
test('Tracks pushed, replaced and popped routes', () async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
engine.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
codec.encodeMethodCall(const engine.MethodCall(
|
||||
'routeUpdated',
|
||||
|
||||
@ -31,7 +31,7 @@ Future<void> testMain() async {
|
||||
expect(domDocument.title, '');
|
||||
expect(getCssThemeColor(), isNull);
|
||||
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(const MethodCall(
|
||||
'SystemChrome.setApplicationSwitcherDescription',
|
||||
@ -48,7 +48,7 @@ Future<void> testMain() async {
|
||||
expect(domDocument.title, 'Title Test');
|
||||
expect(getCssThemeColor(), expectedPrimaryColor.toCssString());
|
||||
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(const MethodCall(
|
||||
'SystemChrome.setApplicationSwitcherDescription',
|
||||
@ -75,7 +75,7 @@ Future<void> testMain() async {
|
||||
domDocument.title = 'Something Else';
|
||||
expect(domDocument.title, 'Something Else');
|
||||
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(const MethodCall(
|
||||
'SystemChrome.setApplicationSwitcherDescription',
|
||||
@ -93,7 +93,7 @@ Future<void> testMain() async {
|
||||
domDocument.title = 'Something Else';
|
||||
expect(domDocument.title, 'Something Else');
|
||||
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(const MethodCall(
|
||||
'SystemChrome.setApplicationSwitcherDescription',
|
||||
|
||||
@ -18,7 +18,7 @@ void testMain() {
|
||||
const MethodCodec codec = JSONMethodCodec();
|
||||
|
||||
void sendSetSystemUIOverlayStyle({ui.Color? statusBarColor}) {
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'SystemChrome.setSystemUIOverlayStyle',
|
||||
|
||||
@ -28,8 +28,8 @@ void testMain() {
|
||||
late double dpi;
|
||||
|
||||
setUp(() {
|
||||
ui.window.onPointerDataPacket = null;
|
||||
dpi = window.devicePixelRatio;
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = null;
|
||||
dpi = EngineFlutterDisplay.instance.devicePixelRatio;
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
@ -253,7 +253,7 @@ void testMain() {
|
||||
() {
|
||||
final _BasicEventContext context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -285,7 +285,7 @@ void testMain() {
|
||||
() {
|
||||
final _BasicEventContext context = _PointerEventContext();
|
||||
ui.PointerDataPacket? receivedPacket;
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
receivedPacket = packet;
|
||||
};
|
||||
|
||||
@ -301,7 +301,7 @@ void testMain() {
|
||||
() {
|
||||
final _BasicEventContext context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -576,7 +576,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -647,7 +647,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -667,7 +667,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -700,7 +700,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -818,10 +818,10 @@ void testMain() {
|
||||
const double dpi = 2.5;
|
||||
debugOperatingSystemOverride = OperatingSystem.macOs;
|
||||
debugBrowserEngineOverride = BrowserEngine.firefox;
|
||||
window.debugOverrideDevicePixelRatio(dpi);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpi);
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -849,7 +849,7 @@ void testMain() {
|
||||
expect(packets[0].data[0].scrollDeltaX, equals(10.0 * dpi));
|
||||
expect(packets[0].data[0].scrollDeltaY, equals(10.0 * dpi));
|
||||
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
debugOperatingSystemOverride = null;
|
||||
debugBrowserEngineOverride = null;
|
||||
},
|
||||
@ -863,10 +863,10 @@ void testMain() {
|
||||
const double dpi = 2.5;
|
||||
debugOperatingSystemOverride = OperatingSystem.macOs;
|
||||
debugBrowserEngineOverride = BrowserEngine.blink;
|
||||
window.debugOverrideDevicePixelRatio(dpi);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpi);
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -894,7 +894,7 @@ void testMain() {
|
||||
expect(packets[0].data[0].scrollDeltaX, equals(10.0));
|
||||
expect(packets[0].data[0].scrollDeltaY, equals(10.0));
|
||||
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
debugOperatingSystemOverride = null;
|
||||
debugBrowserEngineOverride = null;
|
||||
},
|
||||
@ -910,7 +910,7 @@ void testMain() {
|
||||
}
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1147,7 +1147,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1248,7 +1248,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1372,7 +1372,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1562,7 +1562,7 @@ void testMain() {
|
||||
() {
|
||||
final _ButtonedEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1626,7 +1626,7 @@ void testMain() {
|
||||
// clicking, then dismisses it with a left click.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1708,7 +1708,7 @@ void testMain() {
|
||||
// - Releases RMB.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1777,7 +1777,7 @@ void testMain() {
|
||||
// - Moves mouse.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1823,7 +1823,7 @@ void testMain() {
|
||||
// The move event will have "button:-1, buttons:2".
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1856,7 +1856,7 @@ void testMain() {
|
||||
// - Move the pointer to hover.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1915,7 +1915,7 @@ void testMain() {
|
||||
// could be in a different location without any `*move` events in between.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -1974,7 +1974,7 @@ void testMain() {
|
||||
// - Clicks RMB again in a different location;
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2045,7 +2045,7 @@ void testMain() {
|
||||
// This seems to be happening sometimes when using RMB on the Mac trackpad.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2127,7 +2127,7 @@ void testMain() {
|
||||
// when the context menu is shown.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2189,7 +2189,7 @@ void testMain() {
|
||||
// Flutter: down-------move-------move-------up
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2266,7 +2266,7 @@ void testMain() {
|
||||
// browser window.
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2326,7 +2326,7 @@ void testMain() {
|
||||
final _MultiPointerEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
List<ui.PointerData> data;
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2491,7 +2491,7 @@ void testMain() {
|
||||
() {
|
||||
final _MultiPointerEventMixin context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2532,7 +2532,7 @@ void testMain() {
|
||||
() {
|
||||
final _PointerEventContext context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2569,7 +2569,7 @@ void testMain() {
|
||||
() {
|
||||
final _PointerEventContext context = _PointerEventContext();
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2596,7 +2596,7 @@ void testMain() {
|
||||
// For more info, see: https://github.com/flutter/flutter/issues/75559
|
||||
|
||||
final List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
@ -2684,7 +2684,7 @@ void _testClickDebouncer() {
|
||||
context = _PointerEventContext();
|
||||
pointerPackets = <ui.PointerChange>[];
|
||||
semanticsActions = <CapturedSemanticsEvent>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
ui.PlatformDispatcher.instance.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
for (final ui.PointerData data in packet.data) {
|
||||
pointerPackets.add(data.change);
|
||||
}
|
||||
|
||||
@ -7,11 +7,7 @@ import 'dart:typed_data';
|
||||
import 'package:quiver/testing/async.dart';
|
||||
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/raw_keyboard.dart';
|
||||
import 'package:ui/src/engine/services.dart';
|
||||
import 'package:ui/src/engine/text_editing/text_editing.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
void main() {
|
||||
@ -20,15 +16,15 @@ void main() {
|
||||
|
||||
void testMain() {
|
||||
group('RawKeyboard', () {
|
||||
/// Used to save and restore [ui.window.onPlatformMessage] after each test.
|
||||
/// Used to save and restore [PlatformDispatcher.onPlatformMessage] after each test.
|
||||
ui.PlatformMessageCallback? savedCallback;
|
||||
|
||||
setUp(() {
|
||||
savedCallback = ui.window.onPlatformMessage;
|
||||
savedCallback = ui.PlatformDispatcher.instance.onPlatformMessage;
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
ui.window.onPlatformMessage = savedCallback;
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = savedCallback;
|
||||
});
|
||||
|
||||
test('initializes and disposes', () {
|
||||
@ -44,7 +40,7 @@ void testMain() {
|
||||
|
||||
String? channelReceived;
|
||||
Map<String, dynamic>? dataReceived;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
channelReceived = channel;
|
||||
dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
|
||||
@ -78,7 +74,7 @@ void testMain() {
|
||||
|
||||
String? channelReceived;
|
||||
Map<String, dynamic>? dataReceived;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
channelReceived = channel;
|
||||
dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
|
||||
@ -108,7 +104,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
Map<String, dynamic>? dataReceived;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
|
||||
};
|
||||
@ -161,7 +157,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
Map<String, dynamic>? dataReceived;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
|
||||
};
|
||||
@ -189,7 +185,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
@ -242,7 +238,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
};
|
||||
@ -266,7 +262,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': true})!;
|
||||
@ -289,7 +285,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': false})!;
|
||||
@ -312,7 +308,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
};
|
||||
@ -338,7 +334,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': true})!;
|
||||
@ -364,7 +360,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
int count = 0;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
count += 1;
|
||||
final ByteData response = const JSONMessageCodec()
|
||||
@ -395,7 +391,7 @@ void testMain() {
|
||||
RawKeyboard.initialize(onMacOs: true);
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
@ -518,7 +514,7 @@ void testMain() {
|
||||
RawKeyboard.initialize(onMacOs: true);
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
@ -600,7 +596,7 @@ void testMain() {
|
||||
RawKeyboard.initialize();
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
@ -630,7 +626,7 @@ void testMain() {
|
||||
RawKeyboard.initialize(onMacOs: true);
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
@ -694,7 +690,7 @@ void testMain() {
|
||||
RawKeyboard.initialize(); // onMacOs: false
|
||||
|
||||
final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
|
||||
};
|
||||
|
||||
@ -27,25 +27,33 @@ void main() {
|
||||
}
|
||||
|
||||
void testMain() {
|
||||
late EngineFlutterWindow window;
|
||||
EngineFlutterWindow? savedWindow;
|
||||
late EngineFlutterWindow myWindow;
|
||||
|
||||
setUpAll(() async {
|
||||
await initializeEngine();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
window = EngineFlutterWindow(0, EnginePlatformDispatcher.instance);
|
||||
savedWindow = EnginePlatformDispatcher.instance.implicitView;
|
||||
myWindow = EngineFlutterWindow(0, EnginePlatformDispatcher.instance);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await window.resetHistory();
|
||||
await myWindow.resetHistory();
|
||||
|
||||
// Restore the original implicit view.
|
||||
EnginePlatformDispatcher.instance.unregisterView(myWindow);
|
||||
if (savedWindow != null) {
|
||||
EnginePlatformDispatcher.instance.registerView(savedWindow!);
|
||||
}
|
||||
});
|
||||
|
||||
// For now, web always has an implicit view provided by the web engine.
|
||||
test('EnginePlatformDispatcher.instance.implicitView should be non-null', () async {
|
||||
expect(EnginePlatformDispatcher.instance.implicitView, isNotNull);
|
||||
expect(EnginePlatformDispatcher.instance.implicitView?.viewId, 0);
|
||||
expect(window.viewId, 0);
|
||||
expect(myWindow.viewId, 0);
|
||||
});
|
||||
|
||||
test('window.defaultRouteName should work with a custom url strategy', () async {
|
||||
@ -53,8 +61,8 @@ void testMain() {
|
||||
const Object state = <dynamic, dynamic>{'origin': true};
|
||||
|
||||
final _SampleUrlStrategy customStrategy = _SampleUrlStrategy(path, state);
|
||||
await window.debugInitializeHistory(customStrategy, useSingle: true);
|
||||
expect(window.defaultRouteName, '/initial');
|
||||
await myWindow.debugInitializeHistory(customStrategy, useSingle: true);
|
||||
expect(myWindow.defaultRouteName, '/initial');
|
||||
// Also make sure that the custom url strategy was actually used.
|
||||
expect(customStrategy.wasUsed, isTrue);
|
||||
});
|
||||
@ -63,12 +71,12 @@ void testMain() {
|
||||
final TestUrlStrategy strategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
);
|
||||
await window.debugInitializeHistory(strategy, useSingle: true);
|
||||
expect(window.defaultRouteName, '/initial');
|
||||
await myWindow.debugInitializeHistory(strategy, useSingle: true);
|
||||
expect(myWindow.defaultRouteName, '/initial');
|
||||
|
||||
// Changing the URL in the address bar later shouldn't affect [window.defaultRouteName].
|
||||
strategy.replaceState(null, '', '/newpath');
|
||||
expect(window.defaultRouteName, '/initial');
|
||||
expect(myWindow.defaultRouteName, '/initial');
|
||||
});
|
||||
|
||||
// window.defaultRouteName is now permanently decoupled from the history,
|
||||
@ -76,17 +84,17 @@ void testMain() {
|
||||
|
||||
test('window.defaultRouteName should reset after navigation platform message',
|
||||
() async {
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
// The URL here does not set the PlatformDispatcher's defaultRouteName,
|
||||
// since it got cached as soon as we read it above.
|
||||
const TestHistoryEntry('initial state', null, '/not-really-inital/THIS_IS_IGNORED'),
|
||||
), useSingle: true);
|
||||
// Reading it multiple times should return the same value.
|
||||
expect(window.defaultRouteName, '/initial');
|
||||
expect(window.defaultRouteName, '/initial');
|
||||
expect(myWindow.defaultRouteName, '/initial');
|
||||
expect(myWindow.defaultRouteName, '/initial');
|
||||
|
||||
final Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeUpdated',
|
||||
@ -97,27 +105,27 @@ void testMain() {
|
||||
await callback.future;
|
||||
// After a navigation platform message, the PlatformDispatcher's
|
||||
// defaultRouteName resets to "/".
|
||||
expect(window.defaultRouteName, '/');
|
||||
expect(myWindow.defaultRouteName, '/');
|
||||
});
|
||||
|
||||
// window.defaultRouteName is now '/'.
|
||||
|
||||
test('can switch history mode', () async {
|
||||
Completer<void> callback;
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
|
||||
Future<void> check<T>(String method, Object? arguments) async {
|
||||
callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(MethodCall(method, arguments)),
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<T>());
|
||||
expect(myWindow.browserHistory, isA<T>());
|
||||
}
|
||||
|
||||
// These may be initialized as `null`
|
||||
@ -135,7 +143,7 @@ void testMain() {
|
||||
test('handleNavigationMessage throws for route update methods called with null arguments',
|
||||
() async {
|
||||
expect(() async {
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeUpdated',
|
||||
))
|
||||
@ -143,7 +151,7 @@ void testMain() {
|
||||
}, throwsAssertionError);
|
||||
|
||||
expect(() async {
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
))
|
||||
@ -153,33 +161,33 @@ void testMain() {
|
||||
|
||||
test('handleNavigationMessage execute request in order.', () async {
|
||||
// Start with multi entries.
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
final List<String> executionOrder = <String>[];
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'selectSingleEntryHistory',
|
||||
))
|
||||
).then<void>((bool data) {
|
||||
executionOrder.add('1');
|
||||
});
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'selectMultiEntryHistory',
|
||||
))
|
||||
).then<void>((bool data) {
|
||||
executionOrder.add('2');
|
||||
});
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'selectSingleEntryHistory',
|
||||
))
|
||||
).then<void>((bool data) {
|
||||
executionOrder.add('3');
|
||||
});
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
<String, dynamic>{
|
||||
@ -201,14 +209,14 @@ void testMain() {
|
||||
|
||||
test('should not throw when using nav1 and nav2 together',
|
||||
() async {
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
|
||||
// routeUpdated resets the history type
|
||||
Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeUpdated',
|
||||
@ -217,12 +225,12 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/bar');
|
||||
expect(myWindow.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/bar');
|
||||
|
||||
// routeInformationUpdated does not
|
||||
callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -234,31 +242,31 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(myWindow.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
|
||||
// they can be interleaved safely
|
||||
await window.handleNavigationMessage(
|
||||
await myWindow.handleNavigationMessage(
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeUpdated',
|
||||
<String, dynamic>{'routeName': '/foo'},
|
||||
))
|
||||
);
|
||||
expect(window.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/foo');
|
||||
expect(myWindow.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/foo');
|
||||
});
|
||||
|
||||
test('should not throw when state is complex json object',
|
||||
() async {
|
||||
// Regression test https://github.com/flutter/flutter/issues/87823.
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
|
||||
// routeInformationUpdated does not
|
||||
final Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -278,9 +286,9 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
final dynamic wrappedState = window.browserHistory.urlStrategy!.getState();
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
final dynamic wrappedState = myWindow.browserHistory.urlStrategy!.getState();
|
||||
final dynamic actualState = wrappedState['state'];
|
||||
expect(actualState['state1'], true);
|
||||
expect(actualState['state2'], 1);
|
||||
@ -291,14 +299,14 @@ void testMain() {
|
||||
|
||||
test('routeInformationUpdated can handle uri',
|
||||
() async {
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
|
||||
// routeInformationUpdated does not
|
||||
final Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -309,19 +317,19 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz?abc=def#fragment');
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz?abc=def#fragment');
|
||||
});
|
||||
|
||||
test('can replace in MultiEntriesBrowserHistory',
|
||||
() async {
|
||||
await window.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
await myWindow.debugInitializeHistory(TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/initial'),
|
||||
), useSingle: false);
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
|
||||
Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -333,11 +341,11 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(window.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state', 1));
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(myWindow.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state', 1));
|
||||
|
||||
callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -350,11 +358,11 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(window.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state1', 1));
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(myWindow.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state1', 1));
|
||||
|
||||
callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -366,12 +374,12 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/foo');
|
||||
expect(window.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/foostate1', 2));
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/foo');
|
||||
expect(myWindow.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/foostate1', 2));
|
||||
|
||||
await window.browserHistory.back();
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(window.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state1', 1));
|
||||
await myWindow.browserHistory.back();
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(myWindow.browserHistory.urlStrategy!.getState(), _tagStateWithSerialCount('/state1', 1));
|
||||
});
|
||||
|
||||
test('initialize browser history with default url strategy (single)', () async {
|
||||
@ -380,10 +388,10 @@ void testMain() {
|
||||
|
||||
// Without initializing history, the default route name should be
|
||||
// initialized to "/" in tests.
|
||||
expect(window.defaultRouteName, '/');
|
||||
expect(myWindow.defaultRouteName, '/');
|
||||
|
||||
final Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeUpdated',
|
||||
@ -392,11 +400,11 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<SingleEntryBrowserHistory>());
|
||||
// The url strategy should've been set to the default, and the path
|
||||
// should've been correctly set to "/bar".
|
||||
expect(window.browserHistory.urlStrategy, isNot(isNull));
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/bar');
|
||||
expect(myWindow.browserHistory.urlStrategy, isNot(isNull));
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/bar');
|
||||
}, skip: isSafari); // https://github.com/flutter/flutter/issues/50836
|
||||
|
||||
test('initialize browser history with default url strategy (multiple)', () async {
|
||||
@ -405,10 +413,10 @@ void testMain() {
|
||||
|
||||
// Without initializing history, the default route name should be
|
||||
// initialized to "/" in tests.
|
||||
expect(window.defaultRouteName, '/');
|
||||
expect(myWindow.defaultRouteName, '/');
|
||||
|
||||
final Completer<void> callback = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/navigation',
|
||||
const JSONMethodCodec().encodeMethodCall(const MethodCall(
|
||||
'routeInformationUpdated',
|
||||
@ -420,11 +428,11 @@ void testMain() {
|
||||
(_) { callback.complete(); },
|
||||
);
|
||||
await callback.future;
|
||||
expect(window.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
expect(myWindow.browserHistory, isA<MultiEntriesBrowserHistory>());
|
||||
// The url strategy should've been set to the default, and the path
|
||||
// should've been correctly set to "/baz".
|
||||
expect(window.browserHistory.urlStrategy, isNot(isNull));
|
||||
expect(window.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
expect(myWindow.browserHistory.urlStrategy, isNot(isNull));
|
||||
expect(myWindow.browserHistory.urlStrategy!.getPath(), '/baz');
|
||||
}, skip: isSafari); // https://github.com/flutter/flutter/issues/50836
|
||||
|
||||
test('can disable location strategy', () async {
|
||||
@ -436,23 +444,23 @@ void testMain() {
|
||||
returnsNormally,
|
||||
);
|
||||
// History should be initialized.
|
||||
expect(window.browserHistory, isNotNull);
|
||||
expect(myWindow.browserHistory, isNotNull);
|
||||
// But without a URL strategy.
|
||||
expect(window.browserHistory.urlStrategy, isNull);
|
||||
expect(myWindow.browserHistory.urlStrategy, isNull);
|
||||
// Current path is always "/" in this case.
|
||||
expect(window.browserHistory.currentPath, '/');
|
||||
expect(myWindow.browserHistory.currentPath, '/');
|
||||
|
||||
// Perform some navigation operations.
|
||||
await routeInformationUpdated('/foo/bar', null);
|
||||
// Path should not be updated because URL strategy is disabled.
|
||||
expect(window.browserHistory.currentPath, '/');
|
||||
expect(myWindow.browserHistory.currentPath, '/');
|
||||
});
|
||||
|
||||
test('cannot set url strategy after it was initialized', () async {
|
||||
final TestUrlStrategy testStrategy = TestUrlStrategy.fromEntry(
|
||||
const TestHistoryEntry('initial state', null, '/'),
|
||||
);
|
||||
await window.debugInitializeHistory(testStrategy, useSingle: true);
|
||||
await myWindow.debugInitializeHistory(testStrategy, useSingle: true);
|
||||
|
||||
expect(
|
||||
() {
|
||||
@ -482,8 +490,8 @@ void testMain() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/77817
|
||||
test('window.locale(s) are not nullable', () {
|
||||
// If the getters were nullable, these expressions would result in compiler errors.
|
||||
ui.window.locale.countryCode;
|
||||
ui.window.locales.first.countryCode;
|
||||
ui.PlatformDispatcher.instance.locale.countryCode;
|
||||
ui.PlatformDispatcher.instance.locales.first.countryCode;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,11 @@ class StubPictureRenderer implements PictureRenderer {
|
||||
void testMain() {
|
||||
late EngineSceneView sceneView;
|
||||
late StubPictureRenderer stubPictureRenderer;
|
||||
|
||||
setUpAll(() {
|
||||
ensureImplicitViewInitialized();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
stubPictureRenderer = StubPictureRenderer();
|
||||
sceneView = EngineSceneView(stubPictureRenderer);
|
||||
|
||||
@ -2513,16 +2513,15 @@ void _testPlatformView() {
|
||||
width: 20,
|
||||
height: 30,
|
||||
);
|
||||
ui.window.render(sceneBuilder.build());
|
||||
ui.PlatformDispatcher.instance.render(sceneBuilder.build());
|
||||
|
||||
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
|
||||
final double dpr = EngineFlutterDisplay.instance.devicePixelRatio;
|
||||
updateNode(builder,
|
||||
rect: const ui.Rect.fromLTRB(0, 0, 20, 60),
|
||||
childrenInTraversalOrder: Int32List.fromList(<int>[1, 2, 3]),
|
||||
childrenInHitTestOrder: Int32List.fromList(<int>[1, 2, 3]),
|
||||
transform: Float64List.fromList(Matrix4.diagonal3Values(
|
||||
ui.window.devicePixelRatio, ui.window.devicePixelRatio, 1)
|
||||
.storage));
|
||||
transform: Float64List.fromList(Matrix4.diagonal3Values(dpr, dpr, 1).storage));
|
||||
updateNode(
|
||||
builder,
|
||||
id: 1,
|
||||
@ -3137,7 +3136,7 @@ const MethodCodec codec = StandardMethodCodec();
|
||||
/// Sends a platform message to create a Platform View with the given id and viewType.
|
||||
Future<void> createPlatformView(int id, String viewType) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
ui.window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'create',
|
||||
@ -3154,7 +3153,7 @@ Future<void> createPlatformView(int id, String viewType) {
|
||||
/// Disposes of the platform view with the given [id].
|
||||
Future<void> disposePlatformView(int id) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall('dispose', id)),
|
||||
(dynamic _) => completer.complete(),
|
||||
|
||||
@ -371,7 +371,7 @@ DomElement? findScrollable() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Logs semantics actions dispatched to [ui.window].
|
||||
/// Logs semantics actions dispatched to [ui.PlatformDispatcher].
|
||||
class SemanticsActionLogger {
|
||||
SemanticsActionLogger() {
|
||||
_idLogController = StreamController<int>();
|
||||
@ -401,7 +401,7 @@ class SemanticsActionLogger {
|
||||
Stream<int> get idLog => _idLog;
|
||||
late Stream<int> _idLog;
|
||||
|
||||
/// The actions that were dispatched to [ui.window].
|
||||
/// The actions that were dispatched to [ui.PlatformDispatcher].
|
||||
Stream<ui.SemanticsAction> get actionLog => _actionLog;
|
||||
late Stream<ui.SemanticsAction> _actionLog;
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ Future<void> testMain() async {
|
||||
// Sends a platform message to create a Platform View with the given id and viewType.
|
||||
Future<void> _createPlatformView(int id, String viewType) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'create',
|
||||
|
||||
@ -477,7 +477,7 @@ void testMain() {
|
||||
// Pump an empty scene to reset it, otherwise the first frame will attempt
|
||||
// to diff left-overs from a previous test, which results in unpredictable
|
||||
// DOM mutations.
|
||||
window.render(SurfaceSceneBuilder().build());
|
||||
ui.PlatformDispatcher.instance.render(SurfaceSceneBuilder().build());
|
||||
|
||||
// Renders a `string` by breaking it up into individual characters and
|
||||
// rendering each character into its own layer.
|
||||
|
||||
@ -373,10 +373,10 @@ Future<void> testMain() async {
|
||||
});
|
||||
|
||||
test('handling keyboard event prevents triggering input action', () {
|
||||
final ui.PlatformMessageCallback? savedCallback = ui.window.onPlatformMessage;
|
||||
final ui.PlatformMessageCallback? savedCallback = ui.PlatformDispatcher.instance.onPlatformMessage;
|
||||
|
||||
bool markTextEventHandled = false;
|
||||
ui.window.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String channel, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
final ByteData response = const JSONMessageCodec()
|
||||
.encodeMessage(<String, dynamic>{'handled': markTextEventHandled})!;
|
||||
@ -414,7 +414,7 @@ Future<void> testMain() async {
|
||||
// Input action received.
|
||||
expect(lastInputAction, 'TextInputAction.done');
|
||||
|
||||
ui.window.onPlatformMessage = savedCallback;
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = savedCallback;
|
||||
RawKeyboard.instance?.dispose();
|
||||
});
|
||||
|
||||
|
||||
@ -9,9 +9,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider.dart';
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
import 'package:ui/ui.dart' as ui show Size;
|
||||
|
||||
void main() {
|
||||
@ -42,7 +40,7 @@ void doTests() {
|
||||
const double dpr = 2.5;
|
||||
const double logicalWidth = 50;
|
||||
const double logicalHeight = 75;
|
||||
window.debugOverrideDevicePixelRatio(dpr);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpr);
|
||||
|
||||
sizeSource
|
||||
..style.width = '${logicalWidth}px'
|
||||
@ -75,7 +73,7 @@ void doTests() {
|
||||
test('from viewport physical size (simulated keyboard) - always zero', () {
|
||||
// Simulate a 100px tall keyboard showing...
|
||||
const double dpr = 2.5;
|
||||
window.debugOverrideDevicePixelRatio(dpr);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpr);
|
||||
const double keyboardGap = 100;
|
||||
final double physicalHeight =
|
||||
(domWindow.visualViewport!.height! + keyboardGap) * dpr;
|
||||
|
||||
@ -7,11 +7,7 @@ library;
|
||||
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider.dart';
|
||||
import 'package:ui/src/engine/view_embedder/dimensions_provider/dimensions_provider.dart';
|
||||
import 'package:ui/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart';
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
|
||||
void main() {
|
||||
internalBootstrapBrowserTest(() => doTests);
|
||||
@ -39,7 +35,7 @@ void doTests() {
|
||||
group('getDevicePixelRatio', () {
|
||||
test('Returns the correct pixelRatio', () async {
|
||||
// Override the DPI to something known, but weird...
|
||||
window.debugOverrideDevicePixelRatio(33930);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(33930);
|
||||
|
||||
final DimensionsProvider provider = DimensionsProvider.create();
|
||||
|
||||
|
||||
@ -9,9 +9,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart';
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
import 'package:ui/ui.dart' as ui show Size;
|
||||
|
||||
void main() {
|
||||
@ -28,7 +26,7 @@ void doTests() {
|
||||
|
||||
test('returns visualViewport physical size (width * dpr)', () {
|
||||
const double dpr = 2.5;
|
||||
window.debugOverrideDevicePixelRatio(dpr);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpr);
|
||||
final ui.Size expected = ui.Size(domWindow.visualViewport!.width! * dpr,
|
||||
domWindow.visualViewport!.height! * dpr);
|
||||
|
||||
@ -48,7 +46,7 @@ void doTests() {
|
||||
test('from viewport physical size (simulated keyboard)', () {
|
||||
// Simulate a 100px tall keyboard showing...
|
||||
const double dpr = 2.5;
|
||||
window.debugOverrideDevicePixelRatio(dpr);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(dpr);
|
||||
const double keyboardGap = 100;
|
||||
final double physicalHeight =
|
||||
(domWindow.visualViewport!.height! + keyboardGap) * dpr;
|
||||
|
||||
@ -13,6 +13,7 @@ void main() {
|
||||
void doTests() {
|
||||
group('DomManager', () {
|
||||
test('fromFlutterViewEmbedderDEPRECATED', () {
|
||||
ensureImplicitViewInitialized();
|
||||
final FlutterViewEmbedder embedder = FlutterViewEmbedder();
|
||||
final DomManager domManager =
|
||||
DomManager.fromFlutterViewEmbedderDEPRECATED(embedder);
|
||||
|
||||
@ -23,6 +23,17 @@ void main() {
|
||||
Future<void> testMain() async {
|
||||
await ui_web.bootstrapEngine();
|
||||
|
||||
late EngineFlutterWindow myWindow;
|
||||
|
||||
setUp(() {
|
||||
myWindow = EngineFlutterWindow(99, EnginePlatformDispatcher.instance);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await myWindow.resetHistory();
|
||||
EnginePlatformDispatcher.instance.unregisterView(myWindow);
|
||||
});
|
||||
|
||||
test('onTextScaleFactorChanged preserves the zone', () {
|
||||
final Zone innerZone = Zone.current.fork();
|
||||
|
||||
@ -30,10 +41,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onTextScaleFactorChanged = callback;
|
||||
myWindow.onTextScaleFactorChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onTextScaleFactorChanged, same(callback));
|
||||
expect(myWindow.onTextScaleFactorChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnTextScaleFactorChanged();
|
||||
@ -46,10 +57,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onPlatformBrightnessChanged = callback;
|
||||
myWindow.onPlatformBrightnessChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onPlatformBrightnessChanged, same(callback));
|
||||
expect(myWindow.onPlatformBrightnessChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnPlatformBrightnessChanged();
|
||||
@ -62,10 +73,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onMetricsChanged = callback;
|
||||
myWindow.onMetricsChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onMetricsChanged, same(callback));
|
||||
expect(myWindow.onMetricsChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnMetricsChanged();
|
||||
@ -78,10 +89,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onLocaleChanged = callback;
|
||||
myWindow.onLocaleChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onLocaleChanged, same(callback));
|
||||
expect(myWindow.onLocaleChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnLocaleChanged();
|
||||
@ -94,10 +105,10 @@ Future<void> testMain() async {
|
||||
void callback(Duration _) {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onBeginFrame = callback;
|
||||
myWindow.onBeginFrame = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onBeginFrame, same(callback));
|
||||
expect(myWindow.onBeginFrame, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnBeginFrame(Duration.zero);
|
||||
@ -110,10 +121,10 @@ Future<void> testMain() async {
|
||||
void callback(List<dynamic> _) {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onReportTimings = callback;
|
||||
myWindow.onReportTimings = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onReportTimings, same(callback));
|
||||
expect(myWindow.onReportTimings, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnReportTimings(<ui.FrameTiming>[]);
|
||||
@ -126,10 +137,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onDrawFrame = callback;
|
||||
myWindow.onDrawFrame = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onDrawFrame, same(callback));
|
||||
expect(myWindow.onDrawFrame, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnDrawFrame();
|
||||
@ -142,10 +153,10 @@ Future<void> testMain() async {
|
||||
void callback(ui.PointerDataPacket _) {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onPointerDataPacket = callback;
|
||||
myWindow.onPointerDataPacket = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onPointerDataPacket, same(callback));
|
||||
expect(myWindow.onPointerDataPacket, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnPointerDataPacket(const ui.PointerDataPacket());
|
||||
@ -175,11 +186,11 @@ Future<void> testMain() async {
|
||||
expect(Zone.current, innerZone);
|
||||
return false;
|
||||
}
|
||||
window.onKeyData = onKeyData;
|
||||
myWindow.onKeyData = onKeyData;
|
||||
|
||||
// Test that the getter returns the exact same onKeyData, e.g. it doesn't
|
||||
// wrap it.
|
||||
expect(window.onKeyData, same(onKeyData));
|
||||
expect(myWindow.onKeyData, same(onKeyData));
|
||||
});
|
||||
|
||||
const ui.KeyData keyData = ui.KeyData(
|
||||
@ -194,7 +205,7 @@ Future<void> testMain() async {
|
||||
expect(result, isFalse);
|
||||
});
|
||||
|
||||
window.onKeyData = null;
|
||||
myWindow.onKeyData = null;
|
||||
});
|
||||
|
||||
test('onSemanticsEnabledChanged preserves the zone', () {
|
||||
@ -204,10 +215,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onSemanticsEnabledChanged = callback;
|
||||
myWindow.onSemanticsEnabledChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onSemanticsEnabledChanged, same(callback));
|
||||
expect(myWindow.onSemanticsEnabledChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnSemanticsEnabledChanged();
|
||||
@ -236,10 +247,10 @@ Future<void> testMain() async {
|
||||
void callback() {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onAccessibilityFeaturesChanged = callback;
|
||||
myWindow.onAccessibilityFeaturesChanged = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onAccessibilityFeaturesChanged, same(callback));
|
||||
expect(myWindow.onAccessibilityFeaturesChanged, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnAccessibilityFeaturesChanged();
|
||||
@ -252,10 +263,10 @@ Future<void> testMain() async {
|
||||
void callback(String _, ByteData? __, void Function(ByteData?)? ___) {
|
||||
expect(Zone.current, innerZone);
|
||||
}
|
||||
window.onPlatformMessage = callback;
|
||||
myWindow.onPlatformMessage = callback;
|
||||
|
||||
// Test that the getter returns the exact same callback, e.g. it doesn't wrap it.
|
||||
expect(window.onPlatformMessage, same(callback));
|
||||
expect(myWindow.onPlatformMessage, same(callback));
|
||||
});
|
||||
|
||||
EnginePlatformDispatcher.instance.invokeOnPlatformMessage('foo', null, (ByteData? data) {
|
||||
@ -270,7 +281,7 @@ Future<void> testMain() async {
|
||||
innerZone.runGuarded(() {
|
||||
final ByteData inputData = ByteData(4);
|
||||
inputData.setUint32(0, 42);
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/debug-echo',
|
||||
inputData,
|
||||
(ByteData? outputData) {
|
||||
@ -288,7 +299,7 @@ Future<void> testMain() async {
|
||||
|
||||
final ByteData inputData = ByteData(4);
|
||||
inputData.setUint32(0, 42);
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/__unknown__channel__',
|
||||
null,
|
||||
(ByteData? outputData) {
|
||||
@ -309,7 +320,7 @@ Future<void> testMain() async {
|
||||
orientations,
|
||||
));
|
||||
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/platform',
|
||||
inputData,
|
||||
(ByteData? outputData) {
|
||||
@ -411,7 +422,7 @@ Future<void> testMain() async {
|
||||
test('SingletonFlutterWindow implements locale, locales, and locale change notifications', () async {
|
||||
// This will count how many times we notified about locale changes.
|
||||
int localeChangedCount = 0;
|
||||
window.onLocaleChanged = () {
|
||||
myWindow.onLocaleChanged = () {
|
||||
localeChangedCount += 1;
|
||||
};
|
||||
|
||||
@ -420,18 +431,18 @@ Future<void> testMain() async {
|
||||
// We populate the initial list of locales automatically (only test that we
|
||||
// got some locales; some contributors may be in different locales, so we
|
||||
// can't test the exact contents).
|
||||
expect(window.locale, isA<ui.Locale>());
|
||||
expect(window.locales, isNotEmpty);
|
||||
expect(myWindow.locale, isA<ui.Locale>());
|
||||
expect(myWindow.locales, isNotEmpty);
|
||||
|
||||
// Trigger a change notification (reset locales because the notification
|
||||
// doesn't actually change the list of languages; the test only observes
|
||||
// that the list is populated again).
|
||||
EnginePlatformDispatcher.instance.debugResetLocales();
|
||||
expect(window.locales, isEmpty);
|
||||
expect(window.locale, equals(const ui.Locale.fromSubtags()));
|
||||
expect(myWindow.locales, isEmpty);
|
||||
expect(myWindow.locale, equals(const ui.Locale.fromSubtags()));
|
||||
expect(localeChangedCount, 0);
|
||||
domWindow.dispatchEvent(createDomEvent('Event', 'languagechange'));
|
||||
expect(window.locales, isNotEmpty);
|
||||
expect(myWindow.locales, isNotEmpty);
|
||||
expect(localeChangedCount, 1);
|
||||
});
|
||||
|
||||
@ -442,7 +453,7 @@ Future<void> testMain() async {
|
||||
final Zone innerZone = Zone.current.fork();
|
||||
|
||||
innerZone.runGuarded(() {
|
||||
window.sendPlatformMessage(
|
||||
myWindow.sendPlatformMessage(
|
||||
'flutter/service_worker',
|
||||
ByteData(0),
|
||||
(ByteData? outputData) { },
|
||||
|
||||
@ -157,7 +157,7 @@ Future<void> testMain() async {
|
||||
|
||||
for (final int testDpr in <int>[1, 2, 4]) {
|
||||
test('MaskFilter.blur blurs correctly for device-pixel ratio $testDpr', () async {
|
||||
window.debugOverrideDevicePixelRatio(testDpr.toDouble());
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(testDpr.toDouble());
|
||||
const ui.Rect screenRect = ui.Rect.fromLTWH(0, 0, 150, 150);
|
||||
|
||||
final RecordingCanvas rc = RecordingCanvas(screenRect);
|
||||
@ -174,7 +174,7 @@ Future<void> testMain() async {
|
||||
|
||||
await canvasScreenshot(rc, 'mask_filter_blur_dpr_$testDpr',
|
||||
region: screenRect);
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +408,7 @@ void testMain() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/44470
|
||||
test('Should handle contains for devicepixelratio != 1.0', () {
|
||||
js_util.setProperty(domWindow, 'devicePixelRatio', 4.0);
|
||||
window.debugOverrideDevicePixelRatio(4.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(4.0);
|
||||
final Path path = Path()
|
||||
..moveTo(50, 0)
|
||||
..lineTo(100, 100)
|
||||
@ -417,7 +417,7 @@ void testMain() {
|
||||
..close();
|
||||
expect(path.contains(const Offset(50, 50)), isTrue);
|
||||
js_util.setProperty(domWindow, 'devicePixelRatio', 1.0);
|
||||
window.debugOverrideDevicePixelRatio(1.0);
|
||||
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);
|
||||
// TODO(ferhat): Investigate failure on CI. Locally this passes.
|
||||
// [Exception... "Failure" nsresult: "0x80004005 (NS_ERROR_FAILURE)"
|
||||
}, skip: browserEngine == BrowserEngine.firefox);
|
||||
|
||||
@ -806,7 +806,7 @@ Future<void> testMain() async {
|
||||
builder.addPicture(ui.Offset.zero, picture);
|
||||
final ui.Scene scene = builder.build();
|
||||
|
||||
ui.window.render(scene);
|
||||
ui.PlatformDispatcher.instance.render(scene);
|
||||
|
||||
picture.dispose();
|
||||
scene.dispose();
|
||||
|
||||
@ -70,10 +70,10 @@ Future<void> testMain() async {
|
||||
skip: browserEngine == BrowserEngine.webkit);
|
||||
|
||||
test('loading font should send font change message', () async {
|
||||
final ui.PlatformMessageCallback? oldHandler = ui.window.onPlatformMessage;
|
||||
final ui.PlatformMessageCallback? oldHandler = ui.PlatformDispatcher.instance.onPlatformMessage;
|
||||
String? actualName;
|
||||
String? message;
|
||||
window.onPlatformMessage = (String name, ByteData? data,
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = (String name, ByteData? data,
|
||||
ui.PlatformMessageResponseCallback? callback) {
|
||||
actualName = name;
|
||||
final ByteBuffer buffer = data!.buffer;
|
||||
@ -86,7 +86,7 @@ Future<void> testMain() async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
domWindow.requestAnimationFrame((_) { completer.complete();});
|
||||
await completer.future;
|
||||
window.onPlatformMessage = oldHandler;
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = oldHandler;
|
||||
expect(actualName, 'flutter/system');
|
||||
expect(message, '{"type":"fontsChange"}');
|
||||
},
|
||||
|
||||
@ -410,7 +410,9 @@ Future<void> testMain() async {
|
||||
group('test fonts in flutterTester environment', () {
|
||||
final bool resetValue = ui_web.debugEmulateFlutterTesterEnvironment;
|
||||
ui_web.debugEmulateFlutterTesterEnvironment = true;
|
||||
tearDownAll(() => ui_web.debugEmulateFlutterTesterEnvironment = resetValue);
|
||||
tearDownAll(() {
|
||||
ui_web.debugEmulateFlutterTesterEnvironment = resetValue;
|
||||
});
|
||||
const List<String> testFonts = <String>['FlutterTest', 'Ahem'];
|
||||
|
||||
test('The default test font is used when a non-test fontFamily is specified, or fontFamily is not specified', () {
|
||||
|
||||
@ -31,7 +31,7 @@ void testMain() {
|
||||
debugDisableFontFallbacks = false;
|
||||
});
|
||||
|
||||
/// Used to save and restore [ui.window.onPlatformMessage] after each test.
|
||||
/// Used to save and restore [ui.PlatformDispatcher.onPlatformMessage] after each test.
|
||||
ui.PlatformMessageCallback? savedCallback;
|
||||
|
||||
final List<String> downloadedFontFamilies = <String>[];
|
||||
@ -41,12 +41,12 @@ void testMain() {
|
||||
renderer.fontCollection.fontFallbackManager!.downloadQueue.fallbackFontUrlPrefixOverride = 'assets/fallback_fonts/';
|
||||
renderer.fontCollection.fontFallbackManager!.downloadQueue.debugOnLoadFontFamily
|
||||
= (String family) => downloadedFontFamilies.add(family);
|
||||
savedCallback = ui.window.onPlatformMessage;
|
||||
savedCallback = ui.PlatformDispatcher.instance.onPlatformMessage;
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
downloadedFontFamilies.clear();
|
||||
ui.window.onPlatformMessage = savedCallback;
|
||||
ui.PlatformDispatcher.instance.onPlatformMessage = savedCallback;
|
||||
});
|
||||
|
||||
test('Roboto is always a fallback font', () {
|
||||
|
||||
@ -164,7 +164,7 @@ Future<void> testMain() async {
|
||||
Future<void> _createPlatformView(int id, String viewType) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
const MethodCodec codec = StandardMethodCodec();
|
||||
window.sendPlatformMessage(
|
||||
ui.PlatformDispatcher.instance.sendPlatformMessage(
|
||||
'flutter/platform_views',
|
||||
codec.encodeMethodCall(MethodCall(
|
||||
'create',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user