162 lines
5.5 KiB
JavaScript
162 lines
5.5 KiB
JavaScript
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { GameObjectsManager } from './GameObjectsManager.js';
|
|
|
|
// backend/app/bl/GameObjectsManager.test.js
|
|
|
|
// --- Mocks ---
|
|
vi.mock('fs', () => ({
|
|
default: {
|
|
promises: {
|
|
copyFile: vi.fn().mockResolvedValue(),
|
|
unlink: vi.fn().mockResolvedValue(),
|
|
}
|
|
}
|
|
}));
|
|
vi.mock('path', () => ({
|
|
default: {
|
|
extname: vi.fn((name) => {
|
|
const m = name.match(/\.[^.]+$/);
|
|
return m ? m[0] : '';
|
|
})
|
|
}
|
|
}));
|
|
vi.mock('decompress', () => ({
|
|
__esModule: true,
|
|
default: vi.fn().mockResolvedValue([{ path: 'file.gltf' }])
|
|
}));
|
|
vi.mock('sharp', () => {
|
|
const sharpMock = vi.fn(() => ({
|
|
resize: vi.fn().mockReturnThis(),
|
|
toFile: vi.fn().mockResolvedValue()
|
|
}));
|
|
sharpMock.cache = vi.fn();
|
|
return { __esModule: true, default: sharpMock };
|
|
});
|
|
vi.mock('node:util', () => ({
|
|
default: {},
|
|
promisify: (fn) => vi.fn().mockResolvedValue()
|
|
}));
|
|
vi.mock('child_process', () => ({
|
|
execFile: vi.fn()
|
|
}));
|
|
|
|
// --- Test helpers ---
|
|
function createMockDb() {
|
|
let store = {};
|
|
let lastId = 0;
|
|
return {
|
|
getLastId: vi.fn(async () => lastId),
|
|
create: vi.fn(async (coll, obj) => { lastId++; obj.id = lastId; store[obj.id] = { ...obj }; }),
|
|
get: vi.fn(async (coll, query) => store[query.id]),
|
|
update: vi.fn(async (coll, query, obj) => { store[query.id] = { ...store[query.id], ...obj }; }),
|
|
remove: vi.fn(async (coll, query) => { delete store[query.id]; }),
|
|
list: vi.fn(async (coll, { query }) => Object.values(store).filter(o => !query || o.id === query.id)),
|
|
_store: store
|
|
};
|
|
}
|
|
function createMockConfig() {
|
|
return {
|
|
fs: {
|
|
repo: '/mockrepo'
|
|
}
|
|
};
|
|
}
|
|
|
|
// --- Tests ---
|
|
describe('GameObjectsManager', () => {
|
|
let manager, app, db, config;
|
|
|
|
beforeEach(() => {
|
|
db = createMockDb();
|
|
config = createMockConfig();
|
|
app = { db, config };
|
|
manager = new GameObjectsManager();
|
|
manager.init(app);
|
|
});
|
|
|
|
it('should create a game object and assign an ID', async () => {
|
|
const ctx = {};
|
|
const data = { name: 'TestObj' };
|
|
const result = await manager.create(ctx, data);
|
|
expect(result.id).toBe(1);
|
|
expect(db.create).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call addFile and update if ctx.files.file is present', async () => {
|
|
const ctx = { files: { file: { name: 'file.png', path: '/tmp/file.png' } } };
|
|
const data = { name: 'WithFile' };
|
|
const spy = vi.spyOn(manager, 'addFile').mockResolvedValue();
|
|
await manager.create(ctx, data);
|
|
expect(spy).toHaveBeenCalled();
|
|
expect(db.update).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should read a game object by ID', async () => {
|
|
const ctx = {};
|
|
const data = { name: 'ReadObj' };
|
|
await manager.create(ctx, data);
|
|
const obj = await manager.read(1);
|
|
expect(obj.name).toBe('ReadObj');
|
|
});
|
|
|
|
it('should update a game object and call addFile/addThumb if files present', async () => {
|
|
const ctx = {};
|
|
const data = { name: 'UpdateObj' };
|
|
await manager.create(ctx, data);
|
|
const ctx2 = { files: { file: { name: 'file.png', path: '/tmp/file.png' }, thumb: { path: '/tmp/thumb.png' } } };
|
|
const spyFile = vi.spyOn(manager, 'addFile').mockResolvedValue();
|
|
const spyThumb = vi.spyOn(manager, 'addThumb').mockResolvedValue();
|
|
await manager.update(ctx2, { id: 1, name: 'Updated' });
|
|
expect(spyFile).toHaveBeenCalled();
|
|
expect(spyThumb).toHaveBeenCalled();
|
|
expect(db.update).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should remove a game object by ID', async () => {
|
|
const ctx = {};
|
|
const data = { name: 'RemoveObj' };
|
|
await manager.create(ctx, data);
|
|
await manager.remove(1);
|
|
expect(db.remove).toHaveBeenCalledWith('assets', { id: 1 });
|
|
});
|
|
|
|
it('should call sharp for image thumb in addThumb', async () => {
|
|
const sharp = (await import('sharp')).default;
|
|
const object = { asset: {} };
|
|
await manager.addThumb(object, '/tmp/thumb.png');
|
|
expect(sharp).toHaveBeenCalled();
|
|
expect(object.asset.thumb).toBeDefined();
|
|
});
|
|
|
|
it('should call execFile for video thumb in addThumb', async () => {
|
|
const util = await import('node:util');
|
|
const object = { asset: {} };
|
|
await manager.addThumb(object, '/tmp/video.mp4');
|
|
expect(object.asset.thumb).toBeDefined();
|
|
});
|
|
|
|
it('should call decompress for .zip in addFile', async () => {
|
|
const decompress = (await import('decompress')).default;
|
|
const object = {};
|
|
const tmpFile = { name: 'archive.zip', path: '/tmp/archive.zip' };
|
|
await manager.addFile(object, tmpFile);
|
|
expect(decompress).toHaveBeenCalled();
|
|
expect(object.asset.type).toBe('bundle');
|
|
});
|
|
|
|
it('should call addThumb for image/video in addFile', async () => {
|
|
const spy = vi.spyOn(manager, 'addThumb').mockResolvedValue();
|
|
const object = {};
|
|
const tmpFile = { name: 'pic.png', path: '/tmp/pic.png' };
|
|
await manager.addFile(object, tmpFile);
|
|
expect(spy).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should list game objects', async () => {
|
|
await manager.create({}, { name: 'Obj1' });
|
|
await manager.create({}, { name: 'Obj2' });
|
|
const list = await manager.list({});
|
|
expect(Array.isArray(list)).toBe(true);
|
|
expect(list.length).toBe(2);
|
|
});
|
|
}); |