Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c13cd89
Wrote felt_config file and parsing.
eyebrowsoffire Feb 10, 2023
b60b1b4
Some suite filtering and copy artifacts step refactor.
eyebrowsoffire Feb 14, 2023
8760d77
CompileBundleStep implemented.
eyebrowsoffire Feb 16, 2023
752547d
Suites running, but assets alongside tests are not being served.
eyebrowsoffire Feb 17, 2023
1bdd442
Reduce verbosity and fix serving assets from test directory.
eyebrowsoffire Feb 17, 2023
b6e520e
All filters except file filters are implemented.
eyebrowsoffire Feb 17, 2023
e26e6a3
File filter implemented.
eyebrowsoffire Feb 17, 2023
c2d464d
Move around tests themselves.
eyebrowsoffire Feb 17, 2023
3c9c37d
Test against canvaskit_chromium.
eyebrowsoffire Feb 17, 2023
a7906e8
Added and updated documentation.
eyebrowsoffire Feb 17, 2023
b0cfad9
Started some CI stuff.
eyebrowsoffire Mar 1, 2023
78859af
Add bringup:true to the new web engine step.
eyebrowsoffire Mar 1, 2023
2dd558d
Change felt parameters.
eyebrowsoffire Mar 1, 2023
35163cf
Remove old web engine builders.
eyebrowsoffire Mar 1, 2023
d721f10
Always hard code canvaskit variants for chrome and edge.
eyebrowsoffire Mar 2, 2023
ad81ea6
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 2, 2023
c48e279
improve some error messages
mdebbar Mar 2, 2023
83f67b8
support filtering by canvaskit variant
mdebbar Mar 2, 2023
c5f60d1
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 7, 2023
1687708
Change linux_web_engine to new felt commands.
eyebrowsoffire Mar 7, 2023
d6ec4e7
Skip the legacy build path for license checks.
eyebrowsoffire Mar 8, 2023
77e0119
Update lib/web_ui/dev/steps/compile_bundle_step.dart
eyebrowsoffire Mar 8, 2023
7fcc94b
Revert weird change to README.md
eyebrowsoffire Mar 8, 2023
8294f13
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 8, 2023
581023a
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 10, 2023
28808e7
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 10, 2023
55195f0
Separate web_tests build out.
eyebrowsoffire Mar 10, 2023
dbc98f9
Copy artifacts in a generator step.
eyebrowsoffire Mar 10, 2023
0c6bf80
Do copy artifacts as part of the test run.
eyebrowsoffire Mar 10, 2023
dd3c7b9
Allow testing against wasm_profile artifacts.
eyebrowsoffire Mar 11, 2023
38dd751
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 13, 2023
f390a96
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 16, 2023
db9c9e0
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 23, 2023
1071c87
Remove duplicated build step.
eyebrowsoffire Mar 23, 2023
5f5ff75
Add new fields for the v2 tests.
eyebrowsoffire Mar 23, 2023
0cc002e
Put the test invocation into `tasks`
eyebrowsoffire Mar 23, 2023
d5a9e7a
Name the test.
eyebrowsoffire Mar 23, 2023
d84c677
Try sharding compilation and tests.
eyebrowsoffire Mar 23, 2023
bb45d11
Fix bundle filtering.
eyebrowsoffire Mar 23, 2023
ee89022
Try making copy artifacts a subbuild.
eyebrowsoffire Mar 23, 2023
164483f
The main build should be `web_tests/artifacts`
eyebrowsoffire Mar 23, 2023
c25b4da
test_bundles, not test_bundle
eyebrowsoffire Mar 24, 2023
97f9459
Generate all builder json.
eyebrowsoffire Mar 24, 2023
a8bc5c4
Specify an empty tests list.
eyebrowsoffire Mar 24, 2023
442034d
Generate the builder json again.
eyebrowsoffire Mar 24, 2023
eb1e3ec
script, not scripts.
eyebrowsoffire Mar 24, 2023
d25ca9e
Get rid of extra array layer.
eyebrowsoffire Mar 24, 2023
aed3f1b
No need for empty tests array in build steps
eyebrowsoffire Mar 24, 2023
f47bfd3
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 24, 2023
2271295
It's `script` for tests, but `scripts` for generators.
eyebrowsoffire Mar 24, 2023
d4a7f5a
Mac, not MacOS
eyebrowsoffire Mar 24, 2023
6d5fa74
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 24, 2023
4ed8d43
Yegor's comments.
eyebrowsoffire Mar 27, 2023
d66c188
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 27, 2023
ba83669
Add back screenshot logging under verbose flag.
eyebrowsoffire Mar 27, 2023
9b61f3a
Merge branch 'main' into web_test_reorganization
eyebrowsoffire Mar 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
All filters except file filters are implemented.
  • Loading branch information
eyebrowsoffire committed Mar 2, 2023
commit b6e520ee69c38d550b1c3c679d991236cde7e7b4
111 changes: 66 additions & 45 deletions lib/web_ui/dev/suite_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,67 +19,88 @@ abstract class SuiteFilter {
SuiteFilterResult filterSuite(TestSuite suite);
}

bool _macOSSupportsBrowser(BrowserName browser) {
switch (browser) {
case BrowserName.chrome:
case BrowserName.firefox:
case BrowserName.safari:
return true;
case BrowserName.edge:
return false;
abstract class AllowListSuiteFilter<T> implements SuiteFilter {
AllowListSuiteFilter({ required this.allowList });

final Set<T> allowList;

T getAttributeForSuite(TestSuite suite);

String rejectReason(TestSuite suite) {
return '${getAttributeForSuite(suite)} does not match filter.';
}
}

bool _linuxSupportsBrowser(BrowserName browser) {
switch (browser) {
case BrowserName.chrome:
case BrowserName.firefox:
return true;
case BrowserName.edge:
case BrowserName.safari:
return false;
@override
SuiteFilterResult filterSuite(TestSuite suite) {
if (allowList.contains(getAttributeForSuite(suite))) {
return SuiteFilterResult.accepted();
} else {
return SuiteFilterResult.rejected(rejectReason(suite));
}
}
}

bool _windowsSupportsBrowser(BrowserName browser) {
switch (browser) {
case BrowserName.chrome:
case BrowserName.edge:
return true;
case BrowserName.firefox:
case BrowserName.safari:
return false;
}
class BrowserSuiteFilter extends AllowListSuiteFilter<BrowserName> {
BrowserSuiteFilter({required super.allowList});

@override
BrowserName getAttributeForSuite(TestSuite suite) => suite.runConfig.browser;
}

class SuiteNameFilter extends AllowListSuiteFilter<String> {
SuiteNameFilter({required super.allowList});

@override
String getAttributeForSuite(TestSuite suite) => suite.name;
}

typedef BrowserSupportCheck = bool Function(BrowserName browser);
class BundleNameFilter extends AllowListSuiteFilter<String> {
BundleNameFilter({required super.allowList});

BrowserSupportCheck get _platformBrowserSupportCheck {
@override
String getAttributeForSuite(TestSuite suite) => suite.testBundle.name;
}

class CompilerFilter extends AllowListSuiteFilter<Compiler> {
CompilerFilter({required super.allowList});

@override
Compiler getAttributeForSuite(TestSuite suite) => suite.testBundle.compileConfig.compiler;
}

class RendererFilter extends AllowListSuiteFilter<Renderer> {
RendererFilter({required super.allowList});

@override
Renderer getAttributeForSuite(TestSuite suite) => suite.testBundle.compileConfig.renderer;
}

Set<BrowserName> get _supportedPlatformBrowsers {
if (io.Platform.isLinux) {
return _linuxSupportsBrowser;
return <BrowserName>{
BrowserName.chrome,
BrowserName.firefox
};
} else if (io.Platform.isMacOS) {
return _macOSSupportsBrowser;
return <BrowserName>{
BrowserName.chrome,
BrowserName.firefox,
BrowserName.safari,
};
} else if (io.Platform.isWindows) {
return _windowsSupportsBrowser;
return <BrowserName>{
BrowserName.chrome,
BrowserName.edge,
};
} else {
throw AssertionError('Unsupported OS: ${io.Platform.operatingSystem}');
}
}

class PlatformSuiteFilter implements SuiteFilter {
PlatformSuiteFilter() : _browserCheck = _platformBrowserSupportCheck;

final BrowserSupportCheck _browserCheck;
class PlatformBrowserFilter extends BrowserSuiteFilter {
PlatformBrowserFilter() : super(allowList: _supportedPlatformBrowsers);

@override
SuiteFilterResult filterSuite(TestSuite suite) {
final BrowserName browser = suite.runConfig.browser;
if (_browserCheck(browser)) {
return SuiteFilterResult.accepted();
} else {
return SuiteFilterResult.rejected(
'Current platform (${io.Platform.operatingSystem}) does not support browser $browser'
);
}
}
String rejectReason(TestSuite suite) =>
'Current platform (${io.Platform.operatingSystem}) does not support browser ${suite.runConfig.browser}';
}
129 changes: 97 additions & 32 deletions lib/web_ui/dev/test_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:path/path.dart' as path;
import 'package:watcher/src/watch_event.dart';

import 'environment.dart';
import 'exceptions.dart';
import 'felt_config.dart';
import 'pipeline.dart';
import 'steps/compile_bundle_step.dart';
Expand Down Expand Up @@ -72,11 +73,25 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {
'.dart_tool/goldens. Use this option to bulk-update all screenshots, '
'for example, when a new browser version affects pixels.',
)
..addOption(
..addMultiOption(
'browser',
defaultsTo: 'chrome',
help: 'An option to choose a browser to run the tests. By default '
'tests run in Chrome.',
help: 'Filter test suites by browser.',
)
..addMultiOption(
'compiler',
help: 'Filter test suites by compiler.',
)
..addMultiOption(
'renderer',
help: 'Filter test suites by renderer.',
)
..addMultiOption(
'suite',
help: 'Filter test suites by suite name.',
)
..addMultiOption(
'bundle',
help: 'Filter test suites by bundle name.',
)
..addFlag(
'fail-early',
Expand All @@ -94,11 +109,6 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {
..addFlag(
'wasm',
help: 'Whether the test we are running are compiled to webassembly.'
)
..addFlag(
'use-local-canvaskit',
help: 'Optional. Whether or not to use the locally built version of '
'CanvasKit in the tests.',
);
}

Expand All @@ -114,8 +124,6 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {

bool get failEarly => boolArg('fail-early');

bool get isWasm => boolArg('wasm');

/// Whether to start the browser in debug mode.
///
/// In this mode the browser pauses before running the test to allow
Expand All @@ -133,9 +141,6 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {
/// Whether all tests should run.
bool get runAllTests => targets.isEmpty;

/// The name of the browser to run tests in.
String get browserName => stringArg('browser');

/// When running screenshot tests, require Skia Gold to be available and
/// reachable.
bool get requireSkiaGold => boolArg('require-skia-gold');
Expand All @@ -147,27 +152,90 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {
/// Path to a CanvasKit build. Overrides the default CanvasKit.
String? get overridePathToCanvasKit => argResults!['canvaskit-path'] as String?;

/// Whether or not to use the locally built version of CanvasKit.
bool get useLocalCanvasKit => boolArg('use-local-canvaskit');
final FeltConfig config = FeltConfig.fromFile(
path.join(environment.webUiTestDir.path, 'felt_config.yaml')
);

BrowserSuiteFilter? makeBrowserFilter() {
final List<String>? browserArgs = argResults!['browser'] as List<String>?;
if (browserArgs == null || browserArgs.isEmpty) {
return null;
}
final Set<BrowserName> browserNames = Set<BrowserName>.from(browserArgs.map((String arg) => BrowserName.values.byName(arg)));
return BrowserSuiteFilter(allowList: browserNames);
}

CompilerFilter? makeCompilerFilter() {
final List<String>? compilerArgs = argResults!['compiler'] as List<String>?;
if (compilerArgs == null || compilerArgs.isEmpty) {
return null;
}
final Set<Compiler> compilers = Set<Compiler>.from(compilerArgs.map((String arg) => Compiler.values.byName(arg)));
return CompilerFilter(allowList: compilers);
}

RendererFilter? makeRendererFilter() {
final List<String>? rendererArgs = argResults!['renderer'] as List<String>?;
if (rendererArgs == null || rendererArgs.isEmpty) {
return null;
}
final Set<Renderer> renderers = Set<Renderer>.from(rendererArgs.map((String arg) => Renderer.values.byName(arg)));
return RendererFilter(allowList: renderers);
}

SuiteNameFilter? makeSuiteNameFilter() {
final List<String>? suiteNameArgs = argResults!['suite'] as List<String>?;
if (suiteNameArgs == null || suiteNameArgs.isEmpty) {
return null;
}

final Iterable<String> allSuiteNames = config.testSuites.map((TestSuite suite) => suite.name);
for (final String suiteName in suiteNameArgs) {
if (!allSuiteNames.contains(suiteName)) {
throw ToolExit('No suite found named $suiteName');
}
}
return SuiteNameFilter(allowList: Set<String>.from(suiteNameArgs));
}

BundleNameFilter? makeBundleNameFilter() {
final List<String>? bundleNameArgs = argResults!['bundle'] as List<String>?;
if (bundleNameArgs == null || bundleNameArgs.isEmpty) {
return null;
}

final Iterable<String> allBundleNames = config.testSuites.map((TestSuite suite) => suite.name);
for (final String bundleName in bundleNameArgs) {
if (!allBundleNames.contains(bundleName)) {
throw ToolExit('No bundle found named $bundleName');
}
}
return BundleNameFilter(allowList: Set<String>.from(bundleNameArgs));
}

List<SuiteFilter> get suiteFilters {
final BrowserSuiteFilter? browserFilter = makeBrowserFilter();
final CompilerFilter? compilerFilter = makeCompilerFilter();
final RendererFilter? rendererFilter = makeRendererFilter();
final SuiteNameFilter? suiteNameFilter = makeSuiteNameFilter();
final BundleNameFilter? bundleNameFilter = makeBundleNameFilter();
return <SuiteFilter>[
PlatformSuiteFilter()
// TODO(jacksongardner): Add more filters
// Add browser filter from CLI
// Add suite filter from CLI
// Add compiler filter from CLI
PlatformBrowserFilter(),
if (browserFilter != null) browserFilter,
if (compilerFilter != null) compilerFilter,
if (rendererFilter != null) rendererFilter,
if (suiteNameFilter != null) suiteNameFilter,
if (bundleNameFilter != null) bundleNameFilter,
// Add file filter from CLI
// Add renderer filter from CLI
];
}

List<TestSuite> _filterTestSuites(List<TestSuite> suites) {
List<TestSuite> _filterTestSuites() {
if (isVerbose) {
print('Filtering suites...');
}
final List<SuiteFilter> filters = suiteFilters;
final List<TestSuite> filteredSuites = suites.where((TestSuite suite) {
final List<TestSuite> filteredSuites = config.testSuites.where((TestSuite suite) {
for (final SuiteFilter filter in filters) {
final SuiteFilterResult result = filter.filterSuite(suite);
if (!result.isAccepted) {
Expand All @@ -182,10 +250,10 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {
return filteredSuites;
}

List<TestBundle> _filterBundlesForSuites(List<TestBundle> bundles, List<TestSuite> suites) {
List<TestBundle> _filterBundlesForSuites(List<TestSuite> suites) {
final Set<TestBundle> seenBundles =
Set<TestBundle>.from(suites.map((TestSuite suite) => suite.testBundle));
return bundles.where((TestBundle bundle) => seenBundles.contains(bundle)).toList();
return config.testBundles.where((TestBundle bundle) => seenBundles.contains(bundle)).toList();
}

ArtifactDependencies _artifactsForSuites(List<TestSuite> suites) {
Expand All @@ -195,12 +263,9 @@ class TestCommand extends Command<bool> with ArgUtils<bool> {

@override
Future<bool> run() async {
final FeltConfig config = FeltConfig.fromFile(
path.join(environment.webUiTestDir.path, 'felt_config.yaml')
);
final List<TestSuite> filteredSuites = _filterTestSuites(config.testSuites);
final List<TestBundle> bundles = _filterBundlesForSuites(config.testBundles, filteredSuites);
final ArtifactDependencies artifacts = _artifactsForSuites(config.testSuites);
final List<TestSuite> filteredSuites = _filterTestSuites();
final List<TestBundle> bundles = _filterBundlesForSuites(filteredSuites);
final ArtifactDependencies artifacts = _artifactsForSuites(filteredSuites);
if (isList || isVerbose) {
print('Suites:');
for (final TestSuite suite in filteredSuites) {
Expand Down