0.2.24
RustBox CI / rustbox (push) Canceled after 0s

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-04 23:34:09 +01:00
1 parent beae94e932
commit de4d70970c
51 files changed
+4034 -421

No files matched your search

+71
View File
@@ -999,6 +999,18 @@ require(
and 'savePreference("skinGradients"' in bindings_js,
"style gradients have their own persisted Appearance switch",
)
gradient_css = read("src/web/css/59-skin-gradients.css")
require(
"59-skin-gradients.css" in css_manifest
and css_manifest.index("58-skin-immersive.css") < css_manifest.index("59-skin-gradients.css") < css_manifest.index("60-responsive.css"),
"style gradient layer loads after the immersive rules",
)
require(
all(f"var(--grad-{layer})" in gradient_css for layer in ("backdrop", "appbar", "toolbar", "sidebar", "selected", "primary"))
and ':root[data-skin-gradients="true"]:not([data-interface-skin="rustbox"])[data-theme] .appbar' in gradient_css
and "data-skin-depth" not in gradient_css.split("/* Consumers", 1)[-1].split("{", 1)[0],
"style gradients apply to every predefined style except RustBox at any style depth",
)
# Every gradient in the stylesheets must sit in a rule scoped to the switch.
ungated_gradients = []
for css_name in css_manifest:
@@ -1010,6 +1022,65 @@ for css_name in css_manifest:
if 'data-skin-gradients="true"' not in selector:
ungated_gradients.append(f"{css_name}: {selector.strip()[:60]}")
require(not ungated_gradients, "every stylesheet gradient is gated by the style-gradients switch" + (f" (ungated: {'; '.join(ungated_gradients[:5])})" if ungated_gradients else ""))
for _, dialect in MIGRATION_DIALECTS:
require(all(column in read(f"migrations/{dialect}/schema.sql") and column in read(f"src/queries/{dialect}/queries.rs") for column in ("theme_light_from", "theme_dark_from", "account_color")), f"{dialect} fresh schema and display query include the theme schedule and account colour")
try:
conn = sqlite3.connect(":memory:")
conn.executescript("CREATE TABLE u_prod__display_preferences (id INTEGER PRIMARY KEY, theme TEXT NOT NULL DEFAULT 'system'); INSERT INTO u_prod__display_preferences(id) VALUES(1); CREATE TABLE u_prod__calendar_events (id TEXT PRIMARY KEY, reminder_minutes INTEGER); INSERT INTO u_prod__calendar_events(id, reminder_minutes) VALUES('e1', 15); CREATE TABLE u_prod__calendar_settings (id INTEGER PRIMARY KEY); INSERT INTO u_prod__calendar_settings(id) VALUES(1);")
conn.executescript(read("migrations/sqlite/V054__theme_schedule_account_color_and_reminders.sql").replace("{{p}}", "u_prod__"))
require(conn.execute("SELECT theme_light_from, theme_dark_from, account_color FROM u_prod__display_preferences WHERE id=1").fetchone() == ("07:00", "19:00", ""), "SQLite V054 adds the theme schedule and account colour with defaults")
require(conn.execute("SELECT reminder_minutes, reminder_extra_minutes FROM u_prod__calendar_events WHERE id='e1'").fetchone() == (15, None), "SQLite V054 adds an optional second calendar reminder and keeps existing reminders")
require(conn.execute("SELECT default_reminder_minutes, default_extra_reminder_minutes FROM u_prod__calendar_settings WHERE id=1").fetchone() == (None, None), "SQLite V054 adds empty default reminders for new events")
conn.close()
except Exception as exc:
errors.append(f"SQLite V054 migration execution failed: {exc}")
require(
'"schedule"' in display_prefs_rs and 'value="schedule"' in index_html and "function scheduledTheme(" in prefs_js
and 'id="pref-account-color"' in index_html and 'html[data-account-color="true"] .appbar::before' in read("src/web/css/50-settings.css"),
"time-of-day theme and per-account colour are wired end to end",
)
for _, dialect in MIGRATION_DIALECTS:
queries_text = read(f"src/queries/{dialect}/queries.rs")
require(
"reminder_extra_minutes" in read(f"migrations/{dialect}/schema.sql") and "reminder_extra_minutes" in queries_text
and "default_extra_reminder_minutes" in queries_text,
f"{dialect} schema and calendar queries include the second reminder and reminder defaults",
)
calendar_js = read("src/web/js/71-calendar.js")
require(
'id="calendar-reminder-extra"' in index_html and 'id="calendar-default-reminder"' in index_html
and "reminder_extra_minutes: reminderSelectValue(" in calendar_js
and "calendarReminderTrigger(event, minutes)" in read("src/web/js/80-settings-realtime.js"),
"calendar events support a second reminder (e.g. one day before) with defaults for new events",
)
require("function updateContrastWarning(" in prefs_js and 'id="pref-contrast-warning"' in index_html, "custom colours show a live contrast warning")
sieve_js = read("src/web/js/90-sieve.js")
sieve_apply_js = read("src/web/js/91-sieve-apply.js")
filters_rs = read("src/routes/filters.rs")
require(
'.route("/filters/match", post(filters::match_filter_handler))' in read("src/routes/mod.rs")
and "async fn search_uids(" in read("src/imap/client.rs")
and "async fn search_uids(" in read("src/imap/mock.rs")
and all("pub mod db_filter_match" in read(f"src/queries/{d}/queries.rs") for d in ("sqlite", "mysql", "pgsql")),
"filters: POST /filters/match is routed and backed by IMAP UID SEARCH on every client",
)
require(
"fn bounds(" in filters_rs and "fn resolve_matches(" in filters_rs and "uncertain" in filters_rs and "#[cfg(test)]" in filters_rs,
"filters: apply-now matching uses upper/lower IMAP bounds, decides the gap from the cache and reports uncertain messages",
)
require(
"91-sieve-apply.js" in read("src/web/js/manifest.txt")
and 'id="sieve-apply-check"' in index_html and 'id="sieve-apply-run"' in index_html
and "function runParsedSieveRuleNow(" in sieve_apply_js and "function alwaysMoveFromSender(" in sieve_apply_js
and "function ensureSieveTargetFolders(" in sieve_apply_js and 'id="sieve-templates"' in index_html,
"filters: apply now, per-rule run now, templates, missing-folder creation and 'always move from this sender' are wired",
)
require(
'id="sieve-builder-exceptions"' in index_html and "function splitSieveExceptions(" in sieve_js
and all(f'"{kind}"' in sieve_js for kind in ("to-only", "cc-only", "size-over", "size-under", "has-attachment", "priority-high"))
and '"label"' in sieve_js and '"trash"' in sieve_js,
"filters: exceptions, new conditions (To/Cc only, size, attachment, priority) and label/trash actions round-trip through the editor",
)
mysql_text_literal_defaults = re.findall(r"^\s*(\w+)\s+TEXT(?:\s+NOT NULL)?\s+DEFAULT\s+'", read("migrations/mysql/schema.sql") + "\n" + "\n".join(read(f"migrations/mysql/{name}") for _, name in MIGRATIONS["mysql"]), re.M)
require(not mysql_text_literal_defaults, "MySQL TEXT columns use expression defaults" + (f" (literal: {', '.join(mysql_text_literal_defaults)})" if mysql_text_literal_defaults else ""))