diff --git a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart index 4e7ccf343c3..3c578b3da25 100644 --- a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart +++ b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart @@ -48,6 +48,15 @@ typedef DwdsLauncher = Future Function({ ExpressionCompiler expressionCompiler, }); +// A minimal index for projects that do not yet support web. +const String _kDefaultIndex = ''' + + + + + +'''; + /// An expression compiler connecting to FrontendServer /// /// This is only used in development mode @@ -277,8 +286,11 @@ class WebAssetServer implements AssetReader { headers[HttpHeaders.contentTypeHeader] = 'text/html'; headers[HttpHeaders.contentLengthHeader] = indexFile.lengthSync().toString(); return shelf.Response.ok(indexFile.openRead(), headers: headers); + } else { + headers[HttpHeaders.contentTypeHeader] = 'text/html'; + headers[HttpHeaders.contentLengthHeader] = _kDefaultIndex.length.toString(); + return shelf.Response.ok(_kDefaultIndex, headers: headers); } - return shelf.Response.notFound(''); } // Track etag headers for better caching of resources. diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart index 1805ef21616..b851c311fb2 100644 --- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart @@ -368,9 +368,8 @@ class _ResidentWebRunner extends ResidentWebRunner { applicationBinary: null, ); if (package == null) { - globals.printError('This application is not configured to build on the web.'); - globals.printError('To add web support to a project, run `flutter create .`.'); - return 1; + globals.printStatus('This application is not configured to build on the web.'); + globals.printStatus('To add web support to a project, run `flutter create .`.'); } if (!globals.fs.isFileSync(mainPath)) { String message = 'Tried to run $mainPath, but that file does not exist.'; @@ -569,6 +568,7 @@ class _ResidentWebRunner extends ResidentWebRunner { if (importedEntrypoint == null) { final String parent = globals.fs.file(mainUri).parent.path; flutterDevices.first.generator.addFileSystemRoot(parent); + flutterDevices.first.generator.addFileSystemRoot(globals.fs.directory('test').absolute.path); importedEntrypoint = Uri( scheme: 'org-dartlang-app', path: '/' + mainUri.pathSegments.last, diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart index 2bc342c3bcb..30708dd6f12 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart @@ -13,11 +13,9 @@ import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; import 'package:flutter_tools/src/commands/build_web.dart'; import 'package:flutter_tools/src/dart/pub.dart'; -import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/project.dart'; -import 'package:flutter_tools/src/build_runner/resident_web_runner.dart'; import 'package:flutter_tools/src/web/compile.dart'; import 'package:mockito/mockito.dart'; @@ -69,26 +67,6 @@ void main() { ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('Refuses to build using runner when missing index.html', () async { - fileSystem.file(fileSystem.path.join('web', 'index.html')).deleteSync(); - - final ResidentWebRunner runner = DwdsWebRunnerFactory().createWebRunner( - null, - flutterProject: FlutterProject.current(), - ipv6: false, - debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), - stayResident: true, - urlTunneller: null, - ) as ResidentWebRunner; - expect(await runner.run(), 1); - }, overrides: { - Platform: () => fakePlatform, - FileSystem: () => fileSystem, - FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - Pub: () => MockPub(), - ProcessManager: () => FakeProcessManager.any(), - }); - testUsingContext('Refuses to build a debug build for web', () async { final CommandRunner runner = createTestCommandRunner(BuildCommand()); diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart index 6eee507ddfd..cd7d4e77b38 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart @@ -227,18 +227,11 @@ void main() { expect(residentWebRunner.supportsServiceProtocol, true); })); - test('Exits on run if application does not support the web', () => testbed.run(() async { - fakeVmServiceHost = FakeVmServiceHost(requests: []); - globals.fs.file('pubspec.yaml').createSync(); - - expect(await residentWebRunner.run(), 1); - expect(testLogger.errorText, contains('This application is not configured to build on the web')); - })); - test('Exits on run if target file does not exist', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: []); globals.fs.file('pubspec.yaml').createSync(); - globals.fs.file(globals.fs.path.join('web', 'index.html')).createSync(recursive: true); + globals.fs.file(globals.fs.path.join('web', 'index.html')) + .createSync(recursive: true); expect(await residentWebRunner.run(), 1); final String absoluteMain = globals.fs.path.absolute(globals.fs.path.join('lib', 'main.dart')); @@ -277,6 +270,25 @@ void main() { )), })); + test('Can successfully run without an index.html including status warning', () => testbed.run(() async { + fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList()); + _setupMocks(); + globals.fs.file(globals.fs.path.join('web', 'index.html')) + .deleteSync(); + residentWebRunner = DwdsWebRunnerFactory().createWebRunner( + mockFlutterDevice, + flutterProject: FlutterProject.current(), + debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), + ipv6: true, + stayResident: false, + urlTunneller: null, + ) as ResidentWebRunner; + + expect(await residentWebRunner.run(), 0); + expect(testLogger.statusText, + contains('This application is not configured to build on the web')); + })); + test('Can successfully run and disconnect with --no-resident', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList()); _setupMocks(); diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart index 5b6ceb2beda..63ccf34d464 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart @@ -157,6 +157,15 @@ void main() { expect(response.statusCode, HttpStatus.notFound); })); + test('serves default index.html', () => testbed.run(() async { + final Response response = await webAssetServer + .handleRequest(Request('GET', Uri.parse('http://foobar/'))); + + expect(response.statusCode, HttpStatus.ok); + expect((await response.read().toList()).first, + containsAllInOrder(utf8.encode(''))); + })); + test('handles web server paths without .lib extension', () => testbed.run(() async { final File source = globals.fs.file('source') ..writeAsStringSync('main() {}');