@@ -15,8 +15,13 @@ import 'dart:io';
1515
1616import 'package:collection/collection.dart' ;
1717import 'package:dwds/data/debug_info.dart' ;
18+ import 'package:dwds/data/extension_request.dart' ;
19+ import 'package:dwds/src/servers/extension_backend.dart' ;
20+ import 'package:dwds/src/utilities/server.dart' ;
1821import 'package:path/path.dart' as p;
19- import 'package:puppeteer/puppeteer.dart' ;
22+ import 'package:puppeteer/puppeteer.dart' hide Response;
23+ import 'package:shelf/shelf.dart' ;
24+ import 'package:shelf_static/shelf_static.dart' ;
2025import 'package:test/test.dart' ;
2126import 'package:test_common/test_sdk_configuration.dart' ;
2227
@@ -777,25 +782,32 @@ void main() async {
777782 }
778783 });
779784
780- group ('connected to a fake app' , () {
781- final fakeAppPath = webCompatiblePath (
785+ group ('Backwards-compatible with older DWDS versions' , () {
786+ final port = 8080 ;
787+ final hostname = 'localhost' ;
788+ final fakeAppUrl = 'http://$hostname :$port /index.html' ;
789+ final fakeAppDir = webCompatiblePath (
782790 p.split (
783791 absolutePath (
784792 pathFromDwds: p.join (
785793 'test' ,
786794 'puppeteer' ,
787795 'fake_app' ,
788- 'index.html' ,
789796 ),
790797 ),
791798 ),
792799 );
793- final fakeAppUrl = 'file://$fakeAppPath ' ;
794800 late Browser browser;
801+ late HttpServer server;
795802 Worker ? worker;
796803 Page ? backgroundPage;
797804
798805 setUpAll (() async {
806+ server = await _fakeServer (
807+ hostname: hostname,
808+ port: port,
809+ assetPath: fakeAppDir,
810+ );
799811 browser = await puppeteer.launch (
800812 headless: false ,
801813 timeout: Duration (seconds: 60 ),
@@ -824,15 +836,19 @@ void main() async {
824836 });
825837
826838 tearDownAll (() async {
839+ await server.close ();
827840 await browser.close ();
828841 });
829842
830- // Note: This tests that the debug extension still works for DWDS versions
831- // <17.0.0. Those versions don't send the debug info with the ready event.
832- // Therefore the values are read from the Window object.
843+ // Note: This tests that the extension works for DWDS versions <17.0.0.
844+ // Those versions don't send the debug info with the ready event
845+ // (https://github.com/dart-lang/webdev/pull/1772). Therefore the values
846+ // are read from the Window object.
833847 test ('reads debug info from Window and saves to storage' , () async {
834848 // Navigate to the "Dart" app:
835- await navigateToPage (browser, url: fakeAppUrl, isNew: true );
849+ final appTab =
850+ await navigateToPage (browser, url: fakeAppUrl, isNew: true );
851+
836852 // Verify that we have debug info for the fake "Dart" app:
837853 final appTabId = await _getTabId (
838854 fakeAppUrl,
@@ -853,6 +869,56 @@ void main() async {
853869 expect (debugInfo.isFlutterApp, isFalse);
854870 expect (debugInfo.appOrigin, isNotNull);
855871 expect (debugInfo.appUrl, isNotNull);
872+
873+ // Close the tab:
874+ await appTab.close ();
875+ });
876+
877+ // Note: This tests that the extension works for DWDS versions <18.0.0.
878+ // Those versions don't support authentication from the injected client
879+ // (https://github.com/dart-lang/webdev/pull/1916). Therefore the auth
880+ // request is sent from the extension itself.
881+ test ('clicking on extension icon authenticates the user' , () async {
882+ // Navigate to the "Dart" app:
883+ final appTab =
884+ await navigateToPage (browser, url: fakeAppUrl, isNew: true );
885+
886+ // Wait for debug info to be saved:
887+ final appTabId = await _getTabId (
888+ fakeAppUrl,
889+ worker: worker,
890+ backgroundPage: backgroundPage,
891+ );
892+ final debugInfoKey = '$appTabId -debugInfo' ;
893+ final debugInfo = await _fetchStorageObj <DebugInfo >(
894+ debugInfoKey,
895+ storageArea: 'session' ,
896+ worker: worker,
897+ backgroundPage: backgroundPage,
898+ );
899+
900+ // Verify that the extension URL has been saved (this is what is used
901+ // by the extension to create the auth url):
902+ expect (debugInfo.extensionUrl, isNotNull);
903+
904+ // Click on the extension icon:
905+ await clickOnExtensionIcon (
906+ worker: worker,
907+ backgroundPage: backgroundPage,
908+ );
909+
910+ // Verify that the user is now authenticated:
911+ final authKey = '$appTabId -isAuthenticated' ;
912+ final isAuthenticated = await _fetchStorageObj <String >(
913+ authKey,
914+ storageArea: 'session' ,
915+ worker: worker,
916+ backgroundPage: backgroundPage,
917+ );
918+ expect (isAuthenticated, equals ('true' ));
919+
920+ // Close the tab:
921+ await appTab.close ();
856922 });
857923 });
858924 });
@@ -1052,3 +1118,22 @@ Future<void> _takeScreenshot(
10521118 p.join ('test' , 'puppeteer' , 'test_images' , '$screenshotName .png' );
10531119 await File (screenshotPath).writeAsBytes (screenshot);
10541120}
1121+
1122+ Future <HttpServer > _fakeServer ({
1123+ required String hostname,
1124+ required int port,
1125+ required String assetPath,
1126+ }) async {
1127+ final server = await startHttpServer (hostname, port: port);
1128+ final staticHandler = createStaticHandler (assetPath);
1129+ final cascade = Cascade ().add (staticHandler).add (_fakeAuthHandler);
1130+ serveHttpRequests (server, cascade.handler, (e, s) {});
1131+ return server;
1132+ }
1133+
1134+ Response _fakeAuthHandler (request) {
1135+ if (request.url.path == authenticationPath) {
1136+ return Response .ok (authenticationResponse);
1137+ }
1138+ return Response .notFound ('Not found' );
1139+ }
0 commit comments