e115934061
Publish `@librechat/data-schemas` to NPM / pack (push) Failing after 8s
Publish `@librechat/client` to NPM / pack (push) Failing after 0s
GitNexus Index / index (push) Failing after 1s
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Has been skipped
Sync Helm Chart Tags / Sync chart tags (push) Failing after 2s
Publish `librechat-data-provider` to NPM / pack (push) Failing after 1s
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Failing after 1s
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Failing after 0s
Sync Helm Chart Tags / Ignore non-main push (push) Has been skipped
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Failing after 1s
Publish `@librechat/client` to NPM / publish-npm (push) Has been cancelled
Publish `librechat-data-provider` to NPM / publish-npm (push) Has been cancelled
GitNexus Index / post-index (push) Has been cancelled
Publish `@librechat/data-schemas` to NPM / publish-npm (push) Has been cancelled
120 lines
4.3 KiB
JavaScript
120 lines
4.3 KiB
JavaScript
const express = require('express');
|
|
const request = require('supertest');
|
|
|
|
const mockRequireJwtAuth = jest.fn((req, res, next) => {
|
|
req.user = { id: 'user-1', role: 'ADMIN', tenantId: 'tenant-a' };
|
|
next();
|
|
});
|
|
const mockCapabilityMiddleware = jest.fn((req, res, next) => next());
|
|
const mockRequireCapability = jest.fn(() => mockCapabilityMiddleware);
|
|
const mockHasCapability = jest.fn().mockResolvedValue(true);
|
|
const mockConfigMiddleware = jest.fn((req, res, next) => {
|
|
req.config = { skillSync: { github: { enabled: false, sources: [] } } };
|
|
next();
|
|
});
|
|
const mockGetAppConfig = jest.fn();
|
|
const mockGetGitHubSkillSyncRunnerForRequest = jest.fn();
|
|
const mockHandlers = {
|
|
getSyncStatus: jest.fn((req, res) => res.status(200).json({ ok: true })),
|
|
runSync: jest.fn((req, res) => res.status(200).json({ ok: true })),
|
|
setCredential: jest.fn((req, res) => res.status(200).json({ ok: true })),
|
|
deleteCredential: jest.fn((req, res) => res.status(200).json({ ok: true })),
|
|
};
|
|
const mockSyncAccess = {
|
|
attachBaseSkillSyncConfig: jest.fn((req, res, next) => next()),
|
|
requireReadSkills: jest.fn((req, res, next) => next()),
|
|
attachCredentialReadAccess: jest.fn((req, res, next) => next()),
|
|
requireSyncRunCapability: jest.fn((req, res, next) => next()),
|
|
requirePlatformManageSkills: jest.fn((req, res, next) => next()),
|
|
};
|
|
|
|
jest.mock('@librechat/data-schemas', () => ({
|
|
SystemCapabilities: {
|
|
ACCESS_ADMIN: 'access:admin',
|
|
},
|
|
}));
|
|
|
|
jest.mock('@librechat/api', () => ({
|
|
createAdminSkillsSyncAccess: jest.fn(() => mockSyncAccess),
|
|
createAdminSkillsSyncHandlers: jest.fn(() => mockHandlers),
|
|
}));
|
|
|
|
jest.mock('~/server/middleware/roles/capabilities', () => ({
|
|
hasCapability: mockHasCapability,
|
|
requireCapability: mockRequireCapability,
|
|
}));
|
|
|
|
jest.mock('~/server/middleware', () => ({
|
|
requireJwtAuth: mockRequireJwtAuth,
|
|
}));
|
|
|
|
jest.mock('~/server/middleware/config/app', () => mockConfigMiddleware);
|
|
|
|
jest.mock('~/server/services/Config', () => ({
|
|
getAppConfig: mockGetAppConfig,
|
|
}));
|
|
|
|
jest.mock('~/models', () => ({
|
|
upsertSkillSyncCredential: jest.fn(),
|
|
deleteSkillSyncCredential: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('~/server/services/Skills/sync', () => ({
|
|
getGitHubSkillSyncRunnerForRequest: mockGetGitHubSkillSyncRunnerForRequest,
|
|
}));
|
|
|
|
describe('admin skills sync routes', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
function createApp() {
|
|
delete require.cache[require.resolve('./skills')];
|
|
const router = require('./skills');
|
|
const app = express();
|
|
app.use(express.json());
|
|
app.use('/api/admin/skills', router);
|
|
return app;
|
|
}
|
|
|
|
it('delegates skill sync access policy to the API package', async () => {
|
|
const app = createApp();
|
|
|
|
await request(app).get('/api/admin/skills/sync/status').expect(200);
|
|
|
|
const {
|
|
createAdminSkillsSyncAccess,
|
|
createAdminSkillsSyncHandlers,
|
|
} = require('@librechat/api');
|
|
expect(mockRequireCapability).toHaveBeenCalledWith('access:admin');
|
|
expect(createAdminSkillsSyncAccess).toHaveBeenCalledWith({
|
|
getAppConfig: mockGetAppConfig,
|
|
hasCapability: mockHasCapability,
|
|
});
|
|
expect(createAdminSkillsSyncHandlers).toHaveBeenCalledWith(
|
|
expect.objectContaining({ getRunner: mockGetGitHubSkillSyncRunnerForRequest }),
|
|
);
|
|
expect(mockRequireJwtAuth).toHaveBeenCalled();
|
|
expect(mockCapabilityMiddleware).toHaveBeenCalled();
|
|
expect(mockConfigMiddleware).toHaveBeenCalled();
|
|
expect(mockSyncAccess.attachBaseSkillSyncConfig).toHaveBeenCalled();
|
|
expect(mockSyncAccess.requireReadSkills).toHaveBeenCalled();
|
|
expect(mockSyncAccess.attachCredentialReadAccess).toHaveBeenCalled();
|
|
expect(mockHandlers.getSyncStatus).toHaveBeenCalled();
|
|
});
|
|
|
|
it('mounts package access middlewares before each sync endpoint handler', async () => {
|
|
const app = createApp();
|
|
|
|
await request(app).post('/api/admin/skills/sync/run').expect(200);
|
|
await request(app).put('/api/admin/skills/sync/credentials/default').send({}).expect(200);
|
|
await request(app).delete('/api/admin/skills/sync/credentials/default').expect(200);
|
|
|
|
expect(mockSyncAccess.requireSyncRunCapability).toHaveBeenCalled();
|
|
expect(mockHandlers.runSync).toHaveBeenCalled();
|
|
expect(mockSyncAccess.requirePlatformManageSkills).toHaveBeenCalledTimes(2);
|
|
expect(mockHandlers.setCredential).toHaveBeenCalled();
|
|
expect(mockHandlers.deleteCredential).toHaveBeenCalled();
|
|
});
|
|
});
|