Skip to content
Snippets Groups Projects
Commit 4cca6a46 authored by Embruch, Gerd's avatar Embruch, Gerd
Browse files

finished testing route ai/delete

parent 0ca0b801
Branches
No related tags found
No related merge requests found
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ai delete model > given a user tries to access > should respond with a proper body 1`] = `
{
"message": "Access Forbidden",
}
`;
exports[`ai delete model > given no jwt sended > should respond with a proper body 1`] = `
{
"message": "No access token found. Access denied.",
}
`;
exports[`ai delete model > given no matching model found > should respond with a proper body 1`] = `
{
"message": "pull model manifest: file does not exist",
}
`;
exports[`ai delete model > given no valid jwt sended > should respond with a proper body 1`] = `
{
"message": "Access token is no longer valid. Access denied.",
}
`;
exports[`ai delete model > given required fields are missing > should respond with a proper body 1`] = `
{
"message": "Validation errors. Please check the error messages.",
"validationErrors": {
"model": "Required",
},
}
`;
exports[`ai delete model > given the inputs are valid > should respond with a proper body 1`] = `
{
"status": "success",
}
`;
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest'; import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest';
import supertest from "supertest"; import supertest from "supertest";
import app from "../../app.js"; import app from "../../app.js";
// ignore expiration of the (self-signed) certificate import jwt from 'jsonwebtoken';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
// set timeout
const BEFORE_ALL_TIMEOUT = 30000; // 30 sec
// set route // set route
const ROUTE = '/ai/models'; const ROUTE = '/ai/models';
// prepare response of each test // prepare response of each test
...@@ -14,27 +12,37 @@ let response; ...@@ -14,27 +12,37 @@ let response;
// ############################ // ############################
// OBJECTS // OBJECTS
// ############################ // ############################
const mockedVals = vi.hoisted(() => {
const noModelFoundResponse = { return {
code: 500, foundUser: {
message: "no such file or directory", _id: '66a29da2942b3eb',
data: {} username: 'snoopy',
name: 'My User',
email: 'user@mail.local',
verified: true,
role: 4,
createdAt: '2024-07 - 25T18: 46: 58.982Z',
updatedAt: '2024-07 - 25T18: 46: 58.982Z',
__v: 0,
fullname: '',
id: '66a29da2942b3ebcaf047f07'
},
validInput: {
model: 'llama3'
}
}; };
});
// ############################ // ############################
// MOCKS // MOCKS
// ############################ // ############################
// import PocketBase Service import * as dbService from '../../utils/handleDB.js';
import * as pbService from '../../utils/pocketbase/handlePocketBase.js'; // mock dbService
// mock pbService vi.mock('../../utils/handleDB.js', async (importOriginal) => {
vi.mock('../../utils/pocketbase/handlePocketBase.js', async (importOriginal) => {
return { return {
...await importOriginal(), ...await importOriginal(),
pbVerifyAccessToken: vi.fn().mockImplementation((req, res, next) => { dbConnection: vi.fn(() => 'mocked'),
next(); findOneRecord: vi.fn(() => mockedVals.foundUser),
}),
gateKeeper: vi.fn().mockImplementation((req, res, next) => {
return next();
})
}; };
}); });
...@@ -53,103 +61,127 @@ vi.mock('../../utils/handleAI.js', async (importOriginal) => { ...@@ -53,103 +61,127 @@ vi.mock('../../utils/handleAI.js', async (importOriginal) => {
// ############################ // ############################
describe('ai delete model', () => { describe('ai delete model', () => {
const _jwt = (id, role) => {
return jwt.sign({ id, role }, process.env.JWT_SECRET_KEY, { expiresIn: process.env.JWT_TTL });
};
describe('given the inputs are valid', async () => { describe('given the inputs are valid', async () => {
beforeAll(async () => {
response = await supertest(app) response = await supertest(app)
.delete(ROUTE) .delete(ROUTE)
.set('Authorization', 'Bearer 123valid') .set('Authorization', `Bearer ${_jwt(mockedVals.foundUser.id, mockedVals.foundUser.role)}`)
.send({ model: 'validModelName' }); .send(mockedVals.validInput);
it('should have called the gateKeeper', () => {
expect(pbService.gateKeeper).toHaveBeenCalledTimes(1);
}); });
it('should return a proper status code', () => {
it('should return a proper status code status', () => {
expect(response.status).toBe(200); expect(response.status).toBe(200);
}); });
it('should respond with a proper message', () => { it('should respond with a proper body', () => {
expect(response.body).toEqual({ status: 'success' }); expect(response.body).toMatchSnapshot();
}); });
}); });
// ############################ // ############################
describe('given no valid JWT sent', () => { describe('given no matching model found', () => {
beforeAll(async () => { beforeAll(async () => {
pbService.pbVerifyAccessToken.mockImplementationOnce((req, res, next) => { const input = { ...mockedVals.validInput, model: 'unknownModel' };
return res.status(403).json({ message: 'You are not logged in.' });
}); let error = new Error("pull model manifest: file does not exist");
error.name = 'ResponseError';
error.status = 500;
aiService.aiDeleteModel.mockImplementation(() => { throw error; });
response = await supertest(app) response = await supertest(app)
.delete(ROUTE) .delete(ROUTE)
.send({ model: 'validModelName' }); .set('Authorization', `Bearer ${_jwt(mockedVals.foundUser.id, mockedVals.foundUser.role)}`)
}, BEFORE_ALL_TIMEOUT); .send(input);
it('should return a proper status code', () => {
expect(response.status).toBe(403);
}); });
it('should respond with a proper message', () => {
expect(response.body.message).toEqual('You are not logged in.'); it('should return a proper status code status', () => {
expect(response.status).toBe(500);
});
it('should respond with a proper body', () => {
expect(response.body).toMatchSnapshot();
}); });
}); });
// ############################ // ############################
describe('given no access granted', () => { describe('given required fields are missing', () => {
beforeAll(async () => { beforeAll(async () => {
pbService.gateKeeper.mockImplementationOnce((req, res, next) => { const { model, ...input } = mockedVals.validInput;
return res.status(403).json({ message: 'Access Forbidden' });
response = await supertest(app)
.delete(ROUTE)
.set('Authorization', `Bearer ${_jwt(mockedVals.foundUser.id, mockedVals.foundUser.role)}`)
.send(input);
});
it('should return a proper status code status', () => {
expect(response.status).toBe(400);
});
it('should respond with a proper body', () => {
expect(response.body).toMatchSnapshot();
});
});
// ############################
describe('given a user tries to access', () => {
beforeAll(async () => {
dbService.findOneRecord.mockImplementationOnce(async () => {
return { ...mockedVals.foundUser, role: 0 };
}); });
response = await supertest(app) response = await supertest(app)
.delete(ROUTE) .delete(ROUTE)
.set('Authorization', 'Bearer 123valid'); .set('Authorization', `Bearer ${_jwt(mockedVals.foundUser.id, 0)}`)
}, BEFORE_ALL_TIMEOUT); .send(mockedVals.validInput);
});
it('should return a proper status code', () => { it('should return a proper status code status', () => {
expect(response.status).toBe(403); expect(response.status).toBe(403);
}); });
it('should respond with a proper message', () => { it('should respond with a proper body', () => {
expect(response.body.message).toEqual('Access Forbidden'); expect(response.body).toMatchSnapshot();
}); });
}); });
// ############################ // ############################
describe('given no model name sent', () => { describe('given no valid jwt sended', () => {
beforeAll(async () => { beforeAll(async () => {
response = await supertest(app) response = await supertest(app)
.delete(ROUTE) .delete(ROUTE)
.set('Authorization', 'Bearer 123valid'); .set('Authorization', `Bearer invalid`)
}, BEFORE_ALL_TIMEOUT); .send(mockedVals.validInput);
it('should return a proper status code', () => { });
expect(response.status).toBe(400);
it('should return a proper status code status', () => {
expect(response.status).toBe(403);
}); });
it('should respond with a proper message', () => { it('should respond with a proper body', () => {
expect(response.body.validationErrors.model).toEqual('Required'); expect(response.body).toMatchSnapshot();
}); });
}); });
// ############################ // ############################
describe('given no matching model found', () => { describe('given no jwt sended', () => {
beforeAll(async () => { beforeAll(async () => {
let error = new Error('no such file or directory');
error.name = 'ResponseError';
error.response = noModelFoundResponse;
error.status = 500;
aiService.aiDeleteModel.mockImplementation(() => { throw error; });
response = await supertest(app) response = await supertest(app)
.delete(ROUTE) .delete(ROUTE)
.set('Authorization', 'Bearer 123valid') .send(mockedVals.validInput);
.send({ model: 'invalidModelName' });
}, BEFORE_ALL_TIMEOUT);
it('should force aiDeleteModel to throw an error', () => {
expect(aiService.aiDeleteModel).toThrowError();
}); });
it('should return a proper status code', () => {
expect(response.status).toBe(500); it('should return a proper status code status', () => {
expect(response.status).toBe(401);
}); });
it('should respond with a proper message', () => { it('should respond with a proper body', () => {
expect(response.body.message).toEqual('no such file or directory'); expect(response.body).toMatchSnapshot();
}); });
}); });
......
...@@ -48,7 +48,7 @@ Accept: application/json ...@@ -48,7 +48,7 @@ Accept: application/json
Content-Type: application/json Content-Type: application/json
{ {
"filter": "bai" "filter": ""
} }
### show info of a specific model ### show info of a specific model
......
...@@ -29,10 +29,6 @@ export const getStatus = async (req, res, next) => { ...@@ -29,10 +29,6 @@ export const getStatus = async (req, res, next) => {
export const getModels = async (req, res, next) => { export const getModels = async (req, res, next) => {
try { try {
const foundModels = await aiFilterModelsByName(req.body.filter); const foundModels = await aiFilterModelsByName(req.body.filter);
console.log("🚀 ~ getModels ~ foundModels:", foundModels);
return res.json(foundModels); return res.json(foundModels);
} catch (error) { } catch (error) {
next(error); next(error);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment