Show outdated and discontinued in listing in get (#2844)
For a pubspec.yaml
```
name: blah
environment:
sdk: '>=2.7.0 <3.0.0'
dependencies:
package_config:
_dummy_pkg: <0.0.4
retry: ^2.0.0
```
Will now have this output for pub get (the second run highlights outdated and discontinued packages):
```
> dart pub get
Resolving dependencies... (1.0s)
+ _dummy_pkg 0.0.3 (discontinued)
+ charcode 1.1.3
+ package_config 1.9.3
+ path 1.7.0
+ retry 2.0.0 (3.0.1 available)
Changed 5 dependencies!
```
Second invocation (with a pubspec.lock in place):
```
> dart pub get
Resolving dependencies...
_dummy_pkg 0.0.3 (discontinued)
retry 2.0.0 (3.0.1 available)
Got dependencies!
```
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 69a2b33..55a56b3 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -427,8 +427,9 @@
/// This automatically downloads the package to the system-wide cache as well
/// if it requires network access to retrieve (specifically, if the package's
/// source is a [CachedSource]).
- Future _get(PackageId id) {
- return http.withDependencyType(root.dependencyType(id.name), () async {
+ Future<void> _get(PackageId id) async {
+ return await http.withDependencyType(root.dependencyType(id.name),
+ () async {
if (id.isRoot) return;
var source = cache.source(id.source);
diff --git a/lib/src/solver.dart b/lib/src/solver.dart
index 18b4174..e88796a 100644
--- a/lib/src/solver.dart
+++ b/lib/src/solver.dart
@@ -24,8 +24,8 @@
/// If [unlock] is given, then only packages listed in [unlock] will be unlocked
/// from [lockFile]. This is useful for a upgrading specific packages only.
///
-/// If [unlock] is empty [SolveType.GET] interprets this as lock everything,
-/// while [SolveType.UPGRADE] and [SolveType.DOWNGRADE] interprets an empty
+/// If [unlock] is empty [SolveType.get] interprets this as lock everything,
+/// while [SolveType.upgrade] and [SolveType.downgrade] interprets an empty
/// [unlock] as unlock everything.
Future<SolveResult> resolveVersions(
SolveType type,
@@ -55,8 +55,8 @@
/// If [unlock] is given, only packages listed in [unlock] will be unlocked
/// from [lockFile]. This is useful for a upgrading specific packages only.
///
-/// If [unlock] is empty [SolveType.GET] interprets this as lock everything,
-/// while [SolveType.UPGRADE] and [SolveType.DOWNGRADE] interprets an empty
+/// If [unlock] is empty [SolveType.get] interprets this as lock everything,
+/// while [SolveType.upgrade] and [SolveType.downgrade] interprets an empty
/// [unlock] as unlock everything.
Future<SolveResult> tryResolveVersions(
SolveType type,
diff --git a/lib/src/solver/package_lister.dart b/lib/src/solver/package_lister.dart
index 087c958..5851e0e 100644
--- a/lib/src/solver/package_lister.dart
+++ b/lib/src/solver/package_lister.dart
@@ -427,7 +427,7 @@
_RootSource(this._package);
@override
- Future<List<PackageId>> getVersions(PackageRef ref) {
+ Future<List<PackageId>> getVersions(PackageRef ref, {Duration maxAge}) {
assert(ref.isRoot);
return Future.value([PackageId.root(_package)]);
}
@@ -443,7 +443,8 @@
@override
SystemCache get systemCache => throw _unsupported;
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) => throw _unsupported;
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) =>
+ throw _unsupported;
@override
Future<Pubspec> doDescribe(PackageId id) => throw _unsupported;
@override
diff --git a/lib/src/solver/report.dart b/lib/src/solver/report.dart
index 27c368f..39f005f 100644
--- a/lib/src/solver/report.dart
+++ b/lib/src/solver/report.dart
@@ -44,8 +44,8 @@
/// Displays a report of the results of the version resolution relative to
/// the previous lock file.
Future<void> show() async {
- _reportChanges();
- _reportOverrides();
+ await _reportChanges();
+ await _reportOverrides();
}
/// Displays a one-line message summarizing what changes were made (or would
@@ -95,15 +95,16 @@
/// Displays a report of all of the previous and current dependencies and
/// how they have changed.
- void _reportChanges() {
+ Future<void> _reportChanges() async {
_output.clear();
// Show the new set of dependencies ordered by name.
var names = _result.packages.map((id) => id.name).toList();
names.remove(_root.name);
names.sort();
- names.forEach(_reportPackage);
-
+ for (final name in names) {
+ await _reportPackage(name);
+ }
// Show any removed ones.
var removed = _previousLockFile.packages.keys.toSet();
removed.removeAll(names);
@@ -111,7 +112,7 @@
if (removed.isNotEmpty) {
_output.writeln('These packages are no longer being depended on:');
for (var name in ordered(removed)) {
- _reportPackage(name, alwaysShow: true);
+ await _reportPackage(name, alwaysShow: true);
}
}
@@ -119,46 +120,20 @@
}
/// Displays a warning about the overrides currently in effect.
- void _reportOverrides() {
+ Future<void> _reportOverrides() async {
_output.clear();
if (_root.dependencyOverrides.isNotEmpty) {
_output.writeln('Warning: You are using these overridden dependencies:');
for (var name in ordered(_root.dependencyOverrides.keys)) {
- _reportPackage(name, alwaysShow: true, highlightOverride: false);
+ await _reportPackage(name, alwaysShow: true, highlightOverride: false);
}
log.warning(_output);
}
}
- /// Displays a warning about any discontinued packages directly depended upon.
- Future<void> reportDiscontinued() async {
- final directDependencies = _result.packages
- .where((id) => _root.dependencyType(id.name) != DependencyType.none);
- final statuses = await Future.wait(
- directDependencies.map(
- (id) async => Pair(
- id,
- // We allow data to be up to 3 days old to not spend too much network
- // time for packages that were not unlocked.
- await _cache.source(id.source).status(id, Duration(days: 3)),
- ),
- ),
- );
- for (final statusPair in statuses) {
- final id = statusPair.first;
- final status = statusPair.last;
- if (statusPair.last.isDiscontinued ?? false) {
- final suffix = status.discontinuedReplacedBy == null
- ? ''
- : ' it has been replaced by package ${status.discontinuedReplacedBy}';
- log.warning('Package ${id.name} has been discontinued$suffix.');
- }
- }
- }
-
/// Displays a two-line message, number of outdated packages and an
/// instruction to run `pub outdated` if outdated packages are detected.
void reportOutdated() {
@@ -190,8 +165,8 @@
/// If [alwaysShow] is true, the package is reported even if it didn't change,
/// regardless of [_type]. If [highlightOverride] is true (or absent), writes
/// "(override)" next to overridden packages.
- void _reportPackage(String name,
- {bool alwaysShow = false, bool highlightOverride = true}) {
+ Future<void> _reportPackage(String name,
+ {bool alwaysShow = false, bool highlightOverride = true}) async {
var newId = _dependencies[name];
var oldId = _previousLockFile.packages[name];
var id = newId ?? oldId;
@@ -235,8 +210,46 @@
// Unchanged.
icon = ' ';
}
+ String message;
+ // See if there are any newer versions of the package that we were
+ // unable to upgrade to.
+ if (newId != null && _type != SolveType.DOWNGRADE) {
+ var versions = _result.availableVersions[newId.name];
- if (_type == SolveType.GET && !(alwaysShow || changed || addedOrRemoved)) {
+ var newerStable = false;
+ var newerUnstable = false;
+
+ for (var version in versions) {
+ if (version > newId.version) {
+ if (version.isPreRelease) {
+ newerUnstable = true;
+ } else {
+ newerStable = true;
+ }
+ }
+ }
+ final status =
+ await _cache.source(id.source).status(id, Duration(days: 3));
+ if (status.isDiscontinued) {
+ if (status.discontinuedReplacedBy == null) {
+ message = '(discontinued)';
+ } else {
+ message =
+ '(discontinued replaced by ${status.discontinuedReplacedBy})';
+ }
+ } else if (newerStable) {
+ // If there are newer stable versions, only show those.
+ message = '(${maxAll(versions, Version.prioritize)} available)';
+ } else if (
+ // Only show newer prereleases for versions where a prerelease is
+ // already chosen.
+ newId.version.isPreRelease && newerUnstable) {
+ message = '(${maxAll(versions)} available)';
+ }
+ }
+
+ if (_type == SolveType.GET &&
+ !(alwaysShow || changed || addedOrRemoved || message != null)) {
return;
}
@@ -257,37 +270,7 @@
_output.write(" ${log.magenta('(overridden)')}");
}
- // See if there are any newer versions of the package that we were
- // unable to upgrade to.
- if (newId != null && _type != SolveType.DOWNGRADE) {
- var versions = _result.availableVersions[newId.name];
-
- var newerStable = false;
- var newerUnstable = false;
-
- for (var version in versions) {
- if (version > newId.version) {
- if (version.isPreRelease) {
- newerUnstable = true;
- } else {
- newerStable = true;
- }
- }
- }
-
- // If there are newer stable versions, only show those.
- String message;
- if (newerStable) {
- message = '(${maxAll(versions, Version.prioritize)} available)';
- } else if (
- // Only show newer prereleases for versions where a prerelease is
- // already chosen.
- newId.version.isPreRelease && newerUnstable) {
- message = '(${maxAll(versions)} available)';
- }
-
- if (message != null) _output.write(' ${log.cyan(message)}');
- }
+ if (message != null) _output.write(' ${log.cyan(message)}');
_output.writeln();
}
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index 0f33833..5b1022b 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -108,7 +108,6 @@
final report =
SolveReport(type, _sources, _root, _previousLockFile, this, cache);
report.summarize(dryRun: dryRun);
- await report.reportDiscontinued();
if (type == SolveType.UPGRADE) {
report.reportOutdated();
}
diff --git a/lib/src/solver/version_solver.dart b/lib/src/solver/version_solver.dart
index 67d4fe0..10f2126 100644
--- a/lib/src/solver/version_solver.dart
+++ b/lib/src/solver/version_solver.dart
@@ -6,6 +6,7 @@
import 'dart:math' as math;
import 'package:collection/collection.dart';
+import 'package:pub/src/source/hosted.dart';
import 'package:pub_semver/pub_semver.dart';
import '../exceptions.dart';
@@ -414,7 +415,7 @@
_lockFile,
decisions,
pubspecs,
- _getAvailableVersions(decisions),
+ await _getAvailableVersions(decisions),
_solution.attemptedSolutions);
}
@@ -424,17 +425,24 @@
/// The version list may not always be complete. If the package is the root
/// package, or if it's a package that we didn't unlock while solving because
/// we weren't trying to upgrade it, we will just know the current version.
- Map<String, List<Version>> _getAvailableVersions(List<PackageId> packages) {
+ Future<Map<String, List<Version>>> _getAvailableVersions(
+ List<PackageId> packages) async {
var availableVersions = <String, List<Version>>{};
for (var package in packages) {
var cached = _packageListers[package.toRef()]?.cachedVersions;
- // If the version list was never requested, just use the one known
- // version.
- var versions = cached == null
- ? [package.version]
- : cached.map((id) => id.version).toList();
+ // If the version list was never requested, use versions from cached
+ // version listings if the package is "hosted".
+ // TODO(sigurdm): This has a smell. The Git source should have a
+ // reasonable behavior here (we should be able to call getVersions in a
+ // way that doesn't fetch.
+ var ids = cached ??
+ (package.source is HostedSource
+ ? (await _systemCache
+ .source(package.source)
+ .getVersions(package.toRef(), maxAge: Duration(days: 3)))
+ : [package]);
- availableVersions[package.name] = versions;
+ availableVersions[package.name] = ids.map((id) => id.version).toList();
}
return availableVersions;
diff --git a/lib/src/source.dart b/lib/src/source.dart
index e82075c..fcfe2fe 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -157,7 +157,9 @@
/// uses [describe] to get that version.
///
/// Sources should not override this. Instead, they implement [doGetVersions].
- Future<List<PackageId>> getVersions(PackageRef ref) {
+ ///
+ /// If [maxAge] is given answers can be taken from cache - up to that age old.
+ Future<List<PackageId>> getVersions(PackageRef ref, {Duration maxAge}) {
if (ref.isRoot) {
throw ArgumentError('Cannot get versions for the root package.');
}
@@ -165,7 +167,7 @@
throw ArgumentError('Package $ref does not use source ${source.name}.');
}
- return doGetVersions(ref);
+ return doGetVersions(ref, maxAge);
}
/// Get the IDs of all versions that match [ref].
@@ -180,7 +182,7 @@
///
/// This method is effectively protected: subclasses must implement it, but
/// external code should not call this. Instead, call [getVersions].
- Future<List<PackageId>> doGetVersions(PackageRef ref);
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge);
/// A cache of pubspecs described by [describe].
final _pubspecs = <PackageId, Pubspec>{};
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index cc7d18a..3a3e18d 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -225,7 +225,7 @@
}
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) async {
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
return await _pool.withResource(() async {
await _ensureRepoCache(ref);
var path = _repoCachePath(ref);
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index d6baab8..a6a4c17 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -339,9 +339,14 @@
/// Downloads a list of all versions of a package that are available from the
/// site.
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) async {
- final versions = await _scheduler.schedule(ref);
- return versions.keys.toList();
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
+ Map<PackageId, _VersionInfo> versionListing;
+ if (maxAge != null) {
+ // Do we have a cached version response on disk?
+ versionListing ??= await _cachedVersionListingResponse(ref, maxAge);
+ }
+ versionListing ??= await _scheduler.schedule(ref);
+ return versionListing.keys.toList();
}
/// Parses [description] into its server and package name components, then
@@ -647,7 +652,7 @@
/// Gets the list of all versions of [ref] that are in the system cache.
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) async {
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
var parsed = source._parseDescription(ref.description);
var server = parsed.last;
log.io('Finding versions of ${ref.name} in '
@@ -694,6 +699,9 @@
final versionListing =
await _cachedVersionListingResponse(id.toRef(), maxAge);
+ if (versionListing == null) {
+ return PackageStatus();
+ }
final listing = versionListing[id];
// If we don't have the specific version we return the empty response.
//
diff --git a/lib/src/source/path.dart b/lib/src/source/path.dart
index 1d06496..a84b92f 100644
--- a/lib/src/source/path.dart
+++ b/lib/src/source/path.dart
@@ -163,7 +163,7 @@
BoundPathSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) async {
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
// There's only one package ID for a given path. We just need to find the
// version.
var pubspec = _loadPubspec(ref);
diff --git a/lib/src/source/sdk.dart b/lib/src/source/sdk.dart
index ec201f2..c2d4edf 100644
--- a/lib/src/source/sdk.dart
+++ b/lib/src/source/sdk.dart
@@ -70,7 +70,7 @@
BoundSdkSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) async {
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
var pubspec = _loadPubspec(ref);
var id = PackageId(ref.name, source, pubspec.version, ref.description);
memoizePubspec(id, pubspec);
diff --git a/lib/src/source/unknown.dart b/lib/src/source/unknown.dart
index a9ae1f2..53b9a42 100644
--- a/lib/src/source/unknown.dart
+++ b/lib/src/source/unknown.dart
@@ -61,7 +61,7 @@
_BoundUnknownSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref) =>
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) =>
throw UnsupportedError(
"Cannot get package versions from unknown source '${source.name}'.");
diff --git a/test/get/hosted/warn_about_discontinued_test.dart b/test/get/hosted/warn_about_discontinued_test.dart
index 6e4764f..2b0afc5 100644
--- a/test/get/hosted/warn_about_discontinued_test.dart
+++ b/test/get/hosted/warn_about_discontinued_test.dart
@@ -34,7 +34,12 @@
deleteEntry(fooVersionsCache);
deleteEntry(transitiveVersionsCache);
// We warn only about the direct dependency here:
- await pubGet(warning: 'Package foo has been discontinued.');
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued)
+ transitive 1.0.0 (discontinued)
+Got dependencies!
+''');
expect(fileExists(fooVersionsCache), isTrue);
final c = json.decode(readTextFile(fooVersionsCache));
// Make the cache artificially old.
@@ -43,28 +48,39 @@
writeTextFile(fooVersionsCache, json.encode(c));
globalPackageServer
.add((builder) => builder.discontinue('foo', replacementText: 'bar'));
- await pubGet(
- warning:
- 'Package foo has been discontinued it has been replaced by package bar.');
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+ transitive 1.0.0 (discontinued)
+Got dependencies!''');
final c2 = json.decode(readTextFile(fooVersionsCache));
// Make a bad cached value to test that responses are actually from cache.
c2['isDiscontinued'] = false;
writeTextFile(fooVersionsCache, json.encode(c2));
- await pubGet(warning: isEmpty);
+ await pubGet(output: '''
+Resolving dependencies...
+ transitive 1.0.0 (discontinued)
+Got dependencies!''');
// Repairing the cache should reset the package listing caches.
await runPub(args: ['cache', 'repair']);
- await pubGet(
- warning:
- 'Package foo has been discontinued it has been replaced by package bar.');
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+ transitive 1.0.0 (discontinued)
+Got dependencies!''');
// Test that --offline won't try to access the server for retrieving the
// status.
await serveErrors();
- await pubGet(
- args: ['--offline'],
- warning:
- 'Package foo has been discontinued it has been replaced by package bar.');
+ await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+ transitive 1.0.0 (discontinued)
+Got dependencies!''');
deleteEntry(fooVersionsCache);
deleteEntry(transitiveVersionsCache);
- await pubGet(args: ['--offline']);
+ await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+Got dependencies!
+''');
});
}
diff --git a/test/list_package_dirs/lists_dependency_directories_test.dart b/test/list_package_dirs/lists_dependency_directories_test.dart
index a9862bb..20fcf46 100644
--- a/test/list_package_dirs/lists_dependency_directories_test.dart
+++ b/test/list_package_dirs/lists_dependency_directories_test.dart
@@ -26,12 +26,11 @@
await pubGet();
- await
- // Note: Using canonicalize here because pub gets the path to the
- // entrypoint package from the working directory, which has had symlinks
- // resolve. On Mac, "/tmp" is actually a symlink to "/private/tmp", so we
- // need to accommodate that.
- await runPub(args: [
+ // Note: Using canonicalize here because pub gets the path to the
+ // entrypoint package from the working directory, which has had symlinks
+ // resolve. On Mac, "/tmp" is actually a symlink to "/private/tmp", so we
+ // need to accommodate that.
+ await runPub(args: [
'list-package-dirs',
'--format=json'
], outputJson: {
diff --git a/test/test_pub.dart b/test/test_pub.dart
index beff0ce..0e8bbd4 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -123,7 +123,7 @@
///
/// If [exitCode] is given, expects the command to exit with that code.
// TODO(rnystrom): Clean up other tests to call this when possible.
-Future pubCommand(RunCommand command,
+Future<void> pubCommand(RunCommand command,
{Iterable<String> args,
output,
error,
@@ -155,14 +155,14 @@
environment: environment);
}
-Future pubAdd(
+Future<void> pubAdd(
{Iterable<String> args,
output,
error,
warning,
int exitCode,
- Map<String, String> environment}) =>
- pubCommand(RunCommand.add,
+ Map<String, String> environment}) async =>
+ await pubCommand(RunCommand.add,
args: args,
output: output,
error: error,
@@ -170,14 +170,14 @@
exitCode: exitCode,
environment: environment);
-Future pubGet(
+Future<void> pubGet(
{Iterable<String> args,
output,
error,
warning,
int exitCode,
- Map<String, String> environment}) =>
- pubCommand(RunCommand.get,
+ Map<String, String> environment}) async =>
+ await pubCommand(RunCommand.get,
args: args,
output: output,
error: error,
@@ -185,14 +185,14 @@
exitCode: exitCode,
environment: environment);
-Future pubUpgrade(
+Future<void> pubUpgrade(
{Iterable<String> args,
output,
error,
warning,
int exitCode,
- Map<String, String> environment}) =>
- pubCommand(RunCommand.upgrade,
+ Map<String, String> environment}) async =>
+ await pubCommand(RunCommand.upgrade,
args: args,
output: output,
error: error,
@@ -200,14 +200,14 @@
exitCode: exitCode,
environment: environment);
-Future pubDowngrade(
+Future<void> pubDowngrade(
{Iterable<String> args,
output,
error,
warning,
int exitCode,
- Map<String, String> environment}) =>
- pubCommand(RunCommand.downgrade,
+ Map<String, String> environment}) async =>
+ await pubCommand(RunCommand.downgrade,
args: args,
output: output,
error: error,
@@ -215,14 +215,14 @@
exitCode: exitCode,
environment: environment);
-Future pubRemove(
+Future<void> pubRemove(
{Iterable<String> args,
output,
error,
warning,
int exitCode,
- Map<String, String> environment}) =>
- pubCommand(RunCommand.remove,
+ Map<String, String> environment}) async =>
+ await pubCommand(RunCommand.remove,
args: args,
output: output,
error: error,
@@ -295,7 +295,7 @@
///
/// If [environment] is given, any keys in it will override the environment
/// variables passed to the spawned process.
-Future runPub(
+Future<void> runPub(
{List<String> args,
output,
error,
@@ -349,7 +349,7 @@
///
/// Ensures that the right output is shown and then enters "y" to confirm the
/// upload.
-Future confirmPublish(TestProcess pub) async {
+Future<void> confirmPublish(TestProcess pub) async {
// TODO(rnystrom): This is overly specific and inflexible regarding different
// test packages. Should validate this a little more loosely.
await expectLater(
@@ -577,7 +577,7 @@
///
/// [hosted] is a list of package names to version strings for dependencies on
/// hosted packages.
-Future createLockFile(String package,
+Future<void> createLockFile(String package,
{Iterable<String> sandbox, Map<String, String> hosted}) async {
var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
@@ -592,7 +592,7 @@
/// Like [createLockFile], but creates only a `.packages` file without a
/// lockfile.
-Future createPackagesFile(String package,
+Future<void> createPackagesFile(String package,
{Iterable<String> sandbox, Map<String, String> hosted}) async {
var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
var lockFile =
diff --git a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
index ccafebc..7a232d0 100644
--- a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
+++ b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
@@ -9,8 +9,8 @@
void main() {
test(
- 'does not show how many newer versions are available for '
- 'packages that are locked and not being upgraded', () async {
+ 'Shows newer versions available for packages that are locked and not being upgraded',
+ () async {
await servePackages((builder) {
builder.serve('not_upgraded', '1.0.0');
builder.serve('not_upgraded', '2.0.0');
@@ -31,7 +31,7 @@
// Only upgrade "upgraded".
await pubUpgrade(args: ['upgraded'], output: RegExp(r'''
Resolving dependencies\.\.\..*
- not_upgraded 1\.0\.0
+ not_upgraded 1\.0\.0 \(2\.0\.0 available\)
. upgraded 2\.0\.0 \(was 1\.0\.0\)
''', multiLine: true), environment: {'PUB_ALLOW_PRERELEASE_SDK': 'false'});
});