Files
openchamber/packages/ui/src/lib/shiki/sanitizeTemplateCallGrammar.test.ts
T
Bohdan Triapitsyn 48bcac1758 fix: harden and de-slop the merged sidebar/chat/settings batch
Post-merge follow-ups for #2740 #2735 #2734 #2690 #2676 #2738 #2684
#2689 #2733 #2739 #2462 #2687 #2736 #2618 #2697, plus three regressions
found while reviewing them:

- ctrl/cmd+digit while typing no longer switches session tabs (#2503 was
  still open in practice: the guard only covered the mod+alt surface binding)
- Shiki template-call sanitizer now covers every bundled grammar, including
  the js/ts aliases and embedding grammars; timed-out highlight requests are
  memoized and no longer cancel unrelated in-flight requests
- settings flush on suspend uses keepalive and also fires on Capacitor
  appStateChange; keeps the selected model persisted across mode switches
- remote-only branches fetch before checkout; range helpers fail clearly
- git status invalidation now fires for runtime adapters too
- settings number inputs and select triggers size in ch so they scale with
  the interface font
- recent-activity timestamps tick from one list-level ticker
- Markdown preview find goes through the shared find_in_file keybind with
  containment, no longer counts its own bar, and debounces observer runs
- #2676 reverted; #2524 fixed by fading the sticky header's own background
  instead of overlaying the content below it
- sticky group headers in the model picker and sidebar render again
  (oc-sticky-fade-scroller class restored after 9b9d7069c)
- project switcher names are left-aligned again (wrapper lost in 26dbc2f30)
- tool card quick-open icon is always visible and opens the same line as the
  expanded card's button
- tautological tests replaced or removed; new oxlint findings fixed
2026-08-29 01:06:43 +03:00

65 lines
2.9 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import { bundledLanguages, type BundledLanguage, type LanguageRegistration } from 'shiki';
import { hasCatastrophicTemplateCall, sanitizeTemplateCallGrammar } from './sanitizeTemplateCallGrammar';
type BundledLanguageModule = { default: LanguageRegistration[] };
const loadBundledGrammars = async (id: BundledLanguage): Promise<LanguageRegistration[]> => {
// SAFETY: `id` is a Shiki bundled-language key and every bundled language
// module default-exports its grammar array.
const mod = (await bundledLanguages[id]()) as BundledLanguageModule;
return mod.default;
};
describe('sanitizeTemplateCallGrammar', () => {
test('detects template-call on bundled JS/TS grammars', async () => {
for (const id of ['javascript', 'typescript', 'jsx', 'tsx'] as const) {
const [grammar] = await loadBundledGrammars(id);
expect(hasCatastrophicTemplateCall(grammar)).toBe(true);
}
});
test('a bundled alias request yields sanitized grammars too', async () => {
// `js` is a separate key in bundledLanguages resolving to the same grammar
// module; the worker sanitizes whatever id was requested, so the alias must
// come out clean as well.
const grammars = await loadBundledGrammars('js');
const patched = grammars.map((grammar) => sanitizeTemplateCallGrammar(grammar));
expect(grammars.some((grammar) => hasCatastrophicTemplateCall(grammar))).toBe(true);
expect(patched.some((grammar) => hasCatastrophicTemplateCall(grammar))).toBe(false);
});
test('an embedding grammar carries JS/TS entries that are sanitized as well', async () => {
// `vue` ships the JS/TS grammars alongside its own, so gating on the
// requested id alone would leave them unpatched.
const grammars = await loadBundledGrammars('vue');
const affected = grammars.filter((grammar) => hasCatastrophicTemplateCall(grammar));
expect(affected.length).toBeGreaterThan(0);
const patched = grammars.map((grammar) => sanitizeTemplateCallGrammar(grammar));
expect(patched.some((grammar) => hasCatastrophicTemplateCall(grammar))).toBe(false);
});
test('clears template-call patterns without dropping the repository key', async () => {
const [grammar] = await loadBundledGrammars('javascript');
const patched = sanitizeTemplateCallGrammar(grammar);
expect(hasCatastrophicTemplateCall(patched)).toBe(false);
expect(patched.repository?.['template-call']).toEqual({ patterns: [] });
// Original left intact (spread, not mutate-in-place).
expect(hasCatastrophicTemplateCall(grammar)).toBe(true);
});
test('is a no-op when template-call is already empty', () => {
const grammar = {
name: 'javascript',
scopeName: 'source.js',
patterns: [],
repository: { 'template-call': { patterns: [] } },
} satisfies LanguageRegistration;
expect(sanitizeTemplateCallGrammar(grammar)).toBe(grammar);
});
});