Files
Filamenteka/__tests__/data-consistency.test.ts
DaX 12e91d4c3e Remove refresh icon and fix Safari/WebKit runtime errors
- Removed manual refresh button from frontend (kept auto-refresh functionality)
- Fixed WebKit 'object cannot be found' error by replacing absolute positioning with flexbox
- Added lazy loading to images to prevent preload warnings
- Cleaned up unused imports and variables:
  - Removed unused useRef import
  - Removed unused colors state variable and colorService
  - Removed unused ColorSwatch import from FilamentTableV2
  - Removed unused getModifierIcon function from MaterialBadge
- Updated tests to match current implementation
- Improved layout stability for better cross-browser compatibility
- Removed temporary migration scripts

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-30 22:37:30 +02:00

229 lines
6.4 KiB
TypeScript

import { Filament } from '../src/types/filament';
import { Pool } from 'pg';
describe('Data Structure Consistency Tests', () => {
const connectionString = "postgresql://filamenteka_admin:onrBjiAjHKQXBAJSVWU2t2kQ7HDil9re@filamenteka.ci7fsdlbzmag.eu-central-1.rds.amazonaws.com:5432/filamenteka";
// Admin panel expected structure (source of truth)
const ADMIN_STRUCTURE = {
fields: [
'id',
'tip',
'finish',
'boja',
'boja_hex', // Now using snake_case consistently
'refill',
'spulna', // Frontend still uses spulna
'kolicina',
'cena',
'created_at',
'updated_at'
],
requiredFields: ['tip', 'finish', 'boja'],
excludedFields: ['brand'], // Should NOT exist
fieldTypes: {
tip: 'string',
finish: 'string',
boja: 'string',
boja_hex: 'string',
refill: 'number',
spulna: 'number',
kolicina: 'number',
cena: 'string'
}
};
// Database expected structure
const DB_STRUCTURE = {
columns: [
'id',
'tip',
'finish',
'boja',
'boja_hex', // Database uses snake_case
'refill',
'spulna',
'kolicina',
'cena',
'created_at',
'updated_at'
],
excludedColumns: ['brand'],
columnTypes: {
id: 'uuid',
tip: 'character varying',
finish: 'character varying',
boja: 'character varying',
boja_hex: 'character varying',
refill: 'integer',
spulna: 'integer',
kolicina: 'integer',
cena: 'character varying',
created_at: 'timestamp with time zone',
updated_at: 'timestamp with time zone'
}
};
describe('Admin Panel Structure', () => {
it('should have correct TypeScript interface', () => {
// Check Filament interface matches admin structure
const filamentKeys: (keyof Filament)[] = [
'id', 'tip', 'finish', 'boja', 'boja_hex',
'refill', 'spulna', 'kolicina', 'cena',
'status', 'createdAt', 'updatedAt'
];
// Should not have brand
expect(filamentKeys).not.toContain('brand');
// Should have all required fields
ADMIN_STRUCTURE.requiredFields.forEach(field => {
expect(filamentKeys).toContain(field);
});
});
it('should have consistent form fields in admin dashboard', () => {
const formFields = [
'tip', 'finish', 'boja', 'boja_hex',
'refill', 'spulna', 'kolicina', 'cena'
];
// Check all form fields are in admin structure
formFields.forEach(field => {
expect(ADMIN_STRUCTURE.fields).toContain(field);
});
// Should not have brand in form
expect(formFields).not.toContain('brand');
});
});
describe('Database Schema Consistency', () => {
let pool: Pool;
beforeAll(() => {
pool = new Pool({
connectionString,
ssl: { rejectUnauthorized: false }
});
});
afterAll(async () => {
await pool.end();
});
it('should have correct columns in database', async () => {
const result = await pool.query(`
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'filaments'
ORDER BY ordinal_position
`);
const columns = result.rows.map(row => row.column_name);
const columnTypes = result.rows.reduce((acc, row) => {
acc[row.column_name] = row.data_type;
return acc;
}, {} as Record<string, string>);
// Check all expected columns exist
DB_STRUCTURE.columns.forEach(col => {
expect(columns).toContain(col);
});
// Check no excluded columns exist
DB_STRUCTURE.excludedColumns.forEach(col => {
expect(columns).not.toContain(col);
});
// Check column types match
Object.entries(DB_STRUCTURE.columnTypes).forEach(([col, type]) => {
expect(columnTypes[col]).toBe(type);
});
});
it('should not have brand column', async () => {
const result = await pool.query(`
SELECT COUNT(*) as count
FROM information_schema.columns
WHERE table_name = 'filaments' AND column_name = 'brand'
`);
expect(parseInt(result.rows[0].count)).toBe(0);
});
});
describe('Frontend Consistency', () => {
it('should transform fields correctly between admin and database', () => {
// All fields now use snake_case consistently
const snakeCaseFields = {
'boja_hex': 'boja_hex',
'created_at': 'created_at',
'updated_at': 'updated_at'
};
Object.entries(snakeCaseFields).forEach(([adminField, dbField]) => {
expect(ADMIN_STRUCTURE.fields).toContain(adminField);
expect(DB_STRUCTURE.columns).toContain(dbField);
});
});
it('should handle quantity fields correctly', () => {
// Admin form shows refill, spulna as numbers
// Database stores them as strings like "2", "1 spulna"
const quantityFields = ['refill', 'spulna'];
quantityFields.forEach(field => {
expect(ADMIN_STRUCTURE.fieldTypes[field]).toBe('number');
expect(DB_STRUCTURE.columnTypes[field]).toBe('integer');
});
});
});
describe('API Consistency', () => {
it('should handle requests without brand field', () => {
const validRequest = {
tip: 'PLA',
finish: 'Basic',
boja: 'Black',
boja_hex: '#000000',
refill: '2',
spulna: '1 spulna',
kolicina: '3',
cena: '3999'
};
// Should not have brand
expect(validRequest).not.toHaveProperty('brand');
// Should have all required fields
expect(validRequest).toHaveProperty('tip');
expect(validRequest).toHaveProperty('finish');
expect(validRequest).toHaveProperty('boja');
});
});
describe('Data Flow Consistency', () => {
it('should maintain consistent data flow: Admin → API → Database', () => {
// Admin form data
const adminData = {
tip: 'PLA',
finish: 'Basic',
boja: 'Black',
boja_hex: '#000000',
refill: '2',
spulna: '1 spulna',
kolicina: '3',
cena: '3999'
};
// No transformation needed - using boja_hex consistently
const apiData = adminData;
// Database expected data
expect(apiData).toHaveProperty('boja_hex');
// No longer have bojaHex field
expect(apiData).not.toHaveProperty('brand');
});
});
});