mirror of
https://github.com/flutter/packages.git
synced 2025-06-02 17:20:17 +08:00
983 lines
29 KiB
Dart
983 lines
29 KiB
Dart
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:args/command_runner.dart';
|
|
import 'package:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:flutter_plugin_tools/src/common/core.dart';
|
|
import 'package:flutter_plugin_tools/src/pubspec_check_command.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'mocks.dart';
|
|
import 'util.dart';
|
|
|
|
/// Returns the top section of a pubspec.yaml for a package named [name],
|
|
/// for either a flutter/packages or flutter/plugins package depending on
|
|
/// the values of [isPlugin].
|
|
///
|
|
/// By default it will create a header that includes all of the expected
|
|
/// values, elements can be changed via arguments to create incorrect
|
|
/// entries.
|
|
///
|
|
/// If [includeRepository] is true, by default the path in the link will
|
|
/// be "packages/[name]"; a different "packages"-relative path can be
|
|
/// provided with [repositoryPackagesDirRelativePath].
|
|
String _headerSection(
|
|
String name, {
|
|
bool isPlugin = false,
|
|
bool includeRepository = true,
|
|
String repositoryBranch = 'main',
|
|
String? repositoryPackagesDirRelativePath,
|
|
bool includeHomepage = false,
|
|
bool includeIssueTracker = true,
|
|
bool publishable = true,
|
|
String? description,
|
|
}) {
|
|
final String repositoryPath = repositoryPackagesDirRelativePath ?? name;
|
|
final List<String> repoLinkPathComponents = <String>[
|
|
'flutter',
|
|
if (isPlugin) 'plugins' else 'packages',
|
|
'tree',
|
|
repositoryBranch,
|
|
'packages',
|
|
repositoryPath,
|
|
];
|
|
final String repoLink =
|
|
'https://github.com/${repoLinkPathComponents.join('/')}';
|
|
final String issueTrackerLink = 'https://github.com/flutter/flutter/issues?'
|
|
'q=is%3Aissue+is%3Aopen+label%3A%22p%3A+$name%22';
|
|
description ??= 'A test package for validating that the pubspec.yaml '
|
|
'follows repo best practices.';
|
|
return '''
|
|
name: $name
|
|
description: $description
|
|
${includeRepository ? 'repository: $repoLink' : ''}
|
|
${includeHomepage ? 'homepage: $repoLink' : ''}
|
|
${includeIssueTracker ? 'issue_tracker: $issueTrackerLink' : ''}
|
|
version: 1.0.0
|
|
${publishable ? '' : "publish_to: 'none'"}
|
|
''';
|
|
}
|
|
|
|
String _environmentSection() {
|
|
return '''
|
|
environment:
|
|
sdk: ">=2.12.0 <3.0.0"
|
|
flutter: ">=2.0.0"
|
|
''';
|
|
}
|
|
|
|
String _flutterSection({
|
|
bool isPlugin = false,
|
|
String? implementedPackage,
|
|
Map<String, Map<String, String>> pluginPlatformDetails =
|
|
const <String, Map<String, String>>{},
|
|
}) {
|
|
String pluginEntry = '''
|
|
plugin:
|
|
${implementedPackage == null ? '' : ' implements: $implementedPackage'}
|
|
platforms:
|
|
''';
|
|
|
|
for (final MapEntry<String, Map<String, String>> platform
|
|
in pluginPlatformDetails.entries) {
|
|
pluginEntry += '''
|
|
${platform.key}:
|
|
''';
|
|
for (final MapEntry<String, String> detail in platform.value.entries) {
|
|
pluginEntry += '''
|
|
${detail.key}: ${detail.value}
|
|
''';
|
|
}
|
|
}
|
|
|
|
return '''
|
|
flutter:
|
|
${isPlugin ? pluginEntry : ''}
|
|
''';
|
|
}
|
|
|
|
String _dependenciesSection() {
|
|
return '''
|
|
dependencies:
|
|
flutter:
|
|
sdk: flutter
|
|
''';
|
|
}
|
|
|
|
String _devDependenciesSection() {
|
|
return '''
|
|
dev_dependencies:
|
|
flutter_test:
|
|
sdk: flutter
|
|
''';
|
|
}
|
|
|
|
String _falseSecretsSection() {
|
|
return '''
|
|
false_secrets:
|
|
- /lib/main.dart
|
|
''';
|
|
}
|
|
|
|
void main() {
|
|
group('test pubspec_check_command', () {
|
|
late CommandRunner<void> runner;
|
|
late RecordingProcessRunner processRunner;
|
|
late FileSystem fileSystem;
|
|
late MockPlatform mockPlatform;
|
|
late Directory packagesDir;
|
|
|
|
setUp(() {
|
|
fileSystem = MemoryFileSystem();
|
|
mockPlatform = MockPlatform();
|
|
packagesDir = fileSystem.currentDirectory.childDirectory('packages');
|
|
createPackagesDirectory(parentDir: packagesDir.parent);
|
|
processRunner = RecordingProcessRunner();
|
|
final PubspecCheckCommand command = PubspecCheckCommand(
|
|
packagesDir,
|
|
processRunner: processRunner,
|
|
platform: mockPlatform,
|
|
);
|
|
|
|
runner = CommandRunner<void>(
|
|
'pubspec_check_command', 'Test for pubspec_check_command');
|
|
runner.addCommand(command);
|
|
});
|
|
|
|
test('passes for a plugin following conventions', () async {
|
|
final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
${_falseSecretsSection()}
|
|
''');
|
|
|
|
plugin.getExamples().first.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_example',
|
|
publishable: false,
|
|
includeRepository: false,
|
|
includeIssueTracker: false,
|
|
)}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
${_flutterSection()}
|
|
''');
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'pubspec-check',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin...'),
|
|
contains('Running for plugin/example...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes for a Flutter package following conventions', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
|
|
package.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('a_package')}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
${_flutterSection()}
|
|
${_falseSecretsSection()}
|
|
''');
|
|
|
|
package.getExamples().first.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'a_package',
|
|
publishable: false,
|
|
includeRepository: false,
|
|
includeIssueTracker: false,
|
|
)}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
${_flutterSection()}
|
|
''');
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'pubspec-check',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for a_package...'),
|
|
contains('Running for a_package/example...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes for a minimal package following conventions', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('package', packagesDir, examples: <String>[]);
|
|
|
|
package.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('package')}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output = await runCapturingPrint(runner, <String>[
|
|
'pubspec-check',
|
|
]);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for package...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when homepage is included', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, includeHomepage: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Found a "homepage" entry; only "repository" should be used.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when repository is missing', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, includeRepository: false)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Missing "repository"'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when homepage is given instead of repository', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, includeHomepage: true, includeRepository: false)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Found a "homepage" entry; only "repository" should be used.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when repository package name is incorrect', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, repositoryPackagesDirRelativePath: 'different_plugin')}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('The "repository" link should end with the package path.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when repository uses master instead of main', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, repositoryBranch: 'master')}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('The "repository" link should use "main", not "master".'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when issue tracker is missing', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, includeIssueTracker: false)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('A package should have an "issue_tracker" link'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when description is too short', () async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'a_plugin', packagesDir.childDirectory('a_plugin'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, description: 'Too short')}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('"description" is too short. pub.dev recommends package '
|
|
'descriptions of 60-180 characters.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test(
|
|
'allows short descriptions for non-app-facing parts of federated plugins',
|
|
() async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, description: 'Too short')}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('"description" is too short. pub.dev recommends package '
|
|
'descriptions of 60-180 characters.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when description is too long', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
const String description = 'This description is too long. It just goes '
|
|
'on and on and on and on and on. pub.dev will down-score it because '
|
|
'there is just too much here. Someone shoul really cut this down to just '
|
|
'the core description so that search results are more useful and the '
|
|
'package does not lose pub points.';
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true, description: description)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('"description" is too long. pub.dev recommends package '
|
|
'descriptions of 60-180 characters.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when environment section is out of order', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
${_environmentSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when flutter section is out of order', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when dependencies section is out of order', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_devDependenciesSection()}
|
|
${_dependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when dev_dependencies section is out of order', () async {
|
|
final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_devDependenciesSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when false_secrets section is out of order', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_falseSecretsSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when an implemenation package is missing "implements"',
|
|
() async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a_foo', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin_a_foo', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Missing "implements: plugin_a" in "plugin" section.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when an implemenation package has the wrong "implements"',
|
|
() async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a_foo', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin_a_foo', isPlugin: true)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true, implementedPackage: 'plugin_a_foo')}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Expecetd "implements: plugin_a"; '
|
|
'found "implements: plugin_a_foo".'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes for a correct implemenation package', () async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a_foo', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_a_foo',
|
|
isPlugin: true,
|
|
repositoryPackagesDirRelativePath: 'plugin_a/plugin_a_foo',
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true, implementedPackage: 'plugin_a')}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['pubspec-check']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin_a_foo...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('fails when a "default_package" looks incorrect', () async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_a',
|
|
isPlugin: true,
|
|
repositoryPackagesDirRelativePath: 'plugin_a/plugin_a',
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(
|
|
isPlugin: true,
|
|
pluginPlatformDetails: <String, Map<String, String>>{
|
|
'android': <String, String>{'default_package': 'plugin_b_android'}
|
|
},
|
|
)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'"plugin_b_android" is not an expected implementation name for "plugin_a"'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test(
|
|
'fails when a "default_package" does not have a corresponding dependency',
|
|
() async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_a',
|
|
isPlugin: true,
|
|
repositoryPackagesDirRelativePath: 'plugin_a/plugin_a',
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(
|
|
isPlugin: true,
|
|
pluginPlatformDetails: <String, Map<String, String>>{
|
|
'android': <String, String>{'default_package': 'plugin_a_android'}
|
|
},
|
|
)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('The following default_packages are missing corresponding '
|
|
'dependencies:\n plugin_a_android'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes for an app-facing package without "implements"', () async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_a',
|
|
isPlugin: true,
|
|
repositoryPackagesDirRelativePath: 'plugin_a/plugin_a',
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['pubspec-check']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin_a/plugin_a...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('passes for a platform interface package without "implements"',
|
|
() async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a_platform_interface', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin_a_platform_interface',
|
|
isPlugin: true,
|
|
repositoryPackagesDirRelativePath:
|
|
'plugin_a/plugin_a_platform_interface',
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['pubspec-check']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin_a_platform_interface...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('validates some properties even for unpublished packages', () async {
|
|
final RepositoryPackage plugin = createFakePlugin(
|
|
'plugin_a_foo', packagesDir.childDirectory('plugin_a'),
|
|
examples: <String>[]);
|
|
|
|
// Environment section is in the wrong location.
|
|
// Missing 'implements'.
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('plugin_a_foo', isPlugin: true, publishable: false)}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
${_environmentSection()}
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['pubspec-check'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains(
|
|
'Major sections should follow standard repository ordering:'),
|
|
contains('Missing "implements: plugin_a" in "plugin" section.'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('ignores some checks for unpublished packages', () async {
|
|
final RepositoryPackage plugin =
|
|
createFakePlugin('plugin', packagesDir, examples: <String>[]);
|
|
|
|
// Missing metadata that is only useful for published packages, such as
|
|
// repository and issue tracker.
|
|
plugin.pubspecFile.writeAsStringSync('''
|
|
${_headerSection(
|
|
'plugin',
|
|
isPlugin: true,
|
|
publishable: false,
|
|
includeRepository: false,
|
|
includeIssueTracker: false,
|
|
)}
|
|
${_environmentSection()}
|
|
${_flutterSection(isPlugin: true)}
|
|
${_dependenciesSection()}
|
|
${_devDependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['pubspec-check']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for plugin...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
|
|
group('test pubspec_check_command on Windows', () {
|
|
late CommandRunner<void> runner;
|
|
late RecordingProcessRunner processRunner;
|
|
late FileSystem fileSystem;
|
|
late MockPlatform mockPlatform;
|
|
late Directory packagesDir;
|
|
|
|
setUp(() {
|
|
fileSystem = MemoryFileSystem(style: FileSystemStyle.windows);
|
|
mockPlatform = MockPlatform(isWindows: true);
|
|
packagesDir = fileSystem.currentDirectory.childDirectory('packages');
|
|
createPackagesDirectory(parentDir: packagesDir.parent);
|
|
processRunner = RecordingProcessRunner();
|
|
final PubspecCheckCommand command = PubspecCheckCommand(
|
|
packagesDir,
|
|
processRunner: processRunner,
|
|
platform: mockPlatform,
|
|
);
|
|
|
|
runner = CommandRunner<void>(
|
|
'pubspec_check_command', 'Test for pubspec_check_command');
|
|
runner.addCommand(command);
|
|
});
|
|
|
|
test('repository check works', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('package', packagesDir, examples: <String>[]);
|
|
|
|
package.pubspecFile.writeAsStringSync('''
|
|
${_headerSection('package')}
|
|
${_environmentSection()}
|
|
${_dependenciesSection()}
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['pubspec-check']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Running for package...'),
|
|
contains('No issues found!'),
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
}
|