Add test coverage for the Angular bundle patch

patch_ui.py rewrites minified third-party JavaScript by regex and had no tests.
It is the easiest place in this project to do real damage: a pattern that matches
nothing silently leaves the dropdown Storj-only, and one that consumes a paren
too many is a syntax error in the bundle that blanks the entire TrueNAS web UI.

Tests run the real patterns against verbatim snippets from a TrueNAS 25.x
chunk-*.js (the chained property(...)(...) form) and a 24.x literal array, and
assert: exactly one match, all three providers present, the paren balance is
UNCHANGED, surrounding code untouched, re-patching is a no-op, unrelated JS is
never matched, and every pattern stays anchored to filterByProviders.

The paren-balance assertion is the load-bearing one -- a plausible-but-wrong
pattern that eats both parens and re-emits none shifts the delta from 1 to 2 and
is caught.

Also restore the comment explaining why the 25.x pattern is shaped the way it is,
and correct the module docstring, which showed the binding with a single closing
paren; the real bundle wraps it in a chained property call.

90 tests, ruff and shellcheck clean.
This commit is contained in:
flan
2026-07-13 14:37:43 +00:00
parent 8421a34d8d
commit 8a2028bfa7
2 changed files with 127 additions and 4 deletions
+14 -4
View File
@@ -9,8 +9,8 @@ in the minified JS in one of two forms depending on TrueNAS / Angular version:
TrueNAS 24.x (static inline array):
"filterByProviders",["STORJ_IX"]
TrueNAS 25.x+ (Angular pureFunction binding):
"filterByProviders",pe(115,Rn,i.CloudSyncProviderName.Storj)
TrueNAS 25.x+ (Angular pureFunction binding, inside a chained property call):
c(2,"filterByProviders",pe(115,Rn,i.CloudSyncProviderName.Storj))("required",!0)
Both are replaced so the dropdown includes S3 and B2. The file is backed up
before modification so uninstall.sh can restore it.
@@ -33,11 +33,21 @@ WEBUI_CANDIDATES = [
# Patterns tried in order; the first match wins.
# Each entry is (compiled_regex, replacement_string).
_PATTERNS = [
# TrueNAS 25.x+: Angular emits a pureFunction call instead of a literal array.
# TrueNAS 25.x+: Angular emits a pureFunction call instead of a literal array,
# inside a CHAINED property binding — so the call is followed by two closing
# parens, one for pe(...) and one for the property(...) it sits in:
#
# c(2,"filterByProviders",pe(115,Rn,i.CloudSyncProviderName.Storj))("required",!0)
# ^^
# The pattern consumes both and re-emits one, leaving the paren balance
# unchanged. Getting that wrong is a syntax error in the bundle and the whole
# web UI goes blank — see tests/test_patch_ui.py.
#
# The minified names (pe / slot index / Rn / i) change across builds;
# CloudSyncProviderName.Storj is stable because it is a TypeScript enum name.
(re.compile(r'("filterByProviders",)\w+\(\d+,\w+,\w+\.CloudSyncProviderName\.Storj\)\)'),
r'\1["STORJ_IX","S3","B2"])'),
# TrueNAS 24.x and earlier: static inline array.
(re.compile(r'("filterByProviders",)\["STORJ_IX"\]'),
r'\1["STORJ_IX","S3","B2"]'),