Files
iptvnator/tools/nx/check-material-theme-scope.test.mjs
T
4grayandClaude Fable 5.1 7917040aab fix(tools): count runtime Material imports in the theme guard and scope the dialog motion check
The theme-scope guard matched any `from '@angular/material/<entry>'`, so a
type-only import kept a theme required and a dynamic `import()` (as
LazyMatDialog makes) was not counted at all. It now reads the
comment-stripped source for static imports that are not `import type`
and for dynamic imports, with tests for both.

The motion spec accepted any transform transition on the page as the
dialog's entrance and checked no exit motion. Events now carry their
target's class list: the entrance is the surface's transform transition
recorded since the dialog opened, and the close must start the inner
container's opacity fade before the container is removed. The fade's end
is not asserted: Material detaches the container on a timer of the same
length, so a detached element may never report it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 18:31:33 +02:00

132 lines
4.0 KiB
JavaScript

import assert from 'node:assert/strict';
import { test } from 'node:test';
import {
compareThemeScope,
requiredThemes,
themedComponents,
usedEntryPoints,
} from './check-material-theme-scope.mjs';
const lines = (...rows) => rows.join('\n');
test('usedEntryPoints lists each Material entry point with its first importer', () => {
const importers = usedEntryPoints([
{
file: 'a.component.ts',
source: lines(
"import { MatButtonModule } from '@angular/material/button';",
'import {',
' MatDialog,',
"} from '@angular/material/dialog';",
'import { MatIcon } from "@angular/material/icon";'
),
},
{
file: 'b.component.ts',
source: "import { MatButton } from '@angular/material/button';",
},
]);
assert.deepEqual(
[...importers],
[
['button', 'a.component.ts'],
['dialog', 'a.component.ts'],
['icon', 'a.component.ts'],
]
);
});
test('usedEntryPoints counts dynamic imports and ignores type-only ones and comments', () => {
const importers = usedEntryPoints([
{
file: 'lazy-mat-dialog.ts',
source: lines(
"import type { MatDialog } from '@angular/material/dialog';",
"type DialogModule = typeof import('@angular/material/dialog');",
'loadDialogModule = () =>',
" import('@angular/material/dialog');"
),
},
{
file: 'types-only.ts',
source: lines(
"import type { MatTooltip } from '@angular/material/tooltip';",
"// import { MatChipsModule } from '@angular/material/chips';",
"/* import { MatTabsModule } from '@angular/material/tabs'; */"
),
},
]);
assert.deepEqual([...importers], [['dialog', 'lazy-mat-dialog.ts']]);
});
test('requiredThemes always keeps core and expands the button entry point', () => {
const required = requiredThemes(
new Map([
['button', 'a.ts'],
['tooltip', 'b.ts'],
['testing', 'c.ts'],
])
);
assert.deepEqual(
[...required],
[
['core', 'always themed'],
['button', '@angular/material/button in a.ts'],
['icon-button', '@angular/material/button in a.ts'],
['fab', '@angular/material/button in a.ts'],
['tooltip', '@angular/material/tooltip in b.ts'],
]
);
});
test('themedComponents reads the list, direct includes and the all-components mixin', () => {
assert.deepEqual(
themedComponents(
lines(
'$material-components: (',
' core,',
' button, // used by every dialog',
' icon-button,',
');',
'@include mat.tooltip-theme($theme);'
)
),
{
themed: new Set(['core', 'button', 'icon-button', 'tooltip']),
all: false,
}
);
assert.deepEqual(
themedComponents('html { @include mat.all-component-themes($t); }'),
{ themed: new Set(), all: true }
);
});
test('compareThemeScope reports missing and surplus themes', () => {
const required = new Map([
['core', 'always themed'],
['button', '@angular/material/button in a.ts'],
]);
assert.deepEqual(
compareThemeScope(required, {
themed: new Set(['core', 'tabs']),
all: false,
}),
{
unthemed: [['button', '@angular/material/button in a.ts']],
unused: ['tabs'],
}
);
// all-component-themes leaves nothing unthemed, but is still surplus-free
// only when the list is empty.
assert.deepEqual(
compareThemeScope(required, { themed: new Set(), all: true }),
{ unthemed: [], unused: [] }
);
});