Files
Filamenteka/__tests__/data-consistency.test.ts
DaX 58b3ff2dec Remove otvoreno field references from all test files
- Updated ui-features.test.ts to remove otvoreno field expectations
- Updated api-integration.test.ts to remove otvoreno from test data
- Updated data-consistency.test.ts to remove otvoreno from structure definitions
- Updated filament-crud.test.ts to remove otvoreno from CRUD operations
- Updated quantity calculations to only use refill and vakuum fields

All tests pass after these changes.

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

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

233 lines
6.5 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',
'bojaHex', // Frontend uses camelCase
'refill',
'vakum',
'kolicina',
'cena',
'createdAt',
'updatedAt'
],
requiredFields: ['tip', 'finish', 'boja'],
excludedFields: ['brand'], // Should NOT exist
fieldTypes: {
tip: 'string',
finish: 'string',
boja: 'string',
bojaHex: 'string',
refill: 'string',
vakum: 'string',
kolicina: 'string',
cena: 'string'
}
};
// Database expected structure
const DB_STRUCTURE = {
columns: [
'id',
'tip',
'finish',
'boja',
'boja_hex', // Database uses snake_case
'refill',
'vakum',
'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: 'character varying',
vakum: 'character varying',
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', 'bojaHex', 'boja_hex',
'refill', 'vakum', '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', 'bojaHex',
'refill', 'vakum', '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', () => {
// Admin uses camelCase, DB uses snake_case
const transformations = {
'bojaHex': 'boja_hex',
'createdAt': 'created_at',
'updatedAt': 'updated_at'
};
Object.entries(transformations).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, vakuum as numbers
// Database stores them as strings like "2", "1 vakuum"
const quantityFields = ['refill', 'vakum'];
quantityFields.forEach(field => {
expect(ADMIN_STRUCTURE.fieldTypes[field]).toBe('string');
expect(DB_STRUCTURE.columnTypes[field]).toBe('character varying');
});
});
});
describe('API Consistency', () => {
it('should handle requests without brand field', () => {
const validRequest = {
tip: 'PLA',
finish: 'Basic',
boja: 'Black',
boja_hex: '#000000',
refill: '2',
vakum: '1 vakuum',
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',
bojaHex: '#000000',
refill: '2',
vakum: '1 vakuum',
kolicina: '3',
cena: '3999'
};
// API transformation (in services/api.ts)
const apiData = {
...adminData,
boja_hex: adminData.bojaHex
};
delete (apiData as any).bojaHex;
// Database expected data
expect(apiData).toHaveProperty('boja_hex');
expect(apiData).not.toHaveProperty('bojaHex');
expect(apiData).not.toHaveProperty('brand');
});
});
});