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
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
import { Component, input } from '@angular/core';
import type { Spec } from '@json-render/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RenderElementComponent } from '@ngaf/render';
import { ContainerComponent } from './container.component';

// Stub matching <render-element>'s selector + public inputs. Swapped into
// ContainerComponent's imports via overrideComponent so Angular doesn't
// instantiate the real RenderElementComponent (which requires RENDER_CONTEXT).
@Component({
selector: 'render-element',
standalone: true,
template: '',
})
class StubRenderElementComponent {
readonly elementKey = input<string>('');
readonly spec = input<Spec | undefined>(undefined);
}

describe('ContainerComponent', () => {
let fixture: ComponentFixture<ContainerComponent>;

// Minimal Spec satisfying the input.required<Spec>() — children resolution
// is delegated to <render-element>, so the spec body itself is not exercised.
const emptySpec: Spec = { elements: {}, root: 'root' };

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ContainerComponent],
})
.overrideComponent(ContainerComponent, {
remove: { imports: [RenderElementComponent] },
add: { imports: [StubRenderElementComponent] },
})
.compileComponents();
fixture = TestBed.createComponent(ContainerComponent);
});

it('applies column flex classes by default', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.detectChanges();
const wrapper = fixture.nativeElement.querySelector('div');
expect(wrapper?.className).toContain('flex-col');
expect(wrapper?.className).not.toContain('flex-row');
});

it('applies row flex classes when direction is "row"', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.componentRef.setInput('direction', 'row');
fixture.detectChanges();
const wrapper = fixture.nativeElement.querySelector('div');
expect(wrapper?.className).toContain('flex-row');
expect(wrapper?.className).not.toContain('flex-col');
});

it('renders one render-element per childKey', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.componentRef.setInput('childKeys', ['a', 'b', 'c']);
fixture.detectChanges();
const elements = fixture.nativeElement.querySelectorAll('render-element');
expect(elements.length).toBe(3);
});

it('renders no render-element children when childKeys is empty', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.componentRef.setInput('childKeys', []);
fixture.detectChanges();
const elements = fixture.nativeElement.querySelectorAll('render-element');
expect(elements.length).toBe(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
import { Component, input } from '@angular/core';
import type { Spec } from '@json-render/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RenderElementComponent } from '@ngaf/render';
import { DashboardGridComponent } from './dashboard-grid.component';

// See ContainerComponent spec for rationale. Same stub pattern keeps Angular
// from instantiating the real <render-element> (which needs RENDER_CONTEXT).
@Component({
selector: 'render-element',
standalone: true,
template: '',
})
class StubRenderElementComponent {
readonly elementKey = input<string>('');
readonly spec = input<Spec | undefined>(undefined);
}

describe('DashboardGridComponent', () => {
let fixture: ComponentFixture<DashboardGridComponent>;

const emptySpec: Spec = { elements: {}, root: 'root' };

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DashboardGridComponent],
})
.overrideComponent(DashboardGridComponent, {
remove: { imports: [RenderElementComponent] },
add: { imports: [StubRenderElementComponent] },
})
.compileComponents();
fixture = TestBed.createComponent(DashboardGridComponent);
});

it('applies vertical flex layout with section spacing', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.detectChanges();
const wrapper = fixture.nativeElement.querySelector('div');
expect(wrapper?.className).toContain('flex-col');
expect(wrapper?.className).toContain('gap-6');
});

it('renders one render-element per childKey', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.componentRef.setInput('childKeys', ['stats_row', 'charts_row', 'table_section']);
fixture.detectChanges();
const elements = fixture.nativeElement.querySelectorAll('render-element');
expect(elements.length).toBe(3);
});

it('renders no render-element children when childKeys is empty', () => {
fixture.componentRef.setInput('spec', emptySpec);
fixture.componentRef.setInput('childKeys', []);
fixture.detectChanges();
const elements = fixture.nativeElement.querySelectorAll('render-element');
expect(elements.length).toBe(0);
});
});
Loading
Loading