mirror of
https://github.com/flutter/packages.git
synced 2025-06-04 10:18:12 +08:00

The analysis options have gotten behind; this re-syncs to the current state of flutter/flutter. For options that are non-trivial to enable, either because they are non-trivial to fix, or touch a very large number of files, they are locally disabled with clear "LOCAL CHANGE" markers so that it's obvious where we are out of sync. For options that are simple to resolve, they are enabled in the PR. Part of https://github.com/flutter/flutter/issues/76229
955 lines
28 KiB
Dart
955 lines
28 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? 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',
|
|
'main',
|
|
'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 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 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!'),
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
}
|