diff --git a/modules/betterbird/README.md b/modules/betterbird/README.md index bc405744..e5812c95 100644 --- a/modules/betterbird/README.md +++ b/modules/betterbird/README.md @@ -78,7 +78,11 @@ under `/run/user//mesh-betterbird-reminder-test/`, as the user unit `mesh-betterbird-reminder-test` (ended after 10 minutes at most). The profile holds the module's user.js and one calendar: a local `.ics` file with one event, "Mesh reminder test", whose reminder is due `after` seconds from the call (default 40). `carry` copies named preferences of the operator's -profile into it (a theme, a colour switch), under the same limits as `betterbird_prefs`. Then: +profile into it (a theme, a colour switch), under the same limits as `betterbird_prefs`. The test's own +preferences come last in its user.js, so nothing declared or carried overrides them; one of them turns +Betterbird's update check off (`betterbird.update.checkIntervalDays` 0), because a fresh profile checks +at its start and, when a newer build is published, opens the About window on the operator's screen +(seen 2026-10-12). Then: - `xorg_windows` with class `Calendar` answers the reminder window: role `AlarmWindow`, type `Dialog`, its depth (32: a visual with alpha, which the compositor blends), its map state; diff --git a/modules/betterbird/cmd/betterbird-tools/betterbird_test.go b/modules/betterbird/cmd/betterbird-tools/betterbird_test.go index 2f66d12f..2a7aec55 100644 --- a/modules/betterbird/cmd/betterbird-tools/betterbird_test.go +++ b/modules/betterbird/cmd/betterbird-tools/betterbird_test.go @@ -238,6 +238,13 @@ func TestTheReminderTestTouchesNothingOfTheOperatorsProfile(t *testing.T) { !strings.Contains(string(user), "file:///run/user/1000/"+testUnit+"/test.ics") || strings.Contains(string(user), "someone@") { t.Fatalf("%s", user) } + // Betterbird's update check stays off, so no About window opens on the operator's screen, and the + // test's own preferences come last, so nothing carried or declared overrides them. + if !strings.Contains(string(user), `"betterbird.update.checkIntervalDays", 0`) || + strings.Index(string(user), "extensions.activeThemeID") > strings.Index(string(user), "calendar.registry.meshtest.uri") || + strings.Index(string(user), `"calendar.alarms.show"`) > strings.Index(string(user), "calendar.registry.meshtest.uri") { + t.Fatalf("%s", user) + } // The event starts 10 minutes after the reminder, which is due 40 s from now. if !strings.Contains(string(cal), "DTSTART:20270115T081040Z") || !strings.Contains(string(cal), "TRIGGER:-PT10M") || a.Due != "2027-01-15T08:00:40Z" { diff --git a/modules/betterbird/cmd/betterbird-tools/reminder.go b/modules/betterbird/cmd/betterbird-tools/reminder.go index 995f78c9..da31debc 100644 --- a/modules/betterbird/cmd/betterbird-tools/reminder.go +++ b/modules/betterbird/cmd/betterbird-tools/reminder.go @@ -55,6 +55,11 @@ func ics(now time.Time, after time.Duration, stamp string) string { } // testPrefs are the test profile's own preferences: its one calendar, and no first-run questions. +// +// betterbird.update.checkIntervalDays 0 is Betterbird's own switch for its update check (MailGlue): a +// fresh profile has never checked, so Betterbird checks at its start and, when betterbird.eu publishes a +// newer build than the installed one, opens the About window on the operator's screen and gives it the +// focus (seen on the workstation 2026-10-12, novox/hq issue 345). The test is about the reminder only. func testPrefs(calendar string) string { return strings.Join([]string{ `user_pref("calendar.registry.meshtest.type", "ics");`, @@ -68,6 +73,7 @@ func testPrefs(calendar string) string { `user_pref("datareporting.policy.dataSubmissionEnabled", false);`, `user_pref("toolkit.telemetry.reportingpolicy.firstRun", false);`, `user_pref("app.update.auto", false);`, + `user_pref("betterbird.update.checkIntervalDays", 0);`, `user_pref("mail.rights.version", 1);`, "", }, "\n") @@ -125,11 +131,13 @@ func (m *Machine) ReminderTest(after time.Duration, carry []string, stop bool) ( if err := os.WriteFile(calendar, []byte(ics(now, after, strconv.FormatInt(now.Unix(), 10))), 0o600); err != nil { return a, err } - user := testPrefs(strings.TrimPrefix(calendar, m.Root)) + // The module's user.js first, then what is carried, then the test's own preferences: the last + // statement wins, so neither can take the test's calendar or its quiet start away. + user := "" if mine, err := readBounded(m.home(declared)); err == nil && validUserJS(string(mine)) == nil { - user = string(mine) + "\n" + user + user = string(mine) + "\n" } - user += strings.Join(carried, "\n") + "\n" + user += strings.Join(carried, "\n") + "\n" + testPrefs(strings.TrimPrefix(calendar, m.Root)) if err := os.WriteFile(filepath.Join(dir, "profile", "user.js"), []byte(user), 0o600); err != nil { return a, err }