| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file | |
| // 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. | |
| @TestOn('vm') | |
| library; | |
| import 'dart:convert'; | |
| import 'dart:io'; | |
| import 'package:pub/src/io.dart'; | |
| import 'package:pub/src/path.dart'; | |
| import 'package:pub_semver/pub_semver.dart'; | |
| import 'package:shelf/shelf.dart' as shelf; | |
| import 'package:test/test.dart'; | |
| import 'package:yaml/yaml.dart'; | |
| import 'package:yaml_edit/yaml_edit.dart'; | |
| import '../descriptor.dart' as d; | |
| import '../descriptor.dart'; | |
| import '../golden_file.dart'; | |
| import '../test_pub.dart'; | |
| void manifestAndLockfile(GoldenTestContext context, List<String> workspace) { | |
| String catFile(String filename) { | |
| final path = p.join(d.sandbox, appPath, filename); | |
| final normalizedFilename = p.posix.joinAll(p.split(p.normalize(filename))); | |
| if (File(path).existsSync()) { | |
| final contents = File(path).readAsLinesSync().map(filterUnstableText); | |
| return ''' | |
| \$ cat $normalizedFilename | |
| ${contents.join('\n')}'''; | |
| } else { | |
| return ''' | |
| \$ cat $normalizedFilename | |
| No such file $normalizedFilename.'''; | |
| } | |
| } | |
| context.expectNextSection(''' | |
| ${workspace.map((path) => catFile(p.join(path, 'pubspec.yaml'))).join('\n')} | |
| ${catFile('pubspec.lock')} | |
| '''); | |
| } | |
| late final String snapshot; | |
| extension on GoldenTestContext { | |
| /// Returns the stdout. | |
| Future<String> runDependencyServices( | |
| List<String> args, { | |
| String stdin = '', | |
| Map<String, String>? environment, | |
| }) async { | |
| final buffer = StringBuffer(); | |
| buffer.writeln('## Section ${args.join(' ')}'); | |
| final process = await Process.start( | |
| Platform.resolvedExecutable, | |
| ['--enable-asserts', snapshot, '--verbose', ...args], | |
| environment: { | |
| ...getPubTestEnvironment(), | |
| '_PUB_TEST_DEFAULT_HOSTED_URL': globalServer.url, | |
| ...?environment, | |
| }, | |
| workingDirectory: p.join(d.sandbox, appPath), | |
| ); | |
| process.stdin.write(stdin); | |
| await process.stdin.flush(); | |
| await process.stdin.close(); | |
| final outLines = outputLines(process.stdout); | |
| final errLines = outputLines(process.stderr); | |
| final exitCode = await process.exitCode; | |
| final pipe = ' echo ${filterUnstableText(escapeShellArgument(stdin))} |'; | |
| final argString = args.map(escapeShellArgument).join(' '); | |
| buffer.writeln( | |
| [ | |
| '\$$pipe dependency_services $argString', | |
| ...await outLines, | |
| ...(await errLines).map((e) => '[STDERR] $e'), | |
| if (exitCode != 0) '[EXIT CODE] $exitCode', | |
| ].join('\n'), | |
| ); | |
| expectNextSection(buffer.toString()); | |
| return (await outLines).join('\n'); | |
| } | |
| } | |
| Future<Iterable<String>> outputLines(Stream<List<int>> stream) async { | |
| final s = await utf8.decodeStream(stream); | |
| if (s.isEmpty) return []; | |
| return s.split('\n').map(filterUnstableText); | |
| } | |
| Future<void> _listReportApply( | |
| GoldenTestContext context, | |
| List<_PackageVersion> upgrades, { | |
| List<String> workspace = const ['.'], | |
| void Function(Map)? reportAssertions, | |
| Map<String, String>? environment, | |
| }) async { | |
| manifestAndLockfile(context, workspace); | |
| await context.runDependencyServices(['list'], environment: environment); | |
| final report = await context.runDependencyServices([ | |
| 'report', | |
| ], environment: environment); | |
| if (reportAssertions != null) { | |
| reportAssertions(json.decode(report) as Map); | |
| } | |
| final input = json.encode({'dependencyChanges': upgrades}); | |
| await context.runDependencyServices( | |
| ['apply'], | |
| stdin: input, | |
| environment: environment, | |
| ); | |
| manifestAndLockfile(context, workspace); | |
| } | |
| Future<void> _reportWithForbidden( | |
| GoldenTestContext context, | |
| Map<String, List<String>> disallowedVersions, { | |
| void Function(Map)? resultAssertions, | |
| String? targetPackage, | |
| }) async { | |
| manifestAndLockfile(context, ['.']); | |
| final input = json.encode({ | |
| 'target': targetPackage, | |
| 'disallowed': [ | |
| for (final e in disallowedVersions.entries) | |
| { | |
| 'name': e.key, | |
| 'url': globalServer.url, | |
| 'versions': e.value.map((d) => {'range': d}).toList(), | |
| }, | |
| ], | |
| }); | |
| final report = await context.runDependencyServices(['report'], stdin: input); | |
| if (resultAssertions != null) { | |
| resultAssertions(json.decode(report) as Map); | |
| } | |
| // await context.runDependencyServices(['apply'], stdin: input); | |
| manifestAndLockfile(context, ['.']); | |
| } | |
| Future<void> main() async { | |
| setUpAll(() async { | |
| final tempDir = Directory.systemTemp.createTempSync(); | |
| snapshot = p.join(tempDir.path, 'dependency_services.dart.snapshot'); | |
| final r = Process.runSync(Platform.resolvedExecutable, [ | |
| '--snapshot=$snapshot', | |
| p.join('bin', 'dependency_services.dart'), | |
| ]); | |
| expect(r.exitCode, 0, reason: r.stderr as String); | |
| }); | |
| tearDownAll(() { | |
| File(snapshot).parent.deleteSync(recursive: true); | |
| }); | |
| testWithGolden('Removing transitive', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'}) | |
| ..serve('foo', '2.2.3') | |
| ..serve('transitive', '1.0.0') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| server.dontAllowDownloads(); | |
| await _listReportApply( | |
| context, | |
| [_PackageVersion('foo', '2.2.3'), _PackageVersion('transitive', null)], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'singleBreaking', 'foo'), '2.2.3'); | |
| expect(findChangeVersion(report, 'singleBreaking', 'transitive'), null); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Ignoring version', (context) async { | |
| final server = await servePackages(); | |
| server.serve('foo', '1.0.0'); | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| server.serve('foo', '1.0.1'); // should get this. | |
| server.serve('foo', '1.0.2'); // ignored | |
| server.serve('foo', '1.0.3', deps: {'transitive': '1.0.0'}); | |
| server.serve('transitive', '1.0.0'); // ignored | |
| await _reportWithForbidden( | |
| context, | |
| { | |
| 'foo': ['1.0.2'], | |
| 'transitive': ['1.0.0'], | |
| }, | |
| resultAssertions: (report) { | |
| expect(findChangeVersion(report, 'compatible', 'foo'), '1.0.1'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('No pubspec.lock', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'}) | |
| ..serve('foo', '2.2.3') | |
| ..serve('transitive', '1.0.0') | |
| ..serveContentHashes = true; | |
| await d.git('bar.git', [d.libPubspec('bar', '1.0.0')]).create(); | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': { | |
| 'foo': '^1.0.0', | |
| 'bar': { | |
| 'git': {'url': '../bar.git'}, | |
| }, | |
| }, | |
| }), | |
| ]).create(); | |
| server.dontAllowDownloads(); | |
| await _listReportApply(context, [ | |
| _PackageVersion('foo', '2.2.3'), | |
| _PackageVersion('transitive', null), | |
| ]); | |
| }); | |
| testWithGolden('Compatible', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3') | |
| ..serve('foo', '2.2.3') | |
| ..serve('bar', '1.2.3') | |
| ..serve('bar', '2.2.3') | |
| ..serve('boo', '1.2.3') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0', 'bar': '^1.0.0', 'boo': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| server.serve('foo', '1.2.4'); | |
| server.serve('boo', '1.2.4'); | |
| server.dontAllowDownloads(); | |
| await _listReportApply( | |
| context, | |
| [_PackageVersion('foo', '1.2.4')], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'compatible', 'foo'), '1.2.4'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Preserves no content-hashes', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3') | |
| ..serve('foo', '2.2.3') | |
| ..serve('bar', '1.2.3') | |
| ..serve('bar', '2.2.3') | |
| ..serve('boo', '1.2.3') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0', 'bar': '^1.0.0', 'boo': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| final lockFile = File(path(p.join(appPath, 'pubspec.lock'))); | |
| final lockFileYaml = YamlEditor(lockFile.readAsStringSync()); | |
| for (final p in (lockFileYaml.parseAt(['packages']) as YamlMap).entries) { | |
| lockFileYaml.remove(['packages', p.key, 'description', 'sha256']); | |
| } | |
| lockFile.writeAsStringSync(lockFileYaml.toString()); | |
| server.serve('foo', '1.2.4'); | |
| server.serve('boo', '1.2.4'); | |
| server.dontAllowDownloads(); | |
| await _listReportApply(context, [_PackageVersion('foo', '1.2.4')]); | |
| }); | |
| testWithGolden('Preserves pub.dartlang.org as hosted url', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve(r'foo', '1.2.3') | |
| ..serve(r'bar', '1.2.3') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0', 'bar': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| final lockFile = File(path(p.join(appPath, 'pubspec.lock'))); | |
| final lockFileYaml = YamlEditor(lockFile.readAsStringSync()); | |
| for (final p in (lockFileYaml.parseAt(['packages']).value as Map).entries) { | |
| lockFileYaml.update([ | |
| 'packages', | |
| p.key, | |
| 'description', | |
| 'url', | |
| ], 'https://pub.dartlang.org'); | |
| } | |
| lockFile.writeAsStringSync(lockFileYaml.toString()); | |
| server.serve('foo', '1.2.4'); | |
| server.serve('boo', '1.2.4'); | |
| await _listReportApply(context, [_PackageVersion('foo', '1.2.4')]); | |
| }); | |
| testWithGolden('Adding transitive', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3') | |
| ..serve('foo', '2.2.3', deps: {'transitive': '^1.0.0'}) | |
| ..serve('transitive', '1.0.0') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': {'foo': '^1.0.0'}, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| server.dontAllowDownloads(); | |
| await _listReportApply( | |
| context, | |
| [_PackageVersion('foo', '2.2.3'), _PackageVersion('transitive', '1.0.0')], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'singleBreaking', 'foo'), '2.2.3'); | |
| expect( | |
| findChangeVersion(report, 'singleBreaking', 'transitive'), | |
| '1.0.0', | |
| ); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('multibreaking', (context) async { | |
| final server = | |
| (await servePackages()) | |
| ..serve('foo', '1.0.0') | |
| ..serve('bar', '1.0.0') | |
| ..serve('baz', '1.0.0') | |
| ..serveContentHashes = true; | |
| await d.dir(appPath, [ | |
| d.pubspec({ | |
| 'name': 'app', | |
| 'dependencies': { | |
| 'foo': '^1.0.0', | |
| 'bar': '^1.0.0', | |
| // Pinned version. See that the widened constraint is correct. | |
| 'baz': '1.0.0', | |
| }, | |
| }), | |
| ]).create(); | |
| await pubGet(); | |
| server | |
| ..serve('foo', '1.5.0') // compatible | |
| ..serve('foo', '2.0.0') // single breaking | |
| ..serve('foo', '3.0.0', deps: {'bar': '^2.0.0'}) // multi breaking | |
| ..serve('foo', '3.0.1', deps: {'bar': '^2.0.0'}) | |
| ..serve('bar', '2.0.0', deps: {'foo': '^3.0.0'}) | |
| ..serve('baz', '1.1.0'); | |
| server.dontAllowDownloads(); | |
| await _listReportApply( | |
| context, | |
| [ | |
| _PackageVersion( | |
| 'foo', | |
| '3.0.1', | |
| constraint: VersionConstraint.parse('^3.0.0'), | |
| ), | |
| _PackageVersion('bar', '2.0.0'), | |
| ], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'multiBreaking', 'foo'), '3.0.1'); | |
| expect(findChangeVersion(report, 'multiBreaking', 'bar'), '2.0.0'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Relative paths are allowed', (context) async { | |
| // We cannot update path-dependencies, but they should be allowed. | |
| final server = await servePackages(); | |
| server.serve('foo', '1.0.0'); | |
| await d.dir('bar', [d.libPubspec('bar', '1.0.0')]).create(); | |
| await d | |
| .appDir( | |
| dependencies: { | |
| 'foo': '^1.0.0', | |
| 'bar': {'path': '../bar'}, | |
| }, | |
| ) | |
| .create(); | |
| await pubGet(); | |
| server.serve('foo', '2.0.0'); | |
| await _listReportApply( | |
| context, | |
| [ | |
| _PackageVersion( | |
| 'foo', | |
| '2.0.0', | |
| constraint: VersionConstraint.parse('^2.0.0'), | |
| ), | |
| ], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'multiBreaking', 'foo'), '2.0.0'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Can update a git package', (context) async { | |
| await servePackages(); | |
| await d.git('foo.git', [d.libPubspec('foo', '1.0.0')]).create(); | |
| await d.git('bar.git', [d.libPubspec('bar', '1.0.0')]).create(); | |
| await d | |
| .appDir( | |
| dependencies: { | |
| 'foo': { | |
| 'git': {'url': '../foo.git'}, | |
| }, | |
| 'bar': { | |
| // A git dependency with a version constraint. | |
| 'git': {'url': '../bar.git'}, | |
| 'version': '^1.0.0', | |
| }, | |
| }, | |
| ) | |
| .create(); | |
| await pubGet(); | |
| final secondVersion = d.git('foo.git', [d.libPubspec('foo', '2.0.0')]); | |
| await secondVersion.commit(); | |
| final newRef = await secondVersion.revParse('HEAD'); | |
| final barSecondVersion = d.git('bar.git', [d.libPubspec('bar', '2.0.0')]); | |
| await barSecondVersion.commit(); | |
| await _listReportApply( | |
| context, | |
| [_PackageVersion('foo', newRef)], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'multiBreaking', 'foo'), newRef); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Finds smallest possible upgrade', (context) async { | |
| final server = await servePackages(); | |
| server.serve('foo', '1.1.1'); // This version will be disallowed. | |
| await d.appDir(dependencies: {'foo': '^1.0.0'}).create(); | |
| await pubGet(); | |
| server.serve( | |
| 'foo', | |
| '1.0.0', | |
| ); // We don't want the downgrade to go below the current. | |
| server.serve( | |
| 'foo', | |
| '1.1.2', | |
| ); // This will also be disallowed, a minimal update should not find this. | |
| server.serve('foo', '1.1.3'); // We would like this to be the new version. | |
| server.serve('foo', '1.1.4'); // This version would not be a minimal update. | |
| await _reportWithForbidden( | |
| context, | |
| { | |
| 'foo': ['1.1.1', '1.1.2'], | |
| }, | |
| targetPackage: 'foo', | |
| resultAssertions: (r) { | |
| expect(findChangeVersion(r, 'smallestUpdate', 'foo'), '1.1.3'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden('Smallest possible upgrade can upgrade beyond breaking', ( | |
| context, | |
| ) async { | |
| final server = await servePackages(); | |
| server.serve('foo', '1.1.1'); // This version will be disallowed. | |
| await d.appDir(dependencies: {'foo': '^1.0.0'}).create(); | |
| await pubGet(); | |
| server.serve( | |
| 'foo', | |
| '2.0.0', | |
| ); // This will also be disallowed, a minimal update should not find this. | |
| server.serve('foo', '2.0.1'); // We would like this to be the new version. | |
| server.serve('foo', '2.0.2'); // This version would not be a minimal update. | |
| await _reportWithForbidden( | |
| context, | |
| { | |
| 'foo': ['1.1.1', '2.0.0'], | |
| }, | |
| targetPackage: 'foo', | |
| resultAssertions: (r) { | |
| expect(findChangeVersion(r, 'smallestUpdate', 'foo'), '2.0.1'); | |
| }, | |
| ); | |
| }); | |
| testWithGolden( | |
| 'Smallest possible upgrade can upgrade other packages if needed', | |
| (context) async { | |
| final server = await servePackages(); | |
| server.serve('bar', '1.0.0'); | |
| server.serve('bar', '2.0.0'); | |
| server.serve('bar', '2.2.0'); | |
| server.serve( | |
| 'foo', | |
| '1.1.1', | |
| deps: {'bar': '^1.0.0'}, | |
| ); // This version will be disallowed. | |
| await d.appDir(dependencies: {'foo': '^1.0.0', 'bar': '^1.0.0'}).create(); | |
| await pubGet(); | |
| server.serve( | |
| 'foo', | |
| '2.0.0', | |
| deps: {'bar': '^2.0.0'}, | |
| ); // This will also be disallowed, a minimal update should not find this. | |
| server.serve( | |
| 'foo', | |
| '2.0.1', | |
| deps: {'bar': '^2.0.0'}, | |
| ); // We would like this to be the new version. | |
| server.serve( | |
| 'foo', | |
| '2.0.2', | |
| deps: {'bar': '^2.0.0'}, | |
| ); // This version would not be a minimal update. | |
| await _reportWithForbidden( | |
| context, | |
| { | |
| 'foo': ['1.1.1', '2.0.0'], | |
| 'bar': ['2.0.0'], | |
| }, | |
| targetPackage: 'foo', | |
| resultAssertions: (r) { | |
| expect(findChangeVersion(r, 'smallestUpdate', 'foo'), '2.0.1'); | |
| expect(findChangeVersion(r, 'smallestUpdate', 'bar'), '2.2.0'); | |
| }, | |
| ); | |
| }, | |
| ); | |
| testWithGolden('can upgrade workspaces', (context) async { | |
| (await servePackages()) | |
| ..serve('foo', '1.2.3') | |
| ..serve('foo', '2.2.3', deps: {'transitive': '^1.0.0'}) | |
| ..serve('bar', '1.2.3') | |
| ..serve('bar', '2.2.3') | |
| ..serve('only_a', '1.0.0') | |
| ..serve('only_a', '2.0.0') | |
| ..serve('dev', '1.0.0') | |
| ..serve('dev', '2.0.0') | |
| ..serve('transitive', '1.0.0') | |
| ..serveContentHashes = true; | |
| await dir(appPath, [ | |
| libPubspec( | |
| 'myapp', | |
| '1.2.3', | |
| extras: { | |
| 'workspace': ['pkgs/a'], | |
| }, | |
| deps: {'foo': '^1.0.0', 'bar': '^1.0.0'}, | |
| sdk: '^3.5.0', | |
| ), | |
| dir('pkgs', [ | |
| dir('a', [ | |
| libPubspec( | |
| 'a', | |
| '1.1.1', | |
| deps: {'bar': '>=1.2.0 <1.5.0', 'only_a': '^1.0.0'}, | |
| devDeps: {'foo': '^1.2.0', 'dev': '^1.0.0'}, | |
| resolutionWorkspace: true, | |
| ), | |
| ]), | |
| ]), | |
| ]).create(); | |
| await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}); | |
| final result = await Process.run( | |
| Platform.resolvedExecutable, | |
| [snapshot, 'list'], | |
| environment: { | |
| ...getPubTestEnvironment(), | |
| '_PUB_TEST_SDK_VERSION': '3.5.0', | |
| }, | |
| workingDirectory: p.join(d.sandbox, appPath, 'pkgs', 'a'), | |
| ); | |
| expect( | |
| result.stderr, | |
| contains('Only apply dependency_services to the root of the workspace.'), | |
| ); | |
| expect(result.exitCode, 1); | |
| await _listReportApply( | |
| context, | |
| [ | |
| _PackageVersion('foo', '2.2.3'), | |
| _PackageVersion('transitive', '1.0.0'), | |
| _PackageVersion( | |
| 'only_a', | |
| '2.0.0', | |
| constraint: VersionConstraint.parse('^2.0.0'), | |
| ), | |
| ], | |
| workspace: ['.', p.join('pkgs', 'a')], | |
| reportAssertions: (report) { | |
| expect(findChangeVersion(report, 'singleBreaking', 'foo'), '2.2.3'); | |
| expect( | |
| findChangeVersion(report, 'singleBreaking', 'transitive'), | |
| '1.0.0', | |
| ); | |
| }, | |
| environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, | |
| ); | |
| }); | |
| testWithGolden('applying with no changes is a no-op', (context) async { | |
| await servePackages(); | |
| await d | |
| .appDir( | |
| pubspec: { | |
| 'environment': {'sdk': '^3.10.0', 'flutter': '4.0.0'}, | |
| }, | |
| ) | |
| .create(); | |
| await d.dir('flutter', [flutterVersion('4.0.0')]).create(); | |
| await pubGet( | |
| environment: { | |
| '_PUB_TEST_SDK_VERSION': '3.10.0', | |
| 'FLUTTER_ROOT': d.path('flutter'), | |
| }, | |
| ); | |
| await context.runDependencyServices( | |
| ['apply'], | |
| stdin: jsonEncode({'dependencyChanges': <Object?>[]}), | |
| environment: { | |
| '_PUB_TEST_SDK_VERSION': '3.10.0', | |
| 'FLUTTER_ROOT': d.path('flutter'), | |
| }, | |
| ); | |
| final lockfile = | |
| loadYaml(File(path(p.join(appPath, 'pubspec.lock'))).readAsStringSync()) | |
| as Map; | |
| // Regression test for https://github.com/dependabot/dependabot-core/issues/13461 | |
| expect((lockfile['sdks'] as Map)['flutter'], '4.0.0'); | |
| }); | |
| } | |
| String? findChangeVersion(dynamic json, String updateType, String name) { | |
| return dig<String?>(json, [ | |
| 'dependencies', | |
| ('name', 'foo'), | |
| updateType, | |
| ('name', name), | |
| 'version', | |
| ]); | |
| } | |
| class _PackageVersion { | |
| String name; | |
| String? version; | |
| VersionConstraint? constraint; | |
| _PackageVersion(this.name, this.version, {this.constraint}); | |
| Map<String, Object?> toJson() => { | |
| 'name': name, | |
| 'version': version, | |
| if (constraint != null) 'constraint': constraint.toString(), | |
| }; | |
| } | |
| extension on PackageServer { | |
| ///Check that nothing is downloaded. | |
| void dontAllowDownloads() { | |
| // This testing logic is a bit fragile, if we change the pattern for pattern | |
| // for the download URL then this will pass silently. There isn't much we | |
| // can / should do about it. Just accept the limitations, and remove it if | |
| // the test becomes useless. | |
| handle(RegExp(r'/.+\.tar\.gz'), (request) { | |
| return shelf.Response.notFound( | |
| 'This test should not download archives! Requested ${request.url}', | |
| ); | |
| }); | |
| } | |
| } |