Skip to content

Commit

Permalink
feat(cat-voices): Integration tests using flutter_driver (#1304)
Browse files Browse the repository at this point in the history
* custom driver for integration tests

* feat: working voices test driver

* feat: creating internal lib for voices driver

* fix: remove unused import

* fix: check-spelling

* fix: static analysis

* fix: test file

* refactor: skiping test for know

* fix: adding packages to melos

* fix: whitespacing

* Update catalyst_voices/packages/libs/catalyst_cardano/catalyst_cardano/example/test_driver/app_test.dart

Co-authored-by: Dominik Toton <[email protected]>

* feat: add extension to driver

* fix: remove unused function

* fix: add files to gitignore

---------

Co-authored-by: Dominik Toton <[email protected]>
Co-authored-by: bkioshn <[email protected]>
  • Loading branch information
3 people authored Dec 4, 2024
1 parent 5d45c30 commit 34de044
Show file tree
Hide file tree
Showing 21 changed files with 402 additions and 112 deletions.
1 change: 1 addition & 0 deletions .config/dictionaries/project.dic
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Autolayout
autorecalculates
autoresizing
backendpython
backgrounding
bech
bimap
bindgen
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,6 @@ test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
extensions/
extensions/
browser_extensions/
!catalyst_voices/packages/internal/catalyst_voices_driver/lib/src/extensions/
4 changes: 3 additions & 1 deletion catalyst_voices/melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ packageLicenseOverride:
remote_widgets_example: Apache-2.0
catalyst_voices_view_models: Apache-2.0
catalyst_voices_blocs: Apache-2.0
catalyst_voices_driver: Apache-2.0
catalyst_voices_shared: Apache-2.0
catalyst_voices_brands: Apache-2.0
catalyst_voices_services: Apache-2.0
Expand Down Expand Up @@ -129,6 +130,7 @@ command:
# the problem from here: https://github.com/jonataslaw/get_cli/issues/263
win32: ^5.5.4
web: ^1.1.0
webdriver: ^3.0.3
dev_dependencies:
test: ^1.24.9
build_runner: ^2.4.12
Expand Down Expand Up @@ -205,7 +207,7 @@ scripts:
EXIT_CODE=$? ; \
printf "%s" "$OUTPUT" | tojunit --output $MELOS_ROOT_PATH/test_reports/$MELOS_PACKAGE_NAME.junit-report.xml ; \
exit $EXIT_CODE'
# store the exit code after running the tests,
# this is the exit code for the whole script
EXIT_CODE=$?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
build/
10 changes: 10 additions & 0 deletions catalyst_voices/packages/internal/catalyst_voices_driver/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "a0ba2decab156c88708c4261d40660ab8f60da5f"
channel: "master"

project_type: package
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Catalyst Voices Driver
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
library;

export 'src/extension.dart';
export 'src/extensions/voices_web_driver_ext.dart';
export 'src/voices_web_driver.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import 'package:equatable/equatable.dart';

enum Browser {
chrome,
brave,
firefox;

String extensionStoreUrl(String extensionId) {
switch (this) {
case Browser.chrome:
return 'https://clients2.google.com/service/update2/crx?response=redirect&os=win&arch=x64&os_arch=x86_64&nacl_arch=x86-64&prod=chromiumcrx&prodchannel=beta&prodversion=79.0.3945.53&lang=ru&acceptformat=crx3&x=id%3D$extensionId%26installsource%3Dondemand%26uc';
case Browser.brave:
return 'https://brave.com/extension/$extensionId'; // TODO(ryszard-schossler): add brave store url
case Browser.firefox:
return 'https://addons.mozilla.org/en-US/firefox/addon/$extensionId'; // TODO(ryszard-schossler): add firefox store url
}
}
}

class Extension extends Equatable {
final String name;
final String id;
final Browser browser;
final String? extensionPath;

const Extension({
required this.name,
required this.id,
required this.browser,
required this.extensionPath,
});

@override
List<Object?> get props => [name, id, browser, extensionPath];
}

/* cSpell:disable */
//For now use full path to extension
List<Extension> extensions = [
const Extension(
name: 'Eternl',
id: 'kmhcihpebfmpgmihbkipmjlmmioameka',
browser: Browser.chrome,
extensionPath:
'/Users/ryszardschossler/Developer/H2B/catalyst-voices/catalyst_voices/packages/internal/catalyst_voices_driver/lib/src/browser_extensions/eternl',
),
const Extension(
name: 'Typhon',
id: 'kfdniefadaanbjodldohaedphafoffoh',
browser: Browser.chrome,
extensionPath:
'/Users/ryszardschossler/Developer/H2B/catalyst-voices/catalyst_voices/packages/internal/catalyst_voices_driver/lib/src/browser_extensions/typhon',
),
];
/* cSpell:enable */
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:catalyst_voices_driver/catalyst_voices_driver.dart';

extension VoicesWebDriverExt on VoicesWebDriver {
/// Switches the WebDriver's focus to a window whose URL contains the specified pattern.
///
/// [urlPattern] - The string pattern to match against window URLs.
///
/// Returns a [Future<bool>] that completes with:
/// - `true` if a matching window was found and switched to
/// - `false` if no matching window was found
Future<bool> switchToWindow(String urlPattern) async {
final windows = await webDriver.windows.toList();
for (final window in windows) {
await webDriver.switchTo.window(window);
final url = await webDriver.currentUrl;
if (url.contains(urlPattern)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import 'dart:convert';
import 'dart:io';

import 'package:catalyst_voices_driver/src/extension.dart';
import 'package:flutter_driver/flutter_driver.dart';
import 'package:webdriver/async_io.dart' as async_io;

class VoicesWebDriver extends WebFlutterDriver {
VoicesWebDriver.connectedTo(
super.connection, {
super.printCommunication = true,
super.logCommunicationToFile = true,
}) : super.connectedTo();

static Future<VoicesWebDriver> create(
List<Extension> extensions, {
String? hostUrl,
bool printCommunication = true,
bool logCommunicationToFile = true,
Duration? timeout,
}) async {
final driverCapabilities =
json.decode(Platform.environment['DRIVER_SESSION_CAPABILITIES']!)
as Map<String, dynamic>;
final browserName = driverCapabilities['browserName'] as String;

final extensionsPath = extensions
.where((e) => e.browser.name == browserName)
.map((e) => e.extensionPath)
.toList();

final sessionUri = Uri.parse(
Platform.environment['DRIVER_SESSION_URI'].toString(),
);

final driver = await async_io.createDriver(
uri: sessionUri,
desired: _driverCapabilites(extensionsPath),
);

final finalHostUrl = hostUrl ?? Platform.environment['VM_SERVICE_URL']!;
await driver.get(finalHostUrl);
await waitUntilExtensionInstalled(driver, timeout);

final supportTimeLineAction =
Platform.environment['SUPPORT_TIMELINE_ACTION'] == 'true';
final connection = FlutterWebConnection(driver, supportTimeLineAction);

return VoicesWebDriver.connectedTo(
connection,
printCommunication: printCommunication,
logCommunicationToFile: logCommunicationToFile,
);
}

static Map<String, dynamic> _driverCapabilites(List<String?> extensionsPath) {
final extensionPathString = _createPathExtension(extensionsPath);
final driverCapabilities =
json.decode(Platform.environment['DRIVER_SESSION_CAPABILITIES']!)
as Map<String, dynamic>;
final browserName = driverCapabilities['browserName'] as String;
final browserKeyArgs = browserName.contains('chrome')
? 'goog:chromeOptions'
: 'moz:firefoxOptions';
final browsersArgs =
driverCapabilities[browserKeyArgs] as Map<String, dynamic>;
final Directory dataDir = fs.systemTempDirectory.createTempSync(
'flutter_tool.',
);
final updatedDriverCapabilities = <String, dynamic>{
'browserName': browserName,
browserKeyArgs: {
'args': [
...(browsersArgs['args'] as List<dynamic>? ?? <String>[])
.cast<String>(),
'--user-data-dir=${dataDir.path}',
'--disable-extensions-except=$extensionPathString',
'--load-extension=$extensionPathString',
'--disable-gpu',
'--disable-renderer-backgrounding',
'--disable-search-engine-choice-screen',
'--no-first-run',
'--enable-automation',
'--enable-extension-automation',
'--allow-insecure-localhost',
],
},
};

return updatedDriverCapabilities;
}

static String _createPathExtension(List<String?> extensions) {
return extensions.where((e) => e != null).join(',');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: catalyst_voices_driver
description: Catalyst Voices Driver
version: 0.0.1
publish_to: none

environment:
sdk: ">=3.5.0 <4.0.0"
flutter: ">=3.24.1"

dependencies:
equatable: ^2.0.7
flutter:
sdk: flutter
flutter_driver:
sdk: flutter
webdriver: ^3.0.3

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ dependencies:
equatable: ^2.0.7
flutter:
sdk: flutter
flutter_driver:
sdk: flutter
flutter_secure_storage: ^9.2.2
json_annotation: ^4.8.1
logging: ^1.2.0
path: ^1.9.0
rxdart: ^0.27.7
uuid: ^4.5.1
web: ^1.1.0
webdriver: ^3.0.3

dev_dependencies:
build_runner: ^2.4.12
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "example",
"request": "launch",
"type": "dart",
"args": [
"--web-header",
"Cross-Origin-Opener-Policy=same-origin",
"--web-header",
"Cross-Origin-Embedder-Policy=require-corp",
],
},
{
"name": "example (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
"args": [
"--web-header",
"Cross-Origin-Opener-Policy=same-origin",
"--web-header",
"Cross-Origin-Embedder-Policy=require-corp",
],
},
{
"name": "example (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"args": [
"--web-header",
"Cross-Origin-Opener-Policy=same-origin",
"--web-header",
"Cross-Origin-Embedder-Policy=require-corp",
],
}
]
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
# catalyst_cardano_example

Demonstrates usage of catalyst_cardano plugin

## To run integration tests

To run test driver you need to have chromedriver installed.

Then in terminal run:

```bash
chromedriver --port=4444
```

In new terminal in example dir run:

```bash
flutter drive --target=test_driver/app.dart \
--web-browser-flag=--disable-web-security \
--web-browser-flag=--disable-gpu \
--web-browser-flag=--disable-search-engine-choice-screen \
--web-header=Cross-Origin-Opener-Policy=same-origin \
--web-header=Cross-Origin-Embedder-Policy=require-corp \
--debug \
--no-headless \
-d web-server --browser-name=chrome --driver-port=4444
```
Loading

0 comments on commit 34de044

Please sign in to comment.