flutter/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
Srivats Venkataraman 5fd17bccff
Changes message when web folder is not present (#165084)
This PR addresses: https://github.com/flutter/flutter/issues/164921

The old message for when the web folder wasnt present and a build for
web command was executed the following message was thrown:
```Missing index.html.```

The new message is going to be:

```Run flutter create . --platforms web```

<img width="1087" alt="Screenshot 2025-03-12 at 5 16 15 PM"
src="https://github.com/user-attachments/assets/0676083e-03a5-4bea-afac-8321eb9358f9"
/>
<img width="1440" alt="Screenshot 2025-03-12 at 5 33 15 PM"
src="https://github.com/user-attachments/assets/4eab879c-23d8-4bd0-b08a-a5728009a943"
/>

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-04-28 13:19:00 +00:00

708 lines
25 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 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.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/targets/web.dart';
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/features.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/web/compile.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fakes.dart';
import '../../src/package_config.dart';
import '../../src/test_build_system.dart';
import '../../src/test_flutter_command_runner.dart';
void main() {
late FileSystem fileSystem;
final Platform fakePlatform = FakePlatform(environment: <String, String>{'FLUTTER_ROOT': '/'});
late BufferLogger logger;
late ProcessManager processManager;
setUpAll(() {
Cache.flutterRoot = '';
Cache.disableLocking();
});
setUp(() {
fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml')
..createSync()
..writeAsStringSync('name: foo\n');
writePackageConfigFile(mainLibName: 'foo', directory: fileSystem.currentDirectory);
fileSystem.file(fileSystem.path.join('web', 'index.html')).createSync(recursive: true);
fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
fileSystem.file(fileSystem.path.join('lib', 'a.dart')).createSync(recursive: true);
logger = BufferLogger.test();
processManager = FakeProcessManager.any();
});
testUsingContext(
'Refuses to build for web when missing index.html',
() async {
fileSystem.file(fileSystem.path.join('web', 'index.html')).deleteSync();
final CommandRunner<void> runner = createTestCommandRunner(
BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
),
);
expect(
() => runner.run(<String>['build', 'web', '--no-pub']),
throwsToolExit(
message:
'This project is not configured for the web.\n'
'To configure this project for the web, run flutter create . --platforms web',
),
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
},
);
testUsingContext(
'Refuses to build for web when feature is disabled',
() async {
final CommandRunner<void> runner = createTestCommandRunner(
BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: MemoryFileSystem.test(),
logger: logger,
osUtils: FakeOperatingSystemUtils(),
),
);
expect(
() => runner.run(<String>['build', 'web', '--no-pub']),
throwsToolExit(
message:
'"build web" is not currently supported. To enable, run "flutter config --enable-web".',
),
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(),
ProcessManager: () => processManager,
},
);
testUsingContext(
'Setup for a web build with default output directory',
() async {
final BuildCommand buildCommand = BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--no-web-resources-cdn',
'--dart-define=foo=a',
'--dart2js-optimization=O3',
]);
final Directory buildDir = fileSystem.directory(fileSystem.path.join('build', 'web'));
expect(buildDir.existsSync(), true);
expect(testLogger.statusText, contains('✓ Built ${buildDir.path}'));
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(environment.defines, <String, String>{
'TargetFile': 'lib/main.dart',
'HasWebPlugins': 'true',
'ServiceWorkerStrategy': 'offline-first',
'BuildMode': 'release',
'DartDefines':
'Zm9vPWE=,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
'DartObfuscation': 'false',
'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
});
}),
},
);
testUsingContext(
'Infers target entrypoint correctly from --target',
() async {
// Regression test for https://github.com/flutter/flutter/issues/136830.
final BuildCommand buildCommand = BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--no-web-resources-cdn',
'--target=lib/a.dart',
]);
final Directory buildDir = fileSystem.directory(fileSystem.path.join('build', 'web'));
expect(buildDir.existsSync(), true);
expect(testLogger.statusText, contains('Compiling lib/a.dart for the Web...'));
expect(testLogger.statusText, contains('✓ Built ${buildDir.path}'));
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(environment.defines, <String, String>{
'TargetFile': 'lib/a.dart',
'HasWebPlugins': 'true',
'ServiceWorkerStrategy': 'offline-first',
'BuildMode': 'release',
'DartDefines':
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
'DartObfuscation': 'false',
'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
});
}),
},
);
testUsingContext(
'Infers target entrypoint correctly from positional argument list',
() async {
// Regression test for https://github.com/flutter/flutter/issues/136830.
final BuildCommand buildCommand = BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--no-web-resources-cdn',
'lib/a.dart',
]);
final Directory buildDir = fileSystem.directory(fileSystem.path.join('build', 'web'));
expect(buildDir.existsSync(), true);
expect(testLogger.statusText, contains('Compiling lib/a.dart for the Web...'));
expect(testLogger.statusText, contains('✓ Built ${buildDir.path}'));
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(environment.defines, <String, String>{
'TargetFile': 'lib/a.dart',
'HasWebPlugins': 'true',
'ServiceWorkerStrategy': 'offline-first',
'BuildMode': 'release',
'DartDefines':
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
'DartObfuscation': 'false',
'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
});
}),
},
);
testUsingContext(
'Does not allow -O0 optimization level',
() async {
final BuildCommand buildCommand = BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: BufferLogger.test(),
osUtils: FakeOperatingSystemUtils(),
);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await expectLater(
() => runner.run(<String>[
'build',
'web',
'--no-pub',
'--no-web-resources-cdn',
'--dart-define=foo=a',
'--dart2js-optimization=O0',
]),
throwsUsageException(
message: '"O0" is not an allowed value for option "--dart2js-optimization"',
),
);
final Directory buildDir = fileSystem.directory(fileSystem.path.join('build', 'web'));
expect(buildDir.existsSync(), isFalse);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(environment.defines, <String, String>{
'TargetFile': 'lib/main.dart',
'HasWebPlugins': 'true',
'cspMode': 'false',
'SourceMaps': 'false',
'NativeNullAssertions': 'true',
'ServiceWorkerStrategy': 'offline-first',
'Dart2jsDumpInfo': 'false',
'Dart2jsNoFrequencyBasedMinification': 'false',
'Dart2jsOptimization': 'O3',
'BuildMode': 'release',
'DartDefines':
'Zm9vPWE=,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
'DartObfuscation': 'false',
'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true',
});
}),
},
);
testUsingContext(
'Setup for a web build with a user specified output directory',
() async {
final BuildCommand buildCommand = BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
const String newBuildDir = 'new_dir';
final Directory buildDir = fileSystem.directory(fileSystem.path.join(newBuildDir));
expect(buildDir.existsSync(), false);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--no-web-resources-cdn',
'--output=$newBuildDir',
]);
expect(buildDir.existsSync(), true);
expect(testLogger.statusText, contains('✓ Built $newBuildDir'));
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(environment.defines, <String, String>{
'TargetFile': 'lib/main.dart',
'HasWebPlugins': 'true',
'ServiceWorkerStrategy': 'offline-first',
'BuildMode': 'release',
'DartDefines':
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
'DartObfuscation': 'false',
'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
});
}),
},
);
testUsingContext(
'hidden if feature flag is not enabled',
() async {
expect(
BuildWebCommand(
fileSystem: fileSystem,
logger: BufferLogger.test(),
verboseHelp: false,
).hidden,
true,
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(),
ProcessManager: () => processManager,
},
);
testUsingContext(
'not hidden if feature flag is enabled',
() async {
expect(
BuildWebCommand(
fileSystem: fileSystem,
logger: BufferLogger.test(),
verboseHelp: false,
).hidden,
false,
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
},
);
testUsingContext(
'Defaults to web renderer canvaskit mode when no option is specified',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>['build', 'web', '--no-pub']);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(target, isA<WebServiceWorker>());
final List<WebCompilerConfig> configs = (target as WebServiceWorker).compileConfigs;
expect(configs.length, 1);
expect(configs.first.renderer, WebRendererMode.canvaskit);
}),
},
);
testUsingContext(
'Defaults to web renderer skwasm mode for wasm when no option is specified',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>['build', 'web', '--no-pub', '--wasm']);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem:
() => TestBuildSystem.all(BuildResult(success: true), (
Target target,
Environment environment,
) {
expect(target, isA<WebServiceWorker>());
final List<WebCompilerConfig> configs = (target as WebServiceWorker).compileConfigs;
expect(configs.length, 2);
expect(configs[0].renderer, WebRendererMode.skwasm);
expect(configs[0].compileTarget, CompileTarget.wasm);
expect(configs[1].renderer, WebRendererMode.canvaskit);
expect(configs[1].compileTarget, CompileTarget.js);
}),
},
);
testUsingContext(
'Web build supports build-name and build-number',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--build-name=1.2.3',
'--build-number=42',
]);
final BuildInfo buildInfo = await buildCommand.webCommand.getBuildInfo(
forcedBuildMode: BuildMode.debug,
);
expect(buildInfo.buildNumber, '42');
expect(buildInfo.buildName, '1.2.3');
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
},
);
testUsingContext(
'Does not override custom CanvasKit URL',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>[
'build',
'web',
'--no-pub',
'--web-resources-cdn',
'--dart-define=FLUTTER_WEB_CANVASKIT_URL=abcdefg',
]);
final BuildInfo buildInfo = await buildCommand.webCommand.getBuildInfo(
forcedBuildMode: BuildMode.debug,
);
expect(buildInfo.dartDefines, contains('FLUTTER_WEB_CANVASKIT_URL=abcdefg'));
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
},
);
testUsingContext(
'Rejects --base-href value that does not start with /',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
await expectLater(
runner.run(<String>[
'build',
'web',
'--no-pub',
'--base-href=i_dont_start_with_a_forward_slash',
]),
throwsToolExit(
message:
'Received a --base-href value of "i_dont_start_with_a_forward_slash"\n'
'--base-href should start and end with /',
),
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
},
);
testUsingContext(
'flutter build web option visibility',
() async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
createTestCommandRunner(buildCommand);
final BuildWebCommand command = buildCommand.subcommands.values.single as BuildWebCommand;
void expectVisible(String option) {
expect(command.argParser.options.keys, contains(option));
expect(command.argParser.options[option]!.hide, isFalse);
expect(command.usage, contains(option));
}
expectVisible('pwa-strategy');
expectVisible('web-resources-cdn');
expectVisible('optimization-level');
expectVisible('source-maps');
expectVisible('csp');
expectVisible('dart2js-optimization');
expectVisible('dump-info');
expectVisible('no-frequency-based-minification');
expectVisible('wasm');
expectVisible('strip-wasm');
expectVisible('base-href');
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
},
);
testUsingContext(
'Refuses to build for web when folder is missing',
() async {
fileSystem.file(fileSystem.path.join('web')).deleteSync(recursive: true);
final CommandRunner<void> runner = createTestCommandRunner(
BuildCommand(
androidSdk: FakeAndroidSdk(),
buildSystem: TestBuildSystem.all(BuildResult(success: true)),
fileSystem: fileSystem,
logger: logger,
osUtils: FakeOperatingSystemUtils(),
),
);
expect(
() => runner.run(<String>['build', 'web', '--no-pub']),
throwsToolExit(
message:
'This project is not configured for the web.\n'
'To configure this project for the web, run flutter create . --platforms web',
),
);
},
overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
},
);
}
void setupFileSystemForEndToEndTest(FileSystem fileSystem) {
final List<String> dependencies = <String>[
fileSystem.path.join(
'packages',
'flutter_tools',
'lib',
'src',
'build_system',
'targets',
'web.dart',
),
fileSystem.path.join('bin', 'cache', 'flutter_web_sdk'),
fileSystem.path.join('bin', 'cache', 'dart-sdk', 'bin', 'dart'),
fileSystem.path.join('bin', 'cache', 'dart-sdk', 'bin', 'dartaotruntime'),
fileSystem.path.join('bin', 'cache', 'dart-sdk '),
];
for (final String dependency in dependencies) {
fileSystem.file(dependency).createSync(recursive: true);
}
// Project files.
writePackageConfigFile(
directory: fileSystem.currentDirectory,
mainLibName: 'foo',
packages: <String, String>{'fizz': 'bar'},
);
fileSystem.file('pubspec.yaml').writeAsStringSync('''
name: foo
dependencies:
flutter:
sdk: flutter
fizz:
path:
bar/
''');
fileSystem.file(fileSystem.path.join('bar', 'pubspec.yaml'))
..createSync(recursive: true)
..writeAsStringSync('''
name: bar
flutter:
plugin:
platforms:
web:
pluginClass: UrlLauncherPlugin
fileName: url_launcher_web.dart
''');
fileSystem.file(fileSystem.path.join('bar', 'lib', 'url_launcher_web.dart'))
..createSync(recursive: true)
..writeAsStringSync('''
class UrlLauncherPlugin {}
''');
fileSystem.file(fileSystem.path.join('lib', 'main.dart')).writeAsStringSync('void main() { }');
}
class TestWebBuildCommand extends FlutterCommand {
TestWebBuildCommand({required FileSystem fileSystem, bool verboseHelp = false})
: webCommand = BuildWebCommand(
fileSystem: fileSystem,
logger: BufferLogger.test(),
verboseHelp: verboseHelp,
) {
addSubcommand(webCommand);
}
final BuildWebCommand webCommand;
@override
final String name = 'build';
@override
final String description = 'Build a test executable app.';
@override
Future<FlutterCommandResult> runCommand() async => FlutterCommandResult.fail();
@override
bool get shouldRunPub => false;
}