mirror of
https://github.com/flutter/packages.git
synced 2025-06-04 02:08:40 +08:00

Moves the check that README snippets using code excerpting are up to date to LUCI. Now that the check has been rewritten to be extremely fast, it's folded into the existing repo checks instead of being a separate task. Also adjusts the tooling slightly so that it logs the count of snippets checked, for auditability in CI, like the old version of the excerpt update tooling did. Part of https://github.com/flutter/flutter/issues/114373
456 lines
8.7 KiB
Dart
456 lines
8.7 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/update_excerpts_command.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'common/package_command_test.mocks.dart';
|
|
import 'mocks.dart';
|
|
import 'util.dart';
|
|
|
|
void runAllTests(MockPlatform platform) {
|
|
late FileSystem fileSystem;
|
|
late Directory packagesDir;
|
|
late CommandRunner<void> runner;
|
|
|
|
setUp(() {
|
|
fileSystem = MemoryFileSystem(
|
|
style: platform.isWindows
|
|
? FileSystemStyle.windows
|
|
: FileSystemStyle.posix);
|
|
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
|
|
runner = CommandRunner<void>('', '')
|
|
..addCommand(UpdateExcerptsCommand(
|
|
packagesDir,
|
|
platform: platform,
|
|
processRunner: RecordingProcessRunner(),
|
|
gitDir: MockGitDir(),
|
|
));
|
|
});
|
|
|
|
Future<void> testInjection(String before, String source, String after,
|
|
{bool failOnChange = false}) async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
package.readmeFile.writeAsStringSync(before);
|
|
package.directory.childFile('main.dart').writeAsStringSync(source);
|
|
Object? errorObject;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner,
|
|
<String>[
|
|
'update-excerpts',
|
|
if (failOnChange) '--fail-on-change',
|
|
],
|
|
errorHandler: (Object error) {
|
|
errorObject = error;
|
|
},
|
|
);
|
|
if (errorObject != null) {
|
|
fail('Failed: $errorObject\n\nOutput from excerpt command:\n$output');
|
|
}
|
|
expect(package.readmeFile.readAsStringSync(), after);
|
|
}
|
|
|
|
test('succeeds when nothing has changed', () async {
|
|
const String readme = '''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A B C
|
|
```
|
|
''';
|
|
const String source = '''
|
|
FAIL
|
|
// #docregion SomeSection
|
|
A B C
|
|
// #enddocregion SomeSection
|
|
FAIL
|
|
''';
|
|
await testInjection(readme, source, readme);
|
|
});
|
|
|
|
test('fails if example injection fails', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
package.readmeFile.writeAsStringSync('''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (UnknownSection)"?>
|
|
```dart
|
|
A B C
|
|
```
|
|
''');
|
|
package.directory.childFile('main.dart').writeAsStringSync('''
|
|
FAIL
|
|
// #docregion SomeSection
|
|
A B C
|
|
// #enddocregion SomeSection
|
|
FAIL
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['update-excerpts'], errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Injecting excerpts failed:'),
|
|
contains(
|
|
'main.dart: did not find a "// #docregion UnknownSection" pragma'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
test('updates files', () async {
|
|
await testInjection(
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
X Y Z
|
|
```
|
|
''',
|
|
'''
|
|
FAIL
|
|
// #docregion SomeSection
|
|
A B C
|
|
// #enddocregion SomeSection
|
|
FAIL
|
|
''',
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A B C
|
|
```
|
|
''',
|
|
);
|
|
});
|
|
|
|
test('fails if READMEs are changed with --fail-on-change', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
package.readmeFile.writeAsStringSync('''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
X Y Z
|
|
```
|
|
''');
|
|
package.directory.childFile('main.dart').writeAsStringSync('''
|
|
FAIL
|
|
// #docregion SomeSection
|
|
A B C
|
|
// #enddocregion SomeSection
|
|
FAIL
|
|
''');
|
|
|
|
Error? commandError;
|
|
final List<String> output = await runCapturingPrint(
|
|
runner, <String>['update-excerpts', '--fail-on-change'],
|
|
errorHandler: (Error e) {
|
|
commandError = e;
|
|
});
|
|
|
|
expect(commandError, isA<ToolExit>());
|
|
expect(
|
|
output.join('\n'),
|
|
contains('The following files have out of date excerpts:'),
|
|
);
|
|
});
|
|
|
|
test('does not fail if READMEs are not changed with --fail-on-change',
|
|
() async {
|
|
const String readme = '''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (aa)"?>
|
|
```dart
|
|
A
|
|
```
|
|
<?code-excerpt "main.dart (bb)"?>
|
|
```dart
|
|
B
|
|
```
|
|
''';
|
|
await testInjection(
|
|
readme,
|
|
'''
|
|
// #docregion aa
|
|
A
|
|
// #enddocregion aa
|
|
// #docregion bb
|
|
B
|
|
// #enddocregion bb
|
|
''',
|
|
readme,
|
|
failOnChange: true,
|
|
);
|
|
});
|
|
|
|
test('indents the plaster', () async {
|
|
await testInjection(
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
```
|
|
''',
|
|
'''
|
|
// #docregion SomeSection
|
|
A
|
|
// #enddocregion SomeSection
|
|
// #docregion SomeSection
|
|
B
|
|
// #enddocregion SomeSection
|
|
''',
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A
|
|
// ···
|
|
B
|
|
```
|
|
''',
|
|
);
|
|
});
|
|
|
|
test('does not unindent blocks if plaster will not unindent', () async {
|
|
await testInjection(
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
```
|
|
''',
|
|
'''
|
|
// #docregion SomeSection
|
|
A
|
|
// #enddocregion SomeSection
|
|
// #docregion SomeSection
|
|
B
|
|
// #enddocregion SomeSection
|
|
''',
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A
|
|
// ···
|
|
B
|
|
```
|
|
''',
|
|
);
|
|
});
|
|
|
|
test('unindents blocks', () async {
|
|
await testInjection(
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
```
|
|
''',
|
|
'''
|
|
// #docregion SomeSection
|
|
A
|
|
// #enddocregion SomeSection
|
|
// #docregion SomeSection
|
|
B
|
|
// #enddocregion SomeSection
|
|
''',
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A
|
|
// ···
|
|
B
|
|
```
|
|
''',
|
|
);
|
|
});
|
|
|
|
test('unindents blocks and plaster', () async {
|
|
await testInjection(
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
```
|
|
''',
|
|
'''
|
|
// #docregion SomeSection
|
|
A
|
|
// #enddocregion SomeSection
|
|
// #docregion SomeSection
|
|
B
|
|
// #enddocregion SomeSection
|
|
''',
|
|
'''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A
|
|
// ···
|
|
B
|
|
```
|
|
''',
|
|
);
|
|
});
|
|
|
|
test('relative path bases', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
package.readmeFile.writeAsStringSync('''
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt "test/test/main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt path-base="test"?>
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt "../main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt path-base="/packages/a_package"?>
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
```
|
|
''');
|
|
package.directory.childFile('main.dart').writeAsStringSync('''
|
|
// #docregion a
|
|
X
|
|
// #enddocregion a
|
|
''');
|
|
package.directory.childDirectory('test').createSync();
|
|
package.directory
|
|
.childDirectory('test')
|
|
.childFile('main.dart')
|
|
.writeAsStringSync('''
|
|
// #docregion a
|
|
Y
|
|
// #enddocregion a
|
|
''');
|
|
package.directory
|
|
.childDirectory('test')
|
|
.childDirectory('test')
|
|
.createSync();
|
|
package.directory
|
|
.childDirectory('test')
|
|
.childDirectory('test')
|
|
.childFile('main.dart')
|
|
.writeAsStringSync('''
|
|
// #docregion a
|
|
Z
|
|
// #enddocregion a
|
|
''');
|
|
await runCapturingPrint(runner, <String>['update-excerpts']);
|
|
expect(package.readmeFile.readAsStringSync(), '''
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
X
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
Y
|
|
```
|
|
<?code-excerpt "test/test/main.dart (a)"?>
|
|
```dart
|
|
Z
|
|
```
|
|
<?code-excerpt path-base="test"?>
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
Y
|
|
```
|
|
<?code-excerpt "../main.dart (a)"?>
|
|
```dart
|
|
X
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
Z
|
|
```
|
|
<?code-excerpt path-base="/packages/a_package"?>
|
|
<?code-excerpt "main.dart (a)"?>
|
|
```dart
|
|
X
|
|
```
|
|
<?code-excerpt "test/main.dart (a)"?>
|
|
```dart
|
|
Y
|
|
```
|
|
''');
|
|
});
|
|
|
|
test('logs snippets checked', () async {
|
|
final RepositoryPackage package =
|
|
createFakePackage('a_package', packagesDir);
|
|
package.readmeFile.writeAsStringSync('''
|
|
Example:
|
|
|
|
<?code-excerpt "main.dart (SomeSection)"?>
|
|
```dart
|
|
A B C
|
|
```
|
|
''');
|
|
package.directory.childFile('main.dart').writeAsStringSync('''
|
|
FAIL
|
|
// #docregion SomeSection
|
|
A B C
|
|
// #enddocregion SomeSection
|
|
FAIL
|
|
''');
|
|
|
|
final List<String> output =
|
|
await runCapturingPrint(runner, <String>['update-excerpts']);
|
|
|
|
expect(
|
|
output,
|
|
containsAllInOrder(<Matcher>[
|
|
contains('Checked 1 snippet(s) in README.md.'),
|
|
]),
|
|
);
|
|
});
|
|
}
|
|
|
|
void main() {
|
|
runAllTests(MockPlatform());
|
|
runAllTests(MockPlatform(isWindows: true));
|
|
}
|