Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate many custom matchers to TypeMatcher #1668

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
4 changes: 4 additions & 0 deletions pkgs/file/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ dev_dependencies:
file_testing: ^3.0.0
lints: ^2.0.1
test: ^1.23.1

dependency_overrides:
file_testing:
path: ../file_testing
5 changes: 5 additions & 0 deletions pkgs/file_testing/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 3.1.0-wip

* Changed the type of several matchers to `TypeMatcher` which allows cascading
their usage with `.having` and similar.

## 3.0.2

* Require Dart 3.1.
Expand Down
7 changes: 1 addition & 6 deletions pkgs/file_testing/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
include: package:lints/recommended.yaml

analyzer:
errors:
# Allow having TODOs in the code
todo: ignore
include: package:dart_flutter_team_lints/analysis_options.yaml
109 changes: 17 additions & 92 deletions pkgs/file_testing/lib/src/testing/core_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,36 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// ignore_for_file: comment_references

import 'dart:io';

import 'package:test/test.dart';

import 'internal.dart';

/// Matcher that successfully matches against any instance of [Directory].
const Matcher isDirectory = TypeMatcher<Directory>();
const isDirectory = TypeMatcher<Directory>();

/// Matcher that successfully matches against any instance of [File].
const Matcher isFile = TypeMatcher<File>();
const isFile = TypeMatcher<File>();

/// Matcher that successfully matches against any instance of [Link].
const Matcher isLink = TypeMatcher<Link>();
const isLink = TypeMatcher<Link>();

/// Matcher that successfully matches against any instance of
/// [FileSystemEntity].
const Matcher isFileSystemEntity = TypeMatcher<FileSystemEntity>();
const isFileSystemEntity = TypeMatcher<FileSystemEntity>();

/// Matcher that successfully matches against any instance of [FileStat].
const Matcher isFileStat = TypeMatcher<FileStat>();
const isFileStat = TypeMatcher<FileStat>();

/// Returns a [Matcher] that matches [path] against an entity's path.
///
/// [path] may be a String, a predicate function, or a [Matcher]. If it is
/// a String, it will be wrapped in an equality matcher.
Matcher hasPath(dynamic path) => _HasPath(path);
TypeMatcher<FileSystemEntity> hasPath(dynamic path) =>
isFileSystemEntity.having((e) => e.path, 'path', path);

/// Returns a [Matcher] that successfully matches against an instance of
/// [FileSystemException].
Expand All @@ -39,7 +42,8 @@ Matcher hasPath(dynamic path) => _HasPath(path);
/// [osErrorCode] may be an `int`, a predicate function, or a [Matcher]. If it
/// is an `int`, it will be wrapped in an equality matcher.
Matcher isFileSystemException([dynamic osErrorCode]) =>
_FileSystemException(osErrorCode);
const TypeMatcher<FileSystemException>().having((e) => e.osError?.errorCode,
'osError.errorCode', _fileExceptionWrapMatcher(osErrorCode));

/// Returns a matcher that successfully matches against a future or function
/// that throws a [FileSystemException].
Expand Down Expand Up @@ -67,89 +71,10 @@ void expectFileSystemException(dynamic osErrorCode, void Function() callback) {

/// Matcher that successfully matches against a [FileSystemEntity] that
/// exists ([FileSystemEntity.existsSync] returns true).
const Matcher exists = _Exists();

class _FileSystemException extends Matcher {
_FileSystemException(dynamic osErrorCode)
: _matcher = _wrapMatcher(osErrorCode);

final Matcher? _matcher;

static Matcher? _wrapMatcher(dynamic osErrorCode) {
if (osErrorCode == null) {
return null;
}
return ignoreOsErrorCodes ? anything : wrapMatcher(osErrorCode);
}

@override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
if (item is FileSystemException) {
return _matcher == null ||
_matcher!.matches(item.osError?.errorCode, matchState);
}
return false;
}

@override
Description describe(Description desc) {
if (_matcher == null) {
return desc.add('FileSystemException');
} else {
desc.add('FileSystemException with osError.errorCode: ');
return _matcher!.describe(desc);
}
}
}

class _HasPath extends Matcher {
_HasPath(dynamic path) : _matcher = wrapMatcher(path);

final Matcher _matcher;
final TypeMatcher exists =
kevmoo marked this conversation as resolved.
Show resolved Hide resolved
isFileSystemEntity.having((e) => e.existsSync(), 'existsSync', true);

@override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
_matcher.matches(item.path, matchState);

@override
Description describe(Description desc) {
desc.add('has path: ');
return _matcher.describe(desc);
}

@override
Description describeMismatch(
dynamic item,
Description desc,
Map<dynamic, dynamic> matchState,
bool verbose,
) {
desc.add('has path: \'${item.path}\'').add('\n Which: ');
final Description pathDesc = StringDescription();
_matcher.describeMismatch(item.path, pathDesc, matchState, verbose);
desc.add(pathDesc.toString());
return desc;
}
}

class _Exists extends Matcher {
const _Exists();

@override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
item is FileSystemEntity && item.existsSync();

@override
Description describe(Description description) =>
description.add('a file system entity that exists');

@override
Description describeMismatch(
dynamic item,
Description description,
Map<dynamic, dynamic> matchState,
bool verbose,
) {
return description.add('does not exist');
}
}
Matcher? _fileExceptionWrapMatcher(dynamic osErrorCode) =>
(osErrorCode == null || ignoreOsErrorCodes)
? anything
: wrapMatcher(osErrorCode);
6 changes: 3 additions & 3 deletions pkgs/file_testing/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: file_testing
version: 3.0.2
version: 3.1.0-wip
description: Testing utilities for package:file.
repository: https://github.com/dart-lang/tools/tree/main/pkgs/file_testing
issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Afile_testing
Expand All @@ -10,5 +10,5 @@ environment:
dependencies:
test: ^1.23.1

dev_dependencies:
lints: ^5.0.0
dev_dependencies:
dart_flutter_team_lints: ^3.0.0
Loading