From 3fd127f642b27748da5c2438a88da8bc0a78c38e Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Mon, 2 Feb 2026 08:21:54 -0800 Subject: [PATCH] fix: replace Future.delayed with explicit timestamps in tests (#3497) --- .../test/src/artifact_manager_test.dart | 54 ++++++++++++++++--- .../src/platform/windows/windows_test.dart | 9 ++-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/packages/shorebird_cli/test/src/artifact_manager_test.dart b/packages/shorebird_cli/test/src/artifact_manager_test.dart index d245eefa..fdda28e8 100644 --- a/packages/shorebird_cli/test/src/artifact_manager_test.dart +++ b/packages/shorebird_cli/test/src/artifact_manager_test.dart @@ -597,7 +597,7 @@ void main() { late Directory oldArchiveDirectory; late Directory newArchiveDirectory; - setUp(() async { + setUp(() { oldArchiveDirectory = Directory( p.join( projectRoot.path, @@ -607,9 +607,6 @@ void main() { 'Runner.xcarchive', ), )..createSync(recursive: true); - // Wait to ensure the new archive directory is created after the old - // archive directory. - await Future.delayed(const Duration(milliseconds: 50)); newArchiveDirectory = Directory( p.join( projectRoot.path, @@ -619,6 +616,9 @@ void main() { 'Runner2.xcarchive', ), )..createSync(recursive: true); + // Set explicit modification times so newArchiveDirectory is newer. + _setDirectoryMtime(oldArchiveDirectory, DateTime(2024)); + _setDirectoryMtime(newArchiveDirectory, DateTime(2025)); }); test('selects the most recently updated xcarchive', () async { @@ -688,7 +688,7 @@ void main() { late Directory oldAppDirectory; late Directory newAppDirectory; - setUp(() async { + setUp(() { oldAppDirectory = Directory( p.join( projectRoot.path, @@ -700,9 +700,6 @@ void main() { 'Runner.app', ), )..createSync(recursive: true); - // Wait to ensure the new app directory is created after the old - // app directory. - await Future.delayed(const Duration(milliseconds: 50)); newAppDirectory = Directory( p.join( projectRoot.path, @@ -714,6 +711,9 @@ void main() { 'Runner2.app', ), )..createSync(recursive: true); + // Set explicit modification times so newAppDirectory is newer. + _setDirectoryMtime(oldAppDirectory, DateTime(2024)); + _setDirectoryMtime(newAppDirectory, DateTime(2025)); }); test('selects the most recently updated app', () async { @@ -1000,3 +1000,41 @@ void main() { }); }); } + +/// Sets the modification time of [directory] to [mtime]. +/// +/// Dart's [Directory] does not expose `setLastModifiedSync`, so we shell out +/// to platform-specific commands. +void _setDirectoryMtime(Directory directory, DateTime mtime) { + final ProcessResult result; + if (Platform.isWindows) { + final formatted = mtime.toIso8601String(); + result = Process.runSync('powershell', [ + '-Command', + "(Get-Item '${directory.path}').LastWriteTime = '$formatted'", + ]); + } else { + result = Process.runSync('touch', [ + '-t', + _toTouchTimestamp(mtime), + directory.path, + ]); + } + if (result.exitCode != 0) { + throw ProcessException( + 'Failed to set mtime', + [], + '${result.stderr}', + result.exitCode, + ); + } +} + +String _toTouchTimestamp(DateTime dt) { + final y = dt.year.toString().padLeft(4, '0'); + final m = dt.month.toString().padLeft(2, '0'); + final d = dt.day.toString().padLeft(2, '0'); + final h = dt.hour.toString().padLeft(2, '0'); + final min = dt.minute.toString().padLeft(2, '0'); + return '$y$m$d$h$min'; +} diff --git a/packages/shorebird_cli/test/src/platform/windows/windows_test.dart b/packages/shorebird_cli/test/src/platform/windows/windows_test.dart index 534aaa9e..3c27fb37 100644 --- a/packages/shorebird_cli/test/src/platform/windows/windows_test.dart +++ b/packages/shorebird_cli/test/src/platform/windows/windows_test.dart @@ -62,11 +62,12 @@ void main() { group('when an exact match does not exist', () { late File app; - setUp(() async { - File(p.join(tempDir.path, 'other.exe')).createSync(); - // Ensure my_app is created after other. - await Future.delayed(const Duration(seconds: 1)); + setUp(() { + final other = File(p.join(tempDir.path, 'other.exe'))..createSync(); app = File(p.join(tempDir.path, '$projectName.exe'))..createSync(); + // Set modification times so my_app is newer than other. + other.setLastModifiedSync(DateTime(2024)); + app.setLastModifiedSync(DateTime(2025)); }); test('returns most recently modified executable', () {