-
Notifications
You must be signed in to change notification settings - Fork 11
fix(cockpit-examples): use CSS sidebar widths #779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,96 @@ | ||||||
| // SPDX-License-Identifier: MIT | ||||||
| import { existsSync, readdirSync, readFileSync } from 'node:fs'; | ||||||
| import { dirname, resolve } from 'node:path'; | ||||||
| import { fileURLToPath } from 'node:url'; | ||||||
|
|
||||||
| const WORKSPACE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../../..'); | ||||||
| const RENDER_DIR = resolve(WORKSPACE_ROOT, 'cockpit/render'); | ||||||
| const ANGULAR_EXAMPLE_DIRS = ['cockpit', 'examples']; | ||||||
| const SUPPORTED_RENDER_DIRECTIVES = new Set([ | ||||||
| '$and', | ||||||
| '$bindItem', | ||||||
| '$bindState', | ||||||
| '$computed', | ||||||
| '$cond', | ||||||
| '$else', | ||||||
| '$index', | ||||||
| '$item', | ||||||
| '$or', | ||||||
| '$state', | ||||||
| '$template', | ||||||
| '$then', | ||||||
| ]); | ||||||
|
|
||||||
| function renderSpecFiles(): string[] { | ||||||
| return readdirSync(RENDER_DIR, { withFileTypes: true }) | ||||||
| .filter((entry) => entry.isDirectory() && entry.name !== 'shared') | ||||||
| .map((entry) => resolve(RENDER_DIR, entry.name, 'angular/src/app/specs.ts')) | ||||||
| .filter((file) => existsSync(file)); | ||||||
| } | ||||||
|
|
||||||
| function angularSourceFiles(dir: string): string[] { | ||||||
| const out: string[] = []; | ||||||
| for (const entry of readdirSync(dir, { withFileTypes: true })) { | ||||||
| const path = resolve(dir, entry.name); | ||||||
| if (entry.isDirectory()) { | ||||||
| out.push(...angularSourceFiles(path)); | ||||||
| } else if (entry.name.endsWith('.ts') || entry.name.endsWith('.html')) { | ||||||
| out.push(path); | ||||||
| } | ||||||
| } | ||||||
| return out; | ||||||
| } | ||||||
|
|
||||||
| function collectDirectiveNames(value: unknown, out = new Set<string>()): Set<string> { | ||||||
| if (!value || typeof value !== 'object') return out; | ||||||
| if (Array.isArray(value)) { | ||||||
| for (const item of value) collectDirectiveNames(item, out); | ||||||
| return out; | ||||||
| } | ||||||
| for (const [key, nested] of Object.entries(value)) { | ||||||
| if (/^\$[A-Za-z][A-Za-z0-9_]*$/.test(key)) out.add(key); | ||||||
| collectDirectiveNames(nested, out); | ||||||
| } | ||||||
| return out; | ||||||
| } | ||||||
|
|
||||||
| function parseJsonRenderSpecs(source: string): unknown[] { | ||||||
| const specs: unknown[] = []; | ||||||
| const pattern = /json:\s*JSON\.stringify\(([\s\S]*?),\s*null,\s*2\)/g; | ||||||
| for (const match of source.matchAll(pattern)) { | ||||||
| specs.push(Function(`"use strict"; return (${match[1]});`)()); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Low — The streaming harness file already statically imports all six
Suggested change
Replace import { COMPUTED_FUNCTIONS_SPECS } from '../computed-functions/angular/src/app/specs';
import { ELEMENT_RENDERING_SPECS } from '../element-rendering/angular/src/app/specs';
import { REGISTRY_SPECS } from '../registry/angular/src/app/specs';
import { REPEAT_LOOPS_SPECS } from '../repeat-loops/angular/src/app/specs';
import { SPEC_RENDERING_SPECS } from '../spec-rendering/angular/src/app/specs';
import { STATE_MANAGEMENT_SPECS } from '../state-management/angular/src/app/specs';
const ALL_RENDER_SPECS = [
...REGISTRY_SPECS, ...SPEC_RENDERING_SPECS, ...ELEMENT_RENDERING_SPECS,
...STATE_MANAGEMENT_SPECS, ...REPEAT_LOOPS_SPECS, ...COMPUTED_FUNCTIONS_SPECS,
];
// in the test:
for (const spec of ALL_RENDER_SPECS) {
for (const directive of collectDirectiveNames(JSON.parse(spec.json))) {
if (!SUPPORTED_RENDER_DIRECTIVES.has(directive)) {
unsupported.push(`${spec.label}: ${directive}`);
}
}
} |
||||||
| } | ||||||
| return specs; | ||||||
|
Comment on lines
+57
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
// In each specs.ts, export a named constant the test can import directly.
// Then collectDirectiveNames() can run on the imported value without eval.
import { STATE_MANAGEMENT_SPECS } from '../state-management/angular/src/app/specs';
// …and so on for the other render examples.If the regex-parse approach must stay, at minimum validate that the captured expression only looks like an object/array literal before passing it to |
||||||
| } | ||||||
|
|
||||||
| describe('cockpit examples latent bug sweep guards', () => { | ||||||
| it('uses only render directives supported by @json-render/core', () => { | ||||||
| const unsupported: string[] = []; | ||||||
| for (const file of renderSpecFiles()) { | ||||||
| const rel = file.slice(WORKSPACE_ROOT.length + 1); | ||||||
| for (const spec of parseJsonRenderSpecs(readFileSync(file, 'utf8'))) { | ||||||
| for (const directive of collectDirectiveNames(spec)) { | ||||||
| if (!SUPPORTED_RENDER_DIRECTIVES.has(directive)) { | ||||||
| unsupported.push(`${rel}: ${directive}`); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| expect(unsupported).toEqual([]); | ||||||
| }); | ||||||
|
|
||||||
| it('passes CSS lengths, not Tailwind width classes, to example-chat-layout sidebarWidth', () => { | ||||||
| const offenders: string[] = []; | ||||||
| for (const root of ANGULAR_EXAMPLE_DIRS) { | ||||||
| for (const file of angularSourceFiles(resolve(WORKSPACE_ROOT, root))) { | ||||||
| const source = readFileSync(file, 'utf8'); | ||||||
| if (/sidebarWidth="w-\d+"/.test(source)) { | ||||||
| offenders.push(file.slice(WORKSPACE_ROOT.length + 1)); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| expect(offenders).toEqual([]); | ||||||
| }); | ||||||
| }); | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,95 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SPDX-License-Identifier: MIT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { TestBed } from '@angular/core/testing'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { provideRender } from '@threadplane/render'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { COMPUTED_FUNCTIONS_SPECS } from '../computed-functions/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ComputedFunctionsComponent } from '../computed-functions/angular/src/app/computed-functions.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ELEMENT_RENDERING_SPECS } from '../element-rendering/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ElementRenderingComponent } from '../element-rendering/angular/src/app/element-rendering.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { REGISTRY_SPECS } from '../registry/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { RegistryComponent } from '../registry/angular/src/app/registry.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { REPEAT_LOOPS_SPECS } from '../repeat-loops/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { RepeatLoopsComponent } from '../repeat-loops/angular/src/app/repeat-loops.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { SPEC_RENDERING_SPECS } from '../spec-rendering/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { SpecRenderingComponent } from '../spec-rendering/angular/src/app/spec-rendering.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { STATE_MANAGEMENT_SPECS } from '../state-management/angular/src/app/specs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { StateManagementComponent } from '../state-management/angular/src/app/state-management.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { StreamingSimulator } from './streaming-simulator'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface DemoSpec { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| json: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface RenderExampleHarness { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| simulator: StreamingSimulator; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const COMPUTED_FUNCTIONS = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formatDate: (args: Record<string, unknown>) => new Date(args['value'] as string).toLocaleDateString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uppercase: (args: Record<string, unknown>) => (args['value'] as string).toUpperCase(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| multiply: (args: Record<string, unknown>) => (args['a'] as number) * (args['b'] as number), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reverse: (args: Record<string, unknown>) => (args['value'] as string).split('').reverse().join(''), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const EXAMPLES = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'registry', component: RegistryComponent, specs: REGISTRY_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'spec-rendering', component: SpecRenderingComponent, specs: SPEC_RENDERING_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'element-rendering', component: ElementRenderingComponent, specs: ELEMENT_RENDERING_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'state-management', component: StateManagementComponent, specs: STATE_MANAGEMENT_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'repeat-loops', component: RepeatLoopsComponent, specs: REPEAT_LOOPS_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { name: 'computed-functions', component: ComputedFunctionsComponent, specs: COMPUTED_FUNCTIONS_SPECS }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe('render example streaming fixtures', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const example of EXAMPLES) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe(example.name, () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| beforeEach(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await TestBed.configureTestingModule({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imports: [example.component], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| providers: [provideRender({ functions: COMPUTED_FUNCTIONS })], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }).compileComponents(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const spec of example.specs as DemoSpec[]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it(`${spec.label} fully streams without object flash text`, async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fixture = TestBed.createComponent(example.component); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const component = fixture.componentInstance as unknown as RenderExampleHarness; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| component.simulator.setSource(spec.json); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| component.simulator.seek(spec.json.length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fixture.detectChanges(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await fixture.whenStable(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fixture.detectChanges(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const text = (fixture.nativeElement as HTMLElement).textContent ?? ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(text).not.toContain('[object Object]'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(text).not.toContain('object Object'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(text.trim()).not.toBe(''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it('renders non-string primitive state and computed values as display text', async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await TestBed.configureTestingModule({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imports: [StateManagementComponent, ComputedFunctionsComponent], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| providers: [provideRender({ functions: COMPUTED_FUNCTIONS })], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }).compileComponents(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const stateFixture = TestBed.createComponent(StateManagementComponent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const stateComponent = stateFixture.componentInstance as unknown as RenderExampleHarness; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateComponent.simulator.setSource(STATE_MANAGEMENT_SPECS[1].json); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateComponent.simulator.seek(STATE_MANAGEMENT_SPECS[1].json.length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateFixture.detectChanges(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const computedFixture = TestBed.createComponent(ComputedFunctionsComponent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const computedComponent = computedFixture.componentInstance as unknown as RenderExampleHarness; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| computedComponent.simulator.setSource(COMPUTED_FUNCTIONS_SPECS[1].json); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| computedComponent.simulator.seek(COMPUTED_FUNCTIONS_SPECS[1].json.length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| computedFixture.detectChanges(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+82
to
+90
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two issues here, both confirmed after reading the actual spec arrays: Magic indices — Missing
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect((stateFixture.nativeElement as HTMLElement).textContent).toContain('30'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect((computedFixture.nativeElement as HTMLElement).textContent).toContain('42'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+93
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Magic indices make this test silently validate the wrong fixture if
Suggested change
Also note this test doesn't call
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Medium — Magic indices + missing
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "extends": "../../tsconfig.base.json", | ||
| "compilerOptions": { | ||
| "experimentalDecorators": true, | ||
| "noPropertyAccessFromIndexSignature": true, | ||
| "module": "preserve", | ||
| "emitDeclarationOnly": false, | ||
| "composite": false, | ||
| "declaration": false, | ||
| "lib": ["es2022", "dom"], | ||
| "types": ["vitest/globals"] | ||
| }, | ||
| "angularCompilerOptions": { | ||
| "enableI18nLegacyMessageIdFormat": false, | ||
| "strictInjectionParameters": true, | ||
| "strictInputAccessModifiers": true, | ||
| "strictTemplates": true | ||
| }, | ||
| "include": [ | ||
| "shared/**/*.ts", | ||
| "*/angular/src/**/*.ts", | ||
| "../../libs/render/src/**/*.ts" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import angular from '@analogjs/vite-plugin-angular'; | ||
| import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; | ||
| import { defineConfig } from 'vite'; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [angular({ tsconfig: './tsconfig.spec.json' }), nxViteTsPaths()], | ||
| test: { | ||
| globals: true, | ||
| environment: 'jsdom', | ||
| include: ['shared/**/*.spec.ts'], | ||
| setupFiles: ['../../libs/render/src/test-setup.ts'], | ||
| pool: 'forks', | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function()is effectivelyeval(). The practical risk for version-controlled fixtures is low, but there's a simpler fix available: each spec file already exports a named*_SPECSarray wherespec.jsonis the result ofJSON.stringify(obj, null, 2). You can import those arrays statically and round-trip withJSON.parseinstead of evaluating source text:Tradeoff: the static list needs to be updated when new render examples are added, unlike the current dynamic scan. If you want to keep dynamic discovery,
dynamic import()overrenderSpecFiles()paths avoidsFunction()while preserving the automation.