From 10479ed0796ff5bc026b090c3f98eac111f2fa22 Mon Sep 17 00:00:00 2001 From: diffwireauto <330573775+diffwireauto@users.noreply.github.com> Date: Mon, 9 Nov 2026 00:12:53 -0500 Subject: [PATCH] feat(#1129): tell test builds of one version apart by commit Test builds share a version and build number, so the sponsor window would show only for the first of them. A build passed --dart-define=GIT_SHA= is now known as 1.8.0+69@; a build without it (CI releases, whose build number always changes) stays 1.8.0+69. Tests: two commits of one version each show it once; the gate test passes with and without GIT_SHA defined, and failed with the old fixed expectation when it was defined. Full suite 2076 passed. Co-Authored-By: Claude Opus 5.5 --- lib/widgets/sponsor_prompt.dart | 19 ++++++++++++++---- test/widgets/sponsor_prompt_test.dart | 29 ++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/widgets/sponsor_prompt.dart b/lib/widgets/sponsor_prompt.dart index 8a6a5347..63c0e8b4 100644 --- a/lib/widgets/sponsor_prompt.dart +++ b/lib/widgets/sponsor_prompt.dart @@ -18,9 +18,20 @@ class SponsorPrompt { static const String offKey = 'sponsor_prompt_off'; static final Uri sponsorUri = Uri.parse('https://offband.org/donate'); - /// Shows the window unless it has already shown for [version], the user - /// turned it off, or this is iOS (hidden there like About's Donate, #1051). - /// The version is saved before the window opens, so a crash can't loop it. + /// The commit a test build was made from, passed with + /// `--dart-define=GIT_SHA=`. Test builds share one version and build + /// number, so this is what tells them apart. Release builds leave it empty: + /// their build number already changes every time. + static const String buildSha = String.fromEnvironment('GIT_SHA'); + + /// What one installed build is known by: `1.8.0+69`, or `1.8.0+69@`. + static String buildId(String version, {String sha = buildSha}) => + sha.isEmpty ? version : '$version@$sha'; + + /// Shows the window unless it has already shown for this build ([version] is + /// its [buildId]), the user turned it off, or this is iOS (hidden there like + /// About's Donate, #1051). The build is saved before the window opens, so a + /// crash can't loop it. static Future maybeShow( BuildContext context, { String? version, @@ -68,7 +79,7 @@ class SponsorPrompt { static Future _installedVersion() async { try { final info = await PackageInfo.fromPlatform(); - return '${info.version}+${info.buildNumber}'; + return buildId('${info.version}+${info.buildNumber}'); } catch (e) { appLogger.error('Sponsor prompt: no app version: $e', tag: 'Sponsor'); return null; diff --git a/test/widgets/sponsor_prompt_test.dart b/test/widgets/sponsor_prompt_test.dart index 72a812fd..557009c7 100644 --- a/test/widgets/sponsor_prompt_test.dart +++ b/test/widgets/sponsor_prompt_test.dart @@ -131,9 +131,10 @@ void main() { ); await tester.pumpAndSettle(); expect(_title, findsOneWidget); + // Carries the commit when the test run passes --dart-define=GIT_SHA. expect( PrefsManager.instance.getString(SponsorPrompt.shownForKey), - '1.8.0+69', + SponsorPrompt.buildId('1.8.0+69'), ); }); @@ -179,6 +180,32 @@ void main() { }); } + test('a test build is known by its commit, a release by its version', () { + expect(SponsorPrompt.buildId('1.8.0+69', sha: ''), '1.8.0+69'); + expect( + SponsorPrompt.buildId('1.8.0+69', sha: 'abc1234'), + '1.8.0+69@abc1234', + ); + }); + + testWidgets('two test builds of one version each show it once', ( + tester, + ) async { + final prefs = await _prefs(); + final first = SponsorPrompt.buildId('1.8.0+69', sha: 'abc1234'); + final second = SponsorPrompt.buildId('1.8.0+69', sha: 'def5678'); + await _launch(tester, prefs, version: first); + expect(_title, findsOneWidget); + await tester.tap(find.text('Not now')); + await tester.pumpAndSettle(); + + await _launch(tester, prefs, version: first); + expect(_title, findsNothing); + + await _launch(tester, prefs, version: second); + expect(_title, findsOneWidget); + }); + test('Sponsor opens the donate page the About screen uses', () { expect(SponsorPrompt.sponsorUri.toString(), 'https://offband.org/donate'); });