Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions .github/workflows/tests.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,16 +99,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/c*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit q-z"
test_path: "tests/unit/[q-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -130,12 +130,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All@@ -158,16 +158,16 @@ jobs:
include:
- name: "functional"
test_path: "tests/functional/*_test.sh"
- name: "unit a-b"
test_path: "tests/unit/[a-b]*_test.sh"
- name: "unit c + coverage"
test_path: "tests/unit/ch*_test.sh tests/unit/cl*_test.sh tests/unit/console*_test.sh tests/unit/cu*_test.sh tests/unit/coverage_*_test.sh"
- name: "unit d-g"
test_path: "tests/unit/[d-g]*_test.sh"
- name: "unit h-p"
test_path: "tests/unit/[h-p]*_test.sh"
- name: "unit r-z"
test_path: "tests/unit/[r-z]*_test.sh"
- name: "unit 1/5"
test_path: "--shard 1/5 tests/unit"
- name: "unit 2/5"
test_path: "--shard 2/5 tests/unit"
- name: "unit 3/5"
test_path: "--shard 3/5 tests/unit"
- name: "unit 4/5"
test_path: "--shard 4/5 tests/unit"
- name: "unit 5/5"
test_path: "--shard 5/5 tests/unit"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All@@ -191,12 +191,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: "a-e"
test_path: "tests/acceptance/bashunit_[a-e]*_test.sh tests/acceptance/coverage_*_test.sh"
- name: "f-l"
test_path: "tests/acceptance/bashunit_[f-l]*_test.sh tests/acceptance/install*_test.sh"
- name: "m-z"
test_path: "tests/acceptance/bashunit_[m-z]*_test.sh tests/acceptance/bashunit_test.sh tests/acceptance/mock*_test.sh tests/acceptance/parallel*_test.sh"
- name: "1/3"
test_path: "--shard 1/3 tests/acceptance"
- name: "2/3"
test_path: "--shard 2/3 tests/acceptance"
- name: "3/3"
test_path: "--shard 3/3 tests/acceptance"
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/project/ci_test_paths_test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash

# Anti-drift contract for the test paths in .github/workflows/tests.yml.
#
# The CI matrix used to slice tests/unit/ with alphabetical globs
# (tests/unit/[a-b]*_test.sh and friends). #960 moved every unit test into a
# per-module subdirectory, so those globs stopped matching anything -- and
# bashunit answers an argument that matches no file by falling back to its
# default path, i.e. the whole suite. Every macOS and Windows unit leg
# therefore ran all the tests instead of its fifth, on every run, staying green
# the entire time. Nothing was failing, so nothing pointed at it.
#
# The same rot had already cost coverage rather than time: the acceptance
# buckets were also hand-maintained globs, and tests/acceptance/worker_stderr_test.sh
# matched none of the three, so it never ran in CI at all after #891 added it.
#
# Both are now expressed as `--shard i/n <dir>`, which cannot silently select
# nothing. This test pins the property that mattered either way: a path CI runs
# must actually resolve to tests.

WORKFLOW=""
ROOT_DIR=""

function set_up_before_script() {
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/tests.yml"
}

# Without this the greps below would match nothing after a rename and every
# other assertion would compare empty against empty and pass -- the same
# vacuum that hid the bug this file is about.
function test_the_workflow_being_checked_exists() {
assert_file_exists "$WORKFLOW"
}

# Each configured test_path, one per line, quotes stripped.
function ci_test_paths() {
grep -oE 'test_path: "[^"]+"' "$WORKFLOW" | sed 's/test_path: "//; s/"$//'
}

function test_every_ci_test_path_resolves_to_at_least_one_test_file() {
local unresolved=""
local line
while IFS= read -r line; do
[ -z "$line" ] && continue
# Drop flags and their values: what remains is the path or glob CI runs.
local rest="$line"
case "$rest" in
--shard*)
# `--shard i/n <path>`: drop the flag, then drop its i/n value. Done with
# prefix stripping rather than `set -- $rest` so nothing has to rely on
# word splitting here.
rest="${rest#--shard }"
rest="${rest#* }"
;;
esac

local found=0
local token
for token in $rest; do
# Unquoted on purpose: these are globs and must expand here.
local match
for match in $token; do
if [ -e "$match" ]; then
found=1
break
fi
done
[ "$found" -eq 1 ] && break
done

if [ "$found" -eq 0 ]; then
unresolved="$unresolved$line
"
fi
done <<EOF
$(cd "$ROOT_DIR" && ci_test_paths)
EOF

assert_empty "$unresolved"
}
Loading