- 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>
200 lines
5.7 KiB
TypeScript
200 lines
5.7 KiB
TypeScript
// Mock axios before importing services
|
|
jest.mock('axios', () => ({
|
|
create: jest.fn(() => ({
|
|
interceptors: {
|
|
request: { use: jest.fn() },
|
|
response: { use: jest.fn() }
|
|
},
|
|
get: jest.fn(),
|
|
post: jest.fn(),
|
|
put: jest.fn(),
|
|
delete: jest.fn()
|
|
}))
|
|
}));
|
|
|
|
import { filamentService, authService } from '../src/services/api';
|
|
|
|
describe('Filament CRUD Operations', () => {
|
|
let authToken: string;
|
|
|
|
beforeAll(async () => {
|
|
// Mock successful login
|
|
jest.spyOn(authService, 'login').mockResolvedValue({ token: 'test-token' });
|
|
const loginResponse = await authService.login('admin', 'admin123');
|
|
authToken = loginResponse.token;
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('Create Filament', () => {
|
|
it('should create a new filament without brand field', async () => {
|
|
const newFilament = {
|
|
tip: 'PLA',
|
|
finish: 'Basic',
|
|
boja: 'Black',
|
|
boja_hex: '#000000',
|
|
refill: '2',
|
|
spulna: '1 spulna',
|
|
kolicina: '3',
|
|
cena: '3999'
|
|
};
|
|
|
|
const mockResponse = {
|
|
id: '123',
|
|
...newFilament,
|
|
boja_hex: '#000000',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
jest.spyOn(filamentService, 'create').mockResolvedValue(mockResponse);
|
|
|
|
const result = await filamentService.create(newFilament);
|
|
|
|
expect(result).toEqual(mockResponse);
|
|
expect(filamentService.create).toHaveBeenCalledWith(newFilament);
|
|
|
|
// Verify no brand field was sent
|
|
const callArg = (filamentService.create as jest.Mock).mock.calls[0][0];
|
|
expect(callArg).not.toHaveProperty('brand');
|
|
});
|
|
|
|
it('should use boja_hex field directly', async () => {
|
|
const filamentWithHex = {
|
|
tip: 'PETG',
|
|
finish: 'Silk',
|
|
boja: 'Red',
|
|
boja_hex: '#FF0000',
|
|
refill: 'Ne',
|
|
spulna: 'Ne',
|
|
kolicina: '1',
|
|
cena: '4500'
|
|
};
|
|
|
|
// Spy on the actual implementation
|
|
const createSpy = jest.spyOn(filamentService, 'create');
|
|
|
|
// We can't test the actual transformation without a real axios call,
|
|
// but we can verify the method is called correctly
|
|
await expect(async () => {
|
|
await filamentService.create(filamentWithHex);
|
|
}).not.toThrow();
|
|
|
|
expect(createSpy).toHaveBeenCalledWith(filamentWithHex);
|
|
});
|
|
});
|
|
|
|
describe('Update Filament', () => {
|
|
it('should update a filament without brand field', async () => {
|
|
const filamentId = '123';
|
|
const updateData = {
|
|
tip: 'ABS',
|
|
finish: 'Matte',
|
|
boja: 'Blue',
|
|
boja_hex: '#0000FF',
|
|
refill: '1',
|
|
spulna: '2 spulna',
|
|
kolicina: '4',
|
|
cena: '5000'
|
|
};
|
|
|
|
const mockResponse = {
|
|
id: filamentId,
|
|
...updateData,
|
|
boja_hex: '#0000FF',
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
jest.spyOn(filamentService, 'update').mockResolvedValue(mockResponse);
|
|
|
|
const result = await filamentService.update(filamentId, updateData);
|
|
|
|
expect(result).toEqual(mockResponse);
|
|
expect(filamentService.update).toHaveBeenCalledWith(filamentId, updateData);
|
|
|
|
// Verify no brand field was sent
|
|
const callArgs = (filamentService.update as jest.Mock).mock.calls[0];
|
|
expect(callArgs[1]).not.toHaveProperty('brand');
|
|
});
|
|
});
|
|
|
|
describe('Delete Filament', () => {
|
|
it('should delete a filament by ID', async () => {
|
|
const filamentId = '123';
|
|
const mockResponse = { success: true };
|
|
|
|
jest.spyOn(filamentService, 'delete').mockResolvedValue(mockResponse);
|
|
|
|
const result = await filamentService.delete(filamentId);
|
|
|
|
expect(result).toEqual(mockResponse);
|
|
expect(filamentService.delete).toHaveBeenCalledWith(filamentId);
|
|
});
|
|
});
|
|
|
|
describe('Get All Filaments', () => {
|
|
it('should retrieve all filaments with boja_hex field', async () => {
|
|
const mockFilaments = [
|
|
{
|
|
id: '1',
|
|
tip: 'PLA',
|
|
finish: 'Basic',
|
|
boja: 'Black',
|
|
boja_hex: '#000000',
|
|
refill: '2',
|
|
spulna: '1 spulna',
|
|
kolicina: '3',
|
|
cena: '3999'
|
|
},
|
|
{
|
|
id: '2',
|
|
tip: 'PETG',
|
|
finish: 'Silk',
|
|
boja: 'Red',
|
|
boja_hex: '#FF0000',
|
|
refill: 'Ne',
|
|
spulna: 'Ne',
|
|
kolicina: '1',
|
|
cena: '4500'
|
|
}
|
|
];
|
|
|
|
// No transformation needed anymore - we use boja_hex directly
|
|
const expectedFilaments = mockFilaments;
|
|
|
|
jest.spyOn(filamentService, 'getAll').mockResolvedValue(expectedFilaments);
|
|
|
|
const result = await filamentService.getAll();
|
|
|
|
expect(result).toEqual(expectedFilaments);
|
|
expect(result[0]).toHaveProperty('boja_hex', '#000000');
|
|
expect(result[1]).toHaveProperty('boja_hex', '#FF0000');
|
|
});
|
|
});
|
|
|
|
describe('Quantity Calculations', () => {
|
|
it('should correctly calculate total quantity from refill and spulna', () => {
|
|
const testCases = [
|
|
{ refill: '2', spulna: '1 spulna', expected: 3 },
|
|
{ refill: 'Ne', spulna: '3 spulna', expected: 3 },
|
|
{ refill: '1', spulna: 'Ne', expected: 1 },
|
|
{ refill: 'Da', spulna: 'spulna', expected: 2 }
|
|
];
|
|
|
|
testCases.forEach(({ refill, spulna, expected }) => {
|
|
// Parse refill
|
|
const refillCount = parseInt(refill) || (refill?.toLowerCase() === 'da' ? 1 : 0);
|
|
|
|
// Parse spulna
|
|
const vakuumMatch = spulna?.match(/^(\d+)\s*spulna/);
|
|
const vakuumCount = vakuumMatch ? parseInt(vakuumMatch[1]) : (spulna?.toLowerCase().includes('spulna') ? 1 : 0);
|
|
|
|
const total = refillCount + vakuumCount;
|
|
|
|
expect(total).toBe(expected);
|
|
});
|
|
});
|
|
});
|
|
}); |