blob: ac54d6c0186ce30cb4aa044dc5d032f3dc80ca11 [file] [log] [blame]
// 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 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/template.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/depfile.dart';
import 'package:flutter_tools/src/build_system/targets/web.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/isolated/mustache_template.dart';
import 'package:flutter_tools/src/web/file_generators/flutter_js.dart' as flutter_js;
import 'package:flutter_tools/src/web/file_generators/flutter_service_worker_js.dart';
import '../../../src/common.dart';
import '../../../src/fake_process_manager.dart';
import '../../../src/testbed.dart';
const List<String> kDart2jsLinuxArgs = <String>[
'bin/cache/dart-sdk/bin/dart',
'--disable-dart-dev',
'bin/cache/dart-sdk/bin/snapshots/dart2js.dart.snapshot',
'--libraries-spec=bin/cache/flutter_web_sdk/libraries.json',
];
void main() {
late Testbed testbed;
late Environment environment;
late FakeProcessManager processManager;
final Platform linux = FakePlatform(
environment: <String, String>{},
);
final Platform windows = FakePlatform(
operatingSystem: 'windows',
environment: <String, String>{},
);
late DepfileService depfileService;
setUp(() {
testbed = Testbed(setup: () {
globals.fs.file('.packages')
..createSync(recursive: true)
..writeAsStringSync('foo:foo/lib/\n');
globals.fs.currentDirectory.childDirectory('bar').createSync();
processManager = FakeProcessManager.empty();
environment = Environment.test(
globals.fs.currentDirectory,
projectDir: globals.fs.currentDirectory.childDirectory('foo'),
outputDir: globals.fs.currentDirectory.childDirectory('bar'),
defines: <String, String>{
kTargetFile: globals.fs.path.join('foo', 'lib', 'main.dart'),
},
artifacts: Artifacts.test(),
processManager: FakeProcessManager.any(),
logger: globals.logger,
fileSystem: globals.fs,
);
depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
environment.buildDir.createSync(recursive: true);
}, overrides: <Type, Generator>{
Platform: () => linux,
});
});
test('WebEntrypointTarget generates an entrypoint with plugins and init platform', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
environment.defines[kHasWebPlugins] = 'true';
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Plugins
expect(generated, contains("import 'web_plugin_registrant.dart' as pluginRegistrant;"));
expect(generated, contains('pluginRegistrant.registerPlugins();'));
// Import.
expect(generated, contains("import 'package:foo/main.dart' as entrypoint;"));
// Main
expect(generated, contains('ui.webOnlyWarmupEngine('));
expect(generated, contains('entrypoint.main as _'));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('version.json is created after release build', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html')
.createSync(recursive: true);
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('version.json'), exists);
}));
test('override version values', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kBuildName] = '2.0.0';
environment.defines[kBuildNumber] = '22';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html').createSync(recursive: true);
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
final String versionFile = environment.outputDir
.childFile('version.json')
.readAsStringSync();
expect(versionFile, contains('"version":"2.0.0"'));
expect(versionFile, contains('"build_number":"22"'));
}));
test('Base href is created in index.html with given base-href after release build', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kBaseHref] = '/basehreftest/';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html').createSync(recursive: true);
webResources.childFile('index.html').writeAsStringSync('''
<!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html>
''');
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
}));
test('null base href does not override existing base href in index.html', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html').createSync(recursive: true);
webResources.childFile('index.html').writeAsStringSync('''
<!DOCTYPE html><html><head><base href='/basehreftest/'></head></html>
''');
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
}));
test('WebReleaseBundle copies dart2js output and resource files to output directory', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html')
..createSync(recursive: true)
..writeAsStringSync('''
<html>
<script src="main.dart.js" type="application/javascript"></script>
<script>
navigator.serviceWorker.register('flutter_service_worker.js');
</script>
</html>
''');
webResources.childFile('foo.txt')
.writeAsStringSync('A');
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('foo.txt')
.readAsStringSync(), 'A');
expect(environment.outputDir.childFile('main.dart.js')
.existsSync(), true);
expect(environment.outputDir.childDirectory('assets')
.childFile('AssetManifest.json').existsSync(), true);
// Update to arbitrary resource file triggers rebuild.
webResources.childFile('foo.txt').writeAsStringSync('B');
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('foo.txt')
.readAsStringSync(), 'B');
// Appends number to requests for service worker only
expect(environment.outputDir.childFile('index.html').readAsStringSync(), allOf(
contains('<script src="main.dart.js" type="application/javascript">'),
contains('flutter_service_worker.js?v='),
));
}));
test('WebEntrypointTarget generates an entrypoint for a file outside of main', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('other', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Import.
expect(generated, contains("import 'file:///other/lib/main.dart' as entrypoint;"));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates a plugin registrant for a file outside of main', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('other', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
environment.defines[kHasWebPlugins] = 'true';
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Import.
expect(generated, contains("import 'file:///other/lib/main.dart' as entrypoint;"));
expect(generated, contains("import 'web_plugin_registrant.dart' as pluginRegistrant;"));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates an entrypoint with plugins and init platform on windows', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
environment.defines[kHasWebPlugins] = 'true';
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Plugins
expect(generated, contains("import 'web_plugin_registrant.dart' as pluginRegistrant;"));
expect(generated, contains('pluginRegistrant.registerPlugins();'));
// Import.
expect(generated, contains("import 'package:foo/main.dart' as entrypoint;"));
// Main
expect(generated, contains('ui.webOnlyWarmupEngine('));
expect(generated, contains('entrypoint.main as _'));
}, overrides: <Type, Generator>{
Platform: () => windows,
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates an entrypoint without plugins and init platform', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
environment.defines[kHasWebPlugins] = 'false';
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Plugins (the generated file is a noop)
expect(generated, contains("import 'web_plugin_registrant.dart' as pluginRegistrant;"));
expect(generated, contains('pluginRegistrant.registerPlugins();'));
// Import.
expect(generated, contains("import 'package:foo/main.dart' as entrypoint;"));
// Main
expect(generated, contains('ui.webOnlyWarmupEngine('));
expect(generated, contains('entrypoint.main as _'));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates an entrypoint with a language version', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('// @dart=2.8\nvoid main() {}');
environment.defines[kTargetFile] = mainFile.path;
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Language version
expect(generated, contains('// @dart=2.8'));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates an entrypoint with a language version from a package config', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
globals.fs.file(globals.fs.path.join('pubspec.yaml'))
.writeAsStringSync('name: foo\n');
environment.defines[kTargetFile] = mainFile.path;
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Language version
expect(generated, contains('// @dart=2.7'));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('WebEntrypointTarget generates an entrypoint without plugins and without init platform', () => testbed.run(() async {
final File mainFile = globals.fs.file(globals.fs.path.join('foo', 'lib', 'main.dart'))
..createSync(recursive: true)
..writeAsStringSync('void main() {}');
environment.defines[kTargetFile] = mainFile.path;
environment.defines[kHasWebPlugins] = 'false';
await const WebEntrypointTarget().build(environment);
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Plugins
expect(generated, contains("import 'web_plugin_registrant.dart' as pluginRegistrant;"));
expect(generated, contains('pluginRegistrant.registerPlugins();'));
// Import.
expect(generated, contains("import 'package:foo/main.dart' as entrypoint;"));
// Main
expect(generated, contains('ui.webOnlyWarmupEngine('));
expect(generated, contains('entrypoint.main as _'));
}, overrides: <Type, Generator>{
TemplateRenderer: () => const MustacheTemplateRenderer(),
}));
test('Dart2JSTarget calls dart2js with expected args with csp', () => testbed.run(() async {
environment.defines[kBuildMode] = 'profile';
environment.defines[kCspMode] = 'true';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'--no-source-maps',
'-O4',
'--no-minify',
'--csp',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with expected args with enabled experiment', () => testbed.run(() async {
environment.defines[kBuildMode] = 'profile';
environment.defines[kExtraFrontEndOptions] = '--enable-experiment=non-nullable';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'--enable-experiment=non-nullable',
'-Ddart.vm.profile=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'--enable-experiment=non-nullable',
'-Ddart.vm.profile=true',
'--no-source-maps',
'-O4',
'--no-minify',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with expected args in profile mode', () => testbed.run(() async {
environment.defines[kBuildMode] = 'profile';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'--no-source-maps',
'-O4',
'--no-minify',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with expected args in release mode', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'--no-source-maps',
'-O4',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with expected args in release mode with native null assertions', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kNativeNullAssertions] = 'true';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'--native-null-assertions',
'-Ddart.vm.product=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'--native-null-assertions',
'-Ddart.vm.product=true',
'--no-source-maps',
'-O4',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with expected args in release with dart2js optimization override', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kDart2jsOptimization] = 'O3';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'--no-source-maps',
'-O3',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget produces expected depfile', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
], onRun: () {
environment.buildDir.childFile('app.dill.deps')
.writeAsStringSync('file:///a.dart');
},
));
await const Dart2JSTarget().build(environment);
expect(environment.buildDir.childFile('dart2js.d'), exists);
final Depfile depfile = depfileService.parse(environment.buildDir.childFile('dart2js.d'));
expect(depfile.inputs.single.path, globals.fs.path.absolute('a.dart'));
expect(depfile.outputs.single.path,
environment.buildDir.childFile('main.dart.js').absolute.path);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with Dart defines in release mode', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kDartDefines] = encodeDartDefines(<String>['FOO=bar', 'BAZ=qux']);
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'-DFOO=bar',
'-DBAZ=qux',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'-DFOO=bar',
'-DBAZ=qux',
'--no-source-maps',
'-O4',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget can enable source maps', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
environment.defines[kSourceMapsEnabled] = 'true';
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.product=true',
'-O4',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2JSTarget calls dart2js with Dart defines in profile mode', () => testbed.run(() async {
environment.defines[kBuildMode] = 'profile';
environment.defines[kDartDefines] = encodeDartDefines(<String>['FOO=bar', 'BAZ=qux']);
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'-DFOO=bar',
'-DBAZ=qux',
'--no-source-maps',
'-o',
environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json',
'--cfe-only',
environment.buildDir.childFile('main.dart').absolute.path,
]
));
processManager.addCommand(FakeCommand(
command: <String>[
...kDart2jsLinuxArgs,
'-Ddart.vm.profile=true',
'-DFOO=bar',
'-DBAZ=qux',
'--no-source-maps',
'-O4',
'--no-minify',
'-o',
environment.buildDir.childFile('main.dart.js').absolute.path,
environment.buildDir.childFile('app.dill').absolute.path,
]
));
await const Dart2JSTarget().build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Generated service worker is empty with none-strategy', () {
final String result = generateServiceWorker(<String, String>{'/foo': 'abcd'}, <String>[], serviceWorkerStrategy: ServiceWorkerStrategy.none);
expect(result, '');
});
test('Generated service worker correctly inlines file hashes', () {
final String result = generateServiceWorker(<String, String>{'/foo': 'abcd'}, <String>[], serviceWorkerStrategy: ServiceWorkerStrategy.offlineFirst);
expect(result, contains('{\n "/foo": "abcd"\n};'));
});
test('Generated service worker includes core files', () {
final String result = generateServiceWorker(<String, String>{'/foo': 'abcd'}, <String>['foo', 'bar'], serviceWorkerStrategy: ServiceWorkerStrategy.offlineFirst);
expect(result, contains('"foo",\n"bar"'));
});
test('WebServiceWorker generates a service_worker for a web resource folder', () => testbed.run(() async {
environment.outputDir.childDirectory('a').childFile('a.txt')
..createSync(recursive: true)
..writeAsStringSync('A');
await WebServiceWorker(globals.fs, globals.cache).build(environment);
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
// Contains file hash.
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
contains('"a/a.txt": "7fc56270e7a70fa81a5935b72eacbe29"'));
expect(environment.buildDir.childFile('service_worker.d'), exists);
// Depends on resource file.
expect(environment.buildDir.childFile('service_worker.d').readAsStringSync(),
contains('a/a.txt'));
// Does NOT contain NOTICES
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
isNot(contains('NOTICES')));
}));
test('WebServiceWorker contains baseUrl cache', () => testbed.run(() async {
environment.outputDir
.childFile('index.html')
.createSync(recursive: true);
await WebServiceWorker(globals.fs, globals.cache).build(environment);
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
// Contains file hash for both `/` and index.html.
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
contains('"/": "d41d8cd98f00b204e9800998ecf8427e"'));
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
contains('"index.html": "d41d8cd98f00b204e9800998ecf8427e"'));
expect(environment.buildDir.childFile('service_worker.d'), exists);
}));
test('WebServiceWorker does not cache source maps', () => testbed.run(() async {
environment.outputDir
.childFile('main.dart.js')
.createSync(recursive: true);
environment.outputDir
.childFile('main.dart.js.map')
.createSync(recursive: true);
await WebServiceWorker(globals.fs, globals.cache).build(environment);
// No caching of source maps.
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
isNot(contains('"main.dart.js.map"')));
// Expected twice, once for RESOURCES and once for CORE.
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
contains('"main.dart.js"'));
}));
test('flutter.js is not dynamically generated', () => testbed.run(() async {
globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/foo')
..createSync(recursive: true)
..writeAsStringSync('OL');
await WebBuiltInAssets(globals.fs, globals.cache).build(environment);
// No caching of source maps.
expect(environment.outputDir.childFile('flutter.js').readAsStringSync(),
equals(flutter_js.generateFlutterJsFile()));
}));
}