Files
ISA-Frontend/libs/shared/barcode/src/lib/barcode.directive.spec.ts
Nino Righi 8b852cbd7a Merged PR 2048: fix(shared-barcode, crm-customer-card): improve barcode rendering with transp...
fix(shared-barcode, crm-customer-card): improve barcode rendering with transparent SVG background

Enhance barcode component flexibility by separating container and SVG
background colors. The SVG barcode now defaults to transparent background
while maintaining container background control, enabling better integration
with various card designs.

Changes:
- Add separate svgBackground input for SVG element (default: transparent)
- Keep background input for container styling (default: #ffffff)
- Add containerWidth and containerHeight inputs for flexible sizing
- Update customer card to remove explicit white background on barcode
- Add opacity styling for inactive customer cards
- Enhance test coverage for new background and sizing inputs

The separation of concerns allows the barcode to adapt to parent container
backgrounds while maintaining consistent rendering across different contexts.

Ref: #5498
2025-11-24 14:58:05 +00:00

254 lines
7.1 KiB
TypeScript

import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { BarcodeDirective } from './barcode.directive';
// Mock JsBarcode
vi.mock('jsbarcode', () => ({
default: vi.fn((element, value, options) => {
// Simulate JsBarcode by adding a rect element to the SVG
if (element && element.tagName === 'svg') {
const rect = document.createElementNS(
'http://www.w3.org/2000/svg',
'rect',
);
rect.setAttribute('data-value', value);
rect.setAttribute('data-format', options?.format || 'CODE128');
element.appendChild(rect);
// Call valid callback if provided
if (options?.valid) {
const isValid = value && value.length > 0;
options.valid(isValid);
}
}
}),
}));
@Component({
standalone: true,
imports: [BarcodeDirective],
template: `
<svg
sharedBarcode
[value]="barcodeValue"
[format]="format"
[width]="width"
[height]="height"
[displayValue]="displayValue"
></svg>
`,
})
class TestHostComponent {
barcodeValue = '123456789';
format = 'CODE128';
width = 2;
height = 100;
displayValue = true;
}
describe('BarcodeDirective', () => {
let fixture: ComponentFixture<TestHostComponent>;
let component: TestHostComponent;
let svgElement: SVGElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TestHostComponent],
}).compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
svgElement = fixture.nativeElement.querySelector('svg');
fixture.detectChanges();
});
describe('Initialization', () => {
it('should create the directive', () => {
expect(component).toBeTruthy();
});
it('should apply to SVG element', () => {
expect(svgElement).toBeTruthy();
expect(svgElement.tagName).toBe('svg');
});
it('should render barcode on initialization', () => {
// JsBarcode adds child elements to the SVG
expect(svgElement.children.length).toBeGreaterThan(0);
});
});
describe('Barcode Rendering', () => {
it('should render barcode with default CODE128 format', () => {
const rect = svgElement.querySelector('rect');
expect(rect).toBeTruthy();
});
it('should render barcode with custom value', () => {
component.barcodeValue = '987654321';
fixture.detectChanges();
// SVG should be updated with new value
expect(svgElement.children.length).toBeGreaterThan(0);
});
it('should update barcode when value changes', () => {
component.barcodeValue = 'NEWVALUE123';
fixture.detectChanges();
// Barcode should be re-rendered (may have different number of bars)
expect(svgElement.children.length).toBeGreaterThan(0);
});
it('should render with custom width', () => {
component.width = 4;
fixture.detectChanges();
expect(svgElement.children.length).toBeGreaterThan(0);
});
it('should render with custom height', () => {
component.height = 200;
fixture.detectChanges();
const rect = svgElement.querySelector('rect');
expect(rect).toBeTruthy();
});
it('should render without display value when disabled', () => {
component.displayValue = false;
fixture.detectChanges();
// Check that SVG is still rendered
expect(svgElement.children.length).toBeGreaterThan(0);
});
});
describe('Input Changes', () => {
it('should re-render when format changes', () => {
component.format = 'CODE128';
fixture.detectChanges();
expect(svgElement.children.length).toBeGreaterThan(0);
});
it('should handle multiple rapid value changes', () => {
component.barcodeValue = 'VALUE1';
fixture.detectChanges();
component.barcodeValue = 'VALUE2';
fixture.detectChanges();
component.barcodeValue = 'VALUE3';
fixture.detectChanges();
expect(svgElement.children.length).toBeGreaterThan(0);
});
});
describe('Error Handling', () => {
it('should handle empty value gracefully', () => {
// JsBarcode should handle this or log warning
component.barcodeValue = '';
fixture.detectChanges();
// Directive should not crash
expect(component).toBeTruthy();
});
it('should handle very long values', () => {
component.barcodeValue = '1'.repeat(100);
fixture.detectChanges();
expect(svgElement.children.length).toBeGreaterThan(0);
});
});
describe('Customization Options', () => {
it('should render with custom line color', () => {
@Component({
standalone: true,
imports: [BarcodeDirective],
template: `
<svg sharedBarcode [value]="'123456'" [lineColor]="'#FF0000'"></svg>
`,
})
class ColorTestComponent {}
const colorFixture = TestBed.createComponent(ColorTestComponent);
colorFixture.detectChanges();
const svg = colorFixture.nativeElement.querySelector('svg');
expect(svg).toBeTruthy();
expect(svg.children.length).toBeGreaterThan(0);
});
it('should render with custom background', () => {
@Component({
standalone: true,
imports: [BarcodeDirective],
template: `
<svg sharedBarcode [value]="'123456'" [background]="'#F0F0F0'"></svg>
`,
})
class BackgroundTestComponent {}
const bgFixture = TestBed.createComponent(BackgroundTestComponent);
bgFixture.detectChanges();
const svg = bgFixture.nativeElement.querySelector('svg');
expect(svg).toBeTruthy();
});
it('should render with transparent background by default', () => {
@Component({
standalone: true,
imports: [BarcodeDirective],
template: ` <svg sharedBarcode [value]="'123456'"></svg> `,
})
class DefaultBackgroundTestComponent {}
const bgFixture = TestBed.createComponent(DefaultBackgroundTestComponent);
bgFixture.detectChanges();
const svg = bgFixture.nativeElement.querySelector('svg');
expect(svg).toBeTruthy();
});
it('should render with custom font size', () => {
@Component({
standalone: true,
imports: [BarcodeDirective],
template: `
<svg sharedBarcode [value]="'123456'" [fontSize]="30"></svg>
`,
})
class FontSizeTestComponent {}
const fontFixture = TestBed.createComponent(FontSizeTestComponent);
fontFixture.detectChanges();
const svg = fontFixture.nativeElement.querySelector('svg');
expect(svg).toBeTruthy();
});
it('should render with custom margin', () => {
@Component({
standalone: true,
imports: [BarcodeDirective],
template: `
<svg sharedBarcode [value]="'123456'" [margin]="20"></svg>
`,
})
class MarginTestComponent {}
const marginFixture = TestBed.createComponent(MarginTestComponent);
marginFixture.detectChanges();
const svg = marginFixture.nativeElement.querySelector('svg');
expect(svg).toBeTruthy();
});
});
});