/** * Testy funkcjonalne dla Quarc * Sprawdzają czy podstawowa funkcjonalność działa poprawnie */ import { ControlFlowTransformer } from '../../cli/helpers/control-flow-transformer'; import { TemplateParser, AttributeType } from '../../cli/helpers/template-parser'; import { StructuralDirectiveHelper } from '../../cli/helpers/structural-directive-helper'; console.log('=== TESTY FUNKCJONALNE QUARC ===\n'); let passedTests = 0; let failedTests = 0; function test(name: string, fn: () => boolean): void { try { const result = fn(); if (result) { console.log(`✅ ${name}`); passedTests++; } else { console.log(`❌ ${name}`); failedTests++; } } catch (e) { console.log(`❌ ${name} - Error: ${e}`); failedTests++; } } // Test 1: ControlFlowTransformer - prosty @if test('ControlFlowTransformer: @if -> *ngIf', () => { const transformer = new ControlFlowTransformer(); const input = '@if (show) {
Content
}'; const result = transformer.transform(input); return result.includes('') && result.includes('Content'); }); // Test 2: ControlFlowTransformer - @if @else test('ControlFlowTransformer: @if @else', () => { const transformer = new ControlFlowTransformer(); const input = '@if (a) {
A
} @else {
B
}'; const result = transformer.transform(input); return result.includes('*ngIf="a"') && result.includes('*ngIf="!(a)"'); }); // Test 3: ControlFlowTransformer - @if @else if @else test('ControlFlowTransformer: @if @else if @else', () => { const transformer = new ControlFlowTransformer(); const input = '@if (a) {
A
} @else if (b) {
B
} @else {
C
}'; const result = transformer.transform(input); return result.includes('*ngIf="a"') && result.includes('*ngIf="!(a) && b"') && result.includes('*ngIf="!(a) && !(b)"'); }); // Test 4: TemplateParser - parsowanie prostego HTML test('TemplateParser: prosty HTML', () => { const parser = new TemplateParser(); const elements = parser.parse('
Content
'); return elements.length === 1 && 'tagName' in elements[0] && elements[0].tagName === 'div'; }); // Test 5: TemplateParser - parsowanie atrybutów test('TemplateParser: atrybuty', () => { const parser = new TemplateParser(); const elements = parser.parse('
Content
'); return elements.length === 1 && 'attributes' in elements[0] && elements[0].attributes.length === 2; }); // Test 6: TemplateParser - *ngIf jako structural directive test('TemplateParser: *ngIf detection', () => { const parser = new TemplateParser(); const elements = parser.parse('
Content
'); if (elements.length === 0 || !('attributes' in elements[0])) return false; const attr = elements[0].attributes.find(a => a.name === '*ngIf'); return attr !== undefined && attr.type === 'structural'; }); // Test 7: TemplateParser - text nodes test('TemplateParser: text nodes', () => { const parser = new TemplateParser(); const elements = parser.parse('Text before
Content
Text after'); return elements.length === 3 && 'type' in elements[0] && elements[0].type === 'text' && 'tagName' in elements[1] && elements[1].tagName === 'div' && 'type' in elements[2] && elements[2].type === 'text'; }); // Test 8: TemplateParser - zagnieżdżone elementy test('TemplateParser: zagnieżdżone elementy', () => { const parser = new TemplateParser(); const elements = parser.parse('
Nested
'); return elements.length === 1 && 'children' in elements[0] && elements[0].children.length === 1 && 'tagName' in elements[0].children[0] && elements[0].children[0].tagName === 'span'; }); // Test 9: StructuralDirectiveHelper - canHandle *ngIf test('StructuralDirectiveHelper: canHandle *ngIf', () => { const helper = new StructuralDirectiveHelper(); const attr = { name: '*ngIf', value: 'show', type: AttributeType.STRUCTURAL_DIRECTIVE }; return helper.canHandle(attr); }); // Test 10: StructuralDirectiveHelper - process *ngIf test('StructuralDirectiveHelper: process *ngIf', () => { const helper = new StructuralDirectiveHelper(); const attr = { name: '*ngIf', value: 'show', type: AttributeType.STRUCTURAL_DIRECTIVE }; const element = { tagName: 'div', attributes: [attr], children: [] }; const result = helper.process({ element, attribute: attr, filePath: 'test.ts' }); return result.transformed === true && result.newAttribute?.name === '*ngIf' && result.newAttribute?.value === 'show'; }); // Test 11: ControlFlowTransformer - brak transformacji bez @if test('ControlFlowTransformer: brak @if', () => { const transformer = new ControlFlowTransformer(); const input = '
Regular content
'; const result = transformer.transform(input); return result === input; }); // Test 12: TemplateParser - self-closing tags test('TemplateParser: self-closing tags', () => { const parser = new TemplateParser(); const elements = parser.parse(''); return elements.length === 1 && 'tagName' in elements[0] && elements[0].tagName === 'img' && elements[0].children.length === 0; }); // Test 13: TemplateParser - komentarze są pomijane test('TemplateParser: komentarze', () => { const parser = new TemplateParser(); const elements = parser.parse('
Content
'); return elements.length === 1 && 'tagName' in elements[0] && elements[0].tagName === 'div'; }); // Test 14: ControlFlowTransformer - wieloliniowy @if test('ControlFlowTransformer: wieloliniowy @if', () => { const transformer = new ControlFlowTransformer(); const input = `@if (show) {
Multi-line content
}`; const result = transformer.transform(input); return result.includes('') && result.includes('Multi-line content'); }); // Test 15: TemplateParser - puste elementy test('TemplateParser: puste elementy', () => { const parser = new TemplateParser(); const elements = parser.parse('
'); return elements.length === 1 && 'tagName' in elements[0] && elements[0].tagName === 'div' && elements[0].children.length === 0; }); // Test 16: ControlFlowTransformer - prosty @for test('ControlFlowTransformer: @for -> *ngFor', () => { const transformer = new ControlFlowTransformer(); const input = '@for (item of items) {
{{ item }}
}'; const result = transformer.transform(input); return result.includes('') && result.includes('
{{ item }}
'); }); // Test 17: ControlFlowTransformer - @for z trackBy test('ControlFlowTransformer: @for z trackBy', () => { const transformer = new ControlFlowTransformer(); const input = '@for (item of items; track item.id) {
{{ item.name }}
}'; const result = transformer.transform(input); return result.includes('') && result.includes('
{{ item.name }}
'); }); // Test 18: ControlFlowTransformer - @for z wieloliniową zawartością test('ControlFlowTransformer: @for wieloliniowy', () => { const transformer = new ControlFlowTransformer(); const input = `@for (user of users) {

{{ user.name }}

{{ user.email }}

}`; const result = transformer.transform(input); return result.includes('') && result.includes('user-card') && result.includes('{{ user.name }}'); }); // Test 19: ControlFlowTransformer - @for i @if razem test('ControlFlowTransformer: @for i @if razem', () => { const transformer = new ControlFlowTransformer(); const input = `@for (item of items) { @if (item.active) {
Active item: {{ item.name }}
} }`; const result = transformer.transform(input); return result.includes('') && result.includes('') && result.includes('Active item:'); }); // Test 20: ControlFlowTransformer - @if z aliasem (as variable) test('ControlFlowTransformer: @if (condition; as variable)', () => { const transformer = new ControlFlowTransformer(); const input = '@if (device(); as dev) {
{{ dev.name }}
}'; const result = transformer.transform(input); return result.includes('') && result.includes('
{{ dev.name }}
'); }); // Test 21: ControlFlowTransformer - @if @else if z aliasem test('ControlFlowTransformer: @if @else if z aliasem', () => { const transformer = new ControlFlowTransformer(); const input = '@if (getUser(); as user) {
{{ user.name }}
} @else if (getGuest(); as guest) {
{{ guest.id }}
}'; const result = transformer.transform(input); return result.includes('*ngIf="getUser(); let user"') && result.includes('*ngIf="!(getUser()) && getGuest(); let guest"'); }); // Test 22: ControlFlowTransformer - @if z zagnieżdżonymi nawiasami w warunku test('ControlFlowTransformer: @if z zagnieżdżonymi nawiasami', () => { const transformer = new ControlFlowTransformer(); const input = '@if (getData(getValue()); as data) {
{{ data }}
}'; const result = transformer.transform(input); return result.includes('*ngIf="getData(getValue()); let data"'); }); // Test 23: ControlFlowTransformer - @if z aliasem i białymi znakami test('ControlFlowTransformer: @if z aliasem i białymi znakami', () => { const transformer = new ControlFlowTransformer(); const input = '@if ( device() ; as dev ) {
{{ dev.name }}
}'; const result = transformer.transform(input); return result.includes('*ngIf="device(); let dev"'); }); // Test 24: ControlFlowTransformer - @if z aliasem w @else if test('ControlFlowTransformer: @if @else if oba z aliasem', () => { const transformer = new ControlFlowTransformer(); const input = '@if (primary(); as p) {
{{ p }}
} @else if (secondary(); as s) {
{{ s }}
} @else {
None
}'; const result = transformer.transform(input); return result.includes('*ngIf="primary(); let p"') && result.includes('*ngIf="!(primary()) && secondary(); let s"') && result.includes('*ngIf="!(primary()) && !(secondary())"'); }); // Test 25: ControlFlowTransformer - niekompletny @if (bez zamknięcia) test('ControlFlowTransformer: niekompletny @if', () => { const transformer = new ControlFlowTransformer(); const input = '@if (range.name) { content'; const result = transformer.transform(input); return result.includes('content'); }); // Test 26: ControlFlowTransformer - niekompletny @if na końcu test('ControlFlowTransformer: niekompletny @if na końcu', () => { const transformer = new ControlFlowTransformer(); const input = '} @if (prepared.sensor.loading) { '; const result = transformer.transform(input); return result.includes(''); }); // Test 27: ControlFlowTransformer - niekompletny @if bez nawiasu klamrowego test('ControlFlowTransformer: niekompletny @if bez nawiasu klamrowego', () => { const transformer = new ControlFlowTransformer(); const input = '@if (condition) '; const result = transformer.transform(input); return result.includes(''); }); // Test 28: ControlFlowTransformer - zagnieżdżony @if wewnątrz @for test('ControlFlowTransformer: zagnieżdżony @if wewnątrz @for', () => { const transformer = new ControlFlowTransformer(); const input = `@for (item of items) { @if (item.active) { {{ item.name }} } }`; const result = transformer.transform(input); return result.includes('') && result.includes('') && !result.includes('@if') && !result.includes('@for'); }); // Test 29: ControlFlowTransformer - zagnieżdżony @for wewnątrz @if test('ControlFlowTransformer: zagnieżdżony @for wewnątrz @if', () => { const transformer = new ControlFlowTransformer(); const input = `@if (hasItems) { @for (item of items; track item.id) {
{{ item }}
} }`; const result = transformer.transform(input); return result.includes('') && result.includes('') && !result.includes('@if') && !result.includes('@for'); }); // Test 30: ControlFlowTransformer - wielokrotnie zagnieżdżone @if wewnątrz @for test('ControlFlowTransformer: wielokrotnie zagnieżdżone @if wewnątrz @for', () => { const transformer = new ControlFlowTransformer(); const input = `@for (range of ranges; track $index) {
@if (range.name) { {{ range.name }} } {{ range.min }}
}`; const result = transformer.transform(input); return result.includes('') && result.includes('') && !result.includes('@if') && !result.includes('@for'); }); // Test 31: ControlFlowTransformer - kompleksowy przypadek z user template test('ControlFlowTransformer: kompleksowy przypadek użytkownika', () => { const transformer = new ControlFlowTransformer(); const input = `@if (prepared.sensor.ranges) { @for (range of prepared.sensor.ranges; track $index) {
@if (range.name) { {{ range.name }} } {{ range.min }} {{ range.max }}
}
}`; const result = transformer.transform(input); return result.includes('') && result.includes('') && result.includes('') && !result.includes('@if') && !result.includes('@for'); }); // Test 32: ControlFlowTransformer - głęboko zagnieżdżone @if/@for/@if test('ControlFlowTransformer: głęboko zagnieżdżone @if/@for/@if', () => { const transformer = new ControlFlowTransformer(); const input = `@if (level1) { @for (item of items; track item.id) { @if (item.visible) {
{{ item.name }}
} } }`; const result = transformer.transform(input); return result.includes('') && result.includes('') && result.includes('') && !result.includes('@if') && !result.includes('@for'); }); // Test 33: ControlFlowTransformer - @for z funkcją w iterable test('ControlFlowTransformer: @for z funkcją w iterable', () => { const transformer = new ControlFlowTransformer(); const input = '@for (item of getItems(); track item.id) {
{{ item }}
}'; const result = transformer.transform(input); return result.includes('') && !result.includes('@for'); }); // Test 34: ControlFlowTransformer - @for z zagnieżdżonymi nawiasami w funkcji test('ControlFlowTransformer: @for z zagnieżdżonymi nawiasami w funkcji', () => { const transformer = new ControlFlowTransformer(); const input = '@for (prepared of preparedSensors(); track prepared.sensor.id) {
{{ prepared.sensor.name }}
}'; const result = transformer.transform(input); return result.includes('') && result.includes('prepared.sensor.name') && !result.includes('@for'); }); // Test 35: ControlFlowTransformer - @for z metodą obiektu w iterable test('ControlFlowTransformer: @for z metodą obiektu w iterable', () => { const transformer = new ControlFlowTransformer(); const input = '@for (item of data.getItems(); track $index) { {{ item }} }'; const result = transformer.transform(input); return result.includes('') && !result.includes('@for'); }); // Test 36: ControlFlowTransformer - @for z wieloma zagnieżdżonymi nawiasami test('ControlFlowTransformer: @for z wieloma zagnieżdżonymi nawiasami', () => { const transformer = new ControlFlowTransformer(); const input = '@for (item of service.getData(filter(value())); track item.id) {
{{ item }}
}'; const result = transformer.transform(input); return result.includes('') && !result.includes('@for'); }); // Test 37: ControlFlowTransformer - @for z funkcją i złożonym trackBy test('ControlFlowTransformer: @for z funkcją i złożonym trackBy', () => { const transformer = new ControlFlowTransformer(); const input = '@for (range of prepared.sensor.ranges; track $index) {
{{ range.name }}
}'; const result = transformer.transform(input); return result.includes('') && result.includes('range.name') && !result.includes('@for'); }); console.log('\n=== PODSUMOWANIE ==='); console.log(`✅ Testy zaliczone: ${passedTests}`); console.log(`❌ Testy niezaliczone: ${failedTests}`); console.log(`📊 Procent sukcesu: ${((passedTests / (passedTests + failedTests)) * 100).toFixed(1)}%`); if (failedTests === 0) { console.log('\n🎉 Wszystkie testy przeszły pomyślnie!'); } else { console.log('\n⚠️ Niektóre testy nie przeszły. Sprawdź implementację.'); }