mirror of
https://github.com/flutter/flutter
synced 2024-08-27 20:10:11 +00:00
110 lines
3.8 KiB
Dart
110 lines
3.8 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:io' as io;
|
|
|
|
import 'package:flutter_devicelab/framework/browser.dart';
|
|
import 'package:shelf/shelf.dart';
|
|
import 'package:shelf/shelf_io.dart' as shelf_io;
|
|
import 'package:shelf_static/shelf_static.dart';
|
|
|
|
/// Runs Chrome, opens the given `appUrl`, and returns the result reported by the
|
|
/// app.
|
|
///
|
|
/// The app is served from the `appDirectory`. Typically, the app is built
|
|
/// using `flutter build web` and served from `build/web`.
|
|
///
|
|
/// The launched app is expected to report the result by sending an HTTP POST
|
|
/// request to "/test-result" containing result data as plain text body of the
|
|
/// request. This function has no opinion about what that string contains.
|
|
Future<String> evalTestAppInChrome({
|
|
required String appUrl,
|
|
required String appDirectory,
|
|
int serverPort = 8080,
|
|
int browserDebugPort = 8081,
|
|
}) async {
|
|
io.HttpServer? server;
|
|
Chrome? chrome;
|
|
try {
|
|
final Completer<String> resultCompleter = Completer<String>();
|
|
server = await io.HttpServer.bind('localhost', serverPort);
|
|
final Cascade cascade = Cascade()
|
|
.add((Request request) async {
|
|
if (request.requestedUri.path.endsWith('/test-result')) {
|
|
resultCompleter.complete(await request.readAsString());
|
|
return Response.ok('Test results received');
|
|
}
|
|
return Response.notFound('');
|
|
})
|
|
.add(createStaticHandler(appDirectory));
|
|
shelf_io.serveRequests(server, cascade.handler);
|
|
final io.Directory userDataDirectory = io.Directory.systemTemp.createTempSync('flutter_chrome_user_data.');
|
|
chrome = await Chrome.launch(ChromeOptions(
|
|
headless: true,
|
|
debugPort: browserDebugPort,
|
|
url: appUrl,
|
|
userDataDirectory: userDataDirectory.path,
|
|
windowHeight: 500,
|
|
windowWidth: 500,
|
|
), onError: resultCompleter.completeError);
|
|
return await resultCompleter.future;
|
|
} finally {
|
|
chrome?.stop();
|
|
await server?.close();
|
|
}
|
|
}
|
|
|
|
typedef ServerRequestListener = void Function(Request);
|
|
|
|
class AppServer {
|
|
AppServer._(this._server, this.chrome, this.onChromeError);
|
|
|
|
static Future<AppServer> start({
|
|
required String appUrl,
|
|
required String appDirectory,
|
|
required String cacheControl,
|
|
int serverPort = 8080,
|
|
int browserDebugPort = 8081,
|
|
bool headless = true,
|
|
List<Handler>? additionalRequestHandlers,
|
|
}) async {
|
|
io.HttpServer server;
|
|
Chrome chrome;
|
|
server = await io.HttpServer.bind('localhost', serverPort);
|
|
final Handler staticHandler = createStaticHandler(appDirectory, defaultDocument: 'index.html');
|
|
Cascade cascade = Cascade();
|
|
if (additionalRequestHandlers != null) {
|
|
for (final Handler handler in additionalRequestHandlers) {
|
|
cascade = cascade.add(handler);
|
|
}
|
|
}
|
|
cascade = cascade.add((Request request) async {
|
|
final Response response = await staticHandler(request);
|
|
return response.change(headers: <String, Object>{
|
|
'cache-control': cacheControl,
|
|
});
|
|
});
|
|
shelf_io.serveRequests(server, cascade.handler);
|
|
final io.Directory userDataDirectory = io.Directory.systemTemp.createTempSync('flutter_chrome_user_data.');
|
|
final Completer<String> chromeErrorCompleter = Completer<String>();
|
|
chrome = await Chrome.launch(ChromeOptions(
|
|
headless: headless,
|
|
debugPort: browserDebugPort,
|
|
url: appUrl,
|
|
userDataDirectory: userDataDirectory.path,
|
|
), onError: chromeErrorCompleter.complete);
|
|
return AppServer._(server, chrome, chromeErrorCompleter.future);
|
|
}
|
|
|
|
final Future<String> onChromeError;
|
|
final io.HttpServer _server;
|
|
final Chrome chrome;
|
|
|
|
Future<void> stop() async {
|
|
chrome.stop();
|
|
await _server.close();
|
|
}
|
|
}
|