Skip to content

Commit b1d2636

Browse files
authored
[ Widget Preview ] Add --web-server support (flutter#172978)
This allows for the widget preview environment to be launched using the `web-server` device instead of just opening Chrome.
1 parent acfe731 commit b1d2636

2 files changed

Lines changed: 47 additions & 10 deletions

File tree

packages/flutter_tools/lib/src/commands/widget_preview.dart

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import '../project.dart';
2626
import '../resident_runner.dart';
2727
import '../runner/flutter_command.dart';
2828
import '../runner/flutter_command_runner.dart';
29+
import '../web/web_device.dart';
2930
import '../widget_preview/analytics.dart';
3031
import '../widget_preview/dependency_graph.dart';
3132
import '../widget_preview/dtd_services.dart';
@@ -137,6 +138,12 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
137138
}
138139
addPubOptions();
139140
argParser
141+
..addFlag(
142+
kWebServer,
143+
help:
144+
'Serve the widget preview environment using the web-server device instead of the '
145+
'browser.',
146+
)
140147
..addFlag(
141148
kLaunchPreviewer,
142149
defaultsTo: true,
@@ -150,12 +157,14 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
150157
help:
151158
'Generated the widget preview environment scaffolding at a given location '
152159
'for testing purposes.',
160+
hide: !verbose,
153161
);
154162
}
155163

156164
static const kWidgetPreviewScaffoldName = 'widget_preview_scaffold';
157165
static const kLaunchPreviewer = 'launch-previewer';
158166
static const kHeadless = 'headless';
167+
static const kWebServer = 'web-server';
159168
static const kWidgetPreviewScaffoldOutputDir = 'scaffold-output-dir';
160169

161170
/// Environment variable used to pass the DTD URI to the widget preview scaffold.
@@ -358,16 +367,28 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
358367

359368
Future<int> runPreviewEnvironment({required FlutterProject widgetPreviewScaffoldProject}) async {
360369
try {
361-
// Since the only target supported by the widget preview scaffold is the web
362-
// device, only a single web device should be returned.
363-
final List<Device> devices = await deviceManager!.getDevices(
364-
filter: DeviceDiscoveryFilter(
365-
supportFilter: DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProject(
366-
flutterProject: widgetPreviewScaffoldProject,
370+
final List<Device> devices;
371+
if (boolArg(kWebServer)) {
372+
try {
373+
// The web-server device is hidden by default, make it visible before trying to look it up.
374+
WebServerDevice.showWebServerDevice = true;
375+
devices = await deviceManager!.getDevicesById(WebServerDevice.kWebServerDeviceId);
376+
} finally {
377+
// Reset the flag to false to avoid affecting other commands.
378+
WebServerDevice.showWebServerDevice = false;
379+
}
380+
} else {
381+
// Since the only target supported by the widget preview scaffold is the web
382+
// device, only a single web device should be returned.
383+
devices = await deviceManager!.getDevices(
384+
filter: DeviceDiscoveryFilter(
385+
supportFilter: DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProject(
386+
flutterProject: widgetPreviewScaffoldProject,
387+
),
388+
deviceConnectionInterface: DeviceConnectionInterface.attached,
367389
),
368-
deviceConnectionInterface: DeviceConnectionInterface.attached,
369-
),
370-
);
390+
);
391+
}
371392
assert(devices.length == 1);
372393
final Device device = devices.first;
373394

packages/flutter_tools/test/integration.shard/widget_preview_test.dart

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ const firstLaunchMessagesWeb = <String>[
2626
'Done loading previews.',
2727
];
2828

29+
const firstLaunchMessagesWebServer = <String>[
30+
'Creating widget preview scaffolding at:',
31+
'Launching the Widget Preview Scaffold...',
32+
'main.dart is being served at',
33+
'Done loading previews.',
34+
];
35+
2936
const subsequentLaunchMessagesWeb = <String>[
3037
'Launching the Widget Preview Scaffold...',
3138
'Done loading previews.',
@@ -53,7 +60,11 @@ void main() {
5360
tryToDelete(tempDir);
5461
});
5562

56-
Future<void> runWidgetPreview({required List<String> expectedMessages, Uri? dtdUri}) async {
63+
Future<void> runWidgetPreview({
64+
required List<String> expectedMessages,
65+
Uri? dtdUri,
66+
bool useWebServer = false,
67+
}) async {
5768
expect(expectedMessages, isNotEmpty);
5869
var i = 0;
5970
process = await processManager.start(<String>[
@@ -62,6 +73,7 @@ void main() {
6273
'start',
6374
'--verbose',
6475
'--${WidgetPreviewStartCommand.kHeadless}',
76+
if (useWebServer) '--${WidgetPreviewStartCommand.kWebServer}',
6577
if (dtdUri != null) '--${FlutterGlobalOptions.kDtdUrl}=$dtdUri',
6678
], workingDirectory: tempDir.path);
6779

@@ -101,6 +113,10 @@ void main() {
101113
await runWidgetPreview(expectedMessages: firstLaunchMessagesWeb);
102114
});
103115

116+
testWithoutContext('--web-server starts a web server instance', () async {
117+
await runWidgetPreview(expectedMessages: firstLaunchMessagesWebServer, useWebServer: true);
118+
});
119+
104120
testWithoutContext('does not recreate project on subsequent runs', () async {
105121
// The first run of 'flutter widget-preview start' should generate a new preview scaffold
106122
await runWidgetPreview(expectedMessages: firstLaunchMessagesWeb);

0 commit comments

Comments
 (0)