Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
refactor(tests): mirror the src/ module layout in tests/unit/ by Chemaclass · Pull Request #960 · TypedDevs/bashunit · GitHub
Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' refactor(tests): mirror the src/ module layout in tests/unit/ by Chemaclass · Pull Request #960 · TypedDevs/bashunit · GitHub
Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

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

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' refactor(tests): mirror the src/ module layout in tests/unit/ by Chemaclass · Pull Request #960 · TypedDevs/bashunit · GitHub
Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' refactor(tests): mirror the src/ module layout in tests/unit/ by Chemaclass · Pull Request #960 · TypedDevs/bashunit · GitHub
Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' refactor(tests): mirror the src/ module layout in tests/unit/ by Chemaclass · Pull Request #960 · TypedDevs/bashunit · GitHub
Skip to content

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

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

refactor(tests): mirror the src/ module layout in tests/unit/ - #960

Merged
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout
Aug 1, 2026
Merged

refactor(tests): mirror the src/ module layout in tests/unit/#960
Chemaclass merged 1 commit into
mainfrom
refactor/957-mirror-src-layout

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename prefix; src/ has been 17 modules since #948.

tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh

16 directories named for their source module, plus tests/unit/project/ for the ten tests covering the repo's own tooling and invariants (the five release_*, package_json, build, bash_version, bash_compatibility, redirect_error) — naming that honestly beats filing them under a module name that would be a lie.

⚠️ Three classes of breakage, all found by running rather than reading

1. Fifteen tests resolve paths from their own location. Moving them one level deeper broke $(bashunit::current_dir)/fixtures/.... Fixtures stay shared at tests/unit/fixtures/, so those become ../fixtures/. The four find_files_recursive tests now take a repo-relative input instead — a ../ in the input reappears in the output they assert on.

2. Snapshots had to move and be renamed with their test — and two were already poisoned. The failing runs had auto-recorded them at the new path (documented behaviour: a missing snapshot gets written). For the two "unsuccessful" cases they captured Expected snapshot instead of Actual snapshot text — those tests exist to demonstrate a mismatch, so keeping the auto-recorded files would have silently inverted them. Originals restored and diffed.

3. Renaming introduced three duplicate basenames, which cost 52 tests under --parallel.

🐛 That third one is a real bashunit bug — #959

src/runner/result.sh:28 buckets per-test results by basename, so a/foo_test.sh and b/foo_test.sh share a bucket and overwrite each other. Silently, and green.

--parallel --simple --strict
with 3 duplicate basenames1536
after renaming them unique1588

Same class as #923, which fixed exactly this in build.sh. It affects any user project whose tests mirror a source tree — the layout this very PR adopts. Worked around here by keeping basenames unique; the fix belongs to #959.

✅ Verification

The number this whole issue was designed around:

Green: make sa · make lint · bash build.sh bin -v✅ Build verified ✅.

Closes#957. tests/unit/ was 71 flat files with the module encoded in a filename
prefix; src/ has been seventeen modules since #948. Now the tree matches:
tests/unit/coverage/engine_test.sh for src/coverage/engine.sh
tests/unit/runner/exec_test.sh for src/runner/exec.sh
Sixteen directories named for their source module, plus tests/unit/project/ for
the ten tests that cover the repo's own tooling and invariants rather than a
module: the five release_*, package_json, build, bash_version,
bash_compatibility and redirect_error. Naming that honestly beats filing them
under a module name that would be a lie.
Three classes of breakage, all found by running rather than by reading:
- Fifteen tests resolve paths from their own location. Moving them one level
deeper broke `$(bashunit::current_dir)/fixtures/...`. Fixtures stay shared at
tests/unit/fixtures/, so those become ../fixtures/. The four
find_files_recursive tests now pass a repo-relative input instead, because a
../ in the input reappears in the output they assert on.
- The assert_snapshot snapshots had to move and be renamed with their test. Two
of them had already been auto-recorded at the new path by the failing runs,
with the wrong content: the "unsuccessful" cases record the expected text
rather than the actual, which would have inverted the two tests that exist to
demonstrate a mismatch. The originals were restored and diffed.
- Renaming introduced three duplicate basenames, which cost 52 tests under
--parallel. That is a real bashunit bug, filed as #959: results are bucketed
by basename in runner/result.sh, so same-named files in different directories
share a bucket and overwrite each other, silently and green. Same class as
#923. Worked around here by keeping basenames unique; the fix belongs to #959.
Verified by the number the whole issue was designed around: the sequential total
is 1629 before and after, and --parallel --simple --strict is 1588, which is the
1585 baseline plus the three collection-guard tests from #958.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoringRefactoring or cleaning related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(tests): mirror the src/ module layout in tests/unit/

1 participant

@Chemaclass