mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-07-10 00:03:03 +00:00
test: remove unrelated suite stabilization
This commit is contained in:
parent
affd0194b2
commit
16d5fa63b3
10 changed files with 140 additions and 197 deletions
|
|
@ -27,27 +27,23 @@ describe('Convos Routes', () => {
|
|||
deleteConvoSharedLinksWithCleanup,
|
||||
} = require('@librechat/api');
|
||||
|
||||
const createApp = (userId = 'test-user-123') => {
|
||||
const testApp = express();
|
||||
testApp.use(express.json());
|
||||
beforeAll(() => {
|
||||
convosRouter = require('../convos');
|
||||
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
|
||||
/** Mock authenticated user */
|
||||
testApp.use((req, res, next) => {
|
||||
req.user = { id: userId };
|
||||
app.use((req, res, next) => {
|
||||
req.user = { id: 'test-user-123' };
|
||||
next();
|
||||
});
|
||||
|
||||
testApp.use('/api/convos', convosRouter);
|
||||
return testApp;
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
convosRouter = require('../convos');
|
||||
app.use('/api/convos', convosRouter);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
app = createApp();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('DELETE /all', () => {
|
||||
|
|
@ -150,7 +146,13 @@ describe('Convos Routes', () => {
|
|||
jest.clearAllMocks();
|
||||
|
||||
/** Second user (simulate different user by modifying middleware) */
|
||||
const app2 = createApp('test-user-456');
|
||||
const app2 = express();
|
||||
app2.use(express.json());
|
||||
app2.use((req, res, next) => {
|
||||
req.user = { id: 'test-user-456' };
|
||||
next();
|
||||
});
|
||||
app2.use('/api/convos', require('../convos'));
|
||||
|
||||
deleteConvos.mockResolvedValue({ deletedCount: 7 });
|
||||
deleteToolCalls.mockResolvedValue({ deletedCount: 12 });
|
||||
|
|
|
|||
|
|
@ -25,16 +25,6 @@ jest.mock('@librechat/api', () => ({
|
|||
GenerationJobManager: mockGenerationJobManager,
|
||||
}));
|
||||
|
||||
jest.mock('@librechat/api/telemetry', () => ({
|
||||
createSseStreamTelemetry: jest.fn(() => ({
|
||||
recordHeadersFlushed: jest.fn(),
|
||||
recordWrite: jest.fn(),
|
||||
recordFinalEventEmitted: jest.fn(),
|
||||
recordErrorEventEmitted: jest.fn(),
|
||||
recordSubscribeFailed: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('~/models', () => ({
|
||||
saveMessage: jest.fn(),
|
||||
}));
|
||||
|
|
@ -77,8 +67,7 @@ function mockSubscribeSuccess() {
|
|||
|
||||
describe('SSE stream tenant isolation', () => {
|
||||
beforeEach(() => {
|
||||
Object.values(mockGenerationJobManager).forEach((mock) => mock.mockReset());
|
||||
mockGenerationJobManager.getActiveJobIdsForUser.mockResolvedValue([]);
|
||||
jest.clearAllMocks();
|
||||
mockUserId = 'user-123';
|
||||
mockTenantId = undefined;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ const mockLogger = {
|
|||
debug: jest.fn(),
|
||||
};
|
||||
|
||||
let mockOpenIDCallbackAuthenticatorOptions;
|
||||
const mockOAuthHandler = jest.fn((_req, res) => res.status(204).end());
|
||||
const mockOpenIDCallbackMiddleware = jest.fn((_req, _res, next) => next());
|
||||
const setMockOpenIDCallbackAuthenticator = (options) => {
|
||||
let mockOpenIDCallbackAuthenticatorOptions;
|
||||
const mockCreateOpenIDCallbackAuthenticator = jest.fn((options) => {
|
||||
mockOpenIDCallbackAuthenticatorOptions = options;
|
||||
return mockOpenIDCallbackMiddleware;
|
||||
};
|
||||
const mockCreateOpenIDCallbackAuthenticator = jest.fn(setMockOpenIDCallbackAuthenticator);
|
||||
const buildMockOAuthFailureLog = ({ provider, req, err, info, defaultMessage }) => ({
|
||||
});
|
||||
const mockBuildOAuthFailureLog = jest.fn(({ provider, req, err, info, defaultMessage }) => ({
|
||||
provider,
|
||||
code: err?.code ?? info?.code ?? info?.error ?? req.query?.error,
|
||||
name: err?.name ?? info?.name,
|
||||
|
|
@ -38,17 +37,17 @@ const buildMockOAuthFailureLog = ({ provider, req, err, info, defaultMessage })
|
|||
path: req.path,
|
||||
forwarded_for: req.headers?.['x-forwarded-for'],
|
||||
user_agent: req.headers?.['user-agent'],
|
||||
});
|
||||
const mockBuildOAuthFailureLog = jest.fn(buildMockOAuthFailureLog);
|
||||
const getMockOAuthFailureMessage = (req) =>
|
||||
req.session?.messages?.pop() ??
|
||||
req.query?.error_description ??
|
||||
req.query?.error ??
|
||||
'OAuth authentication failed';
|
||||
const mockGetOAuthFailureMessage = jest.fn(getMockOAuthFailureMessage);
|
||||
const redirectMockToAuthFailure = (res, { clientDomain, authFailedError }) =>
|
||||
res.redirect(`${clientDomain}/login?redirect=false&error=${authFailedError}`);
|
||||
const mockRedirectToAuthFailure = jest.fn(redirectMockToAuthFailure);
|
||||
}));
|
||||
const mockGetOAuthFailureMessage = jest.fn(
|
||||
(req) =>
|
||||
req.session?.messages?.pop() ??
|
||||
req.query?.error_description ??
|
||||
req.query?.error ??
|
||||
'OAuth authentication failed',
|
||||
);
|
||||
const mockRedirectToAuthFailure = jest.fn((res, { clientDomain, authFailedError }) =>
|
||||
res.redirect(`${clientDomain}/login?redirect=false&error=${authFailedError}`),
|
||||
);
|
||||
const mockPassportAuthenticate = jest.fn(() => (_req, _res, next) => next());
|
||||
|
||||
jest.mock('passport', () => ({
|
||||
|
|
@ -106,11 +105,8 @@ afterAll(() => {
|
|||
});
|
||||
|
||||
function getOAuthRouter() {
|
||||
let router;
|
||||
jest.isolateModules(() => {
|
||||
router = require('./oauth');
|
||||
});
|
||||
return router;
|
||||
jest.resetModules();
|
||||
return require('./oauth');
|
||||
}
|
||||
|
||||
function createApp(sessionMessages) {
|
||||
|
|
@ -130,17 +126,19 @@ function createApp(sessionMessages) {
|
|||
|
||||
describe('OAuth route failure logging', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
jest.clearAllMocks();
|
||||
process.env.DOMAIN_CLIENT = 'http://client.test';
|
||||
mockLogger.warn.mockClear();
|
||||
mockLogger.error.mockClear();
|
||||
mockLogger.info.mockClear();
|
||||
mockLogger.debug.mockClear();
|
||||
mockOAuthHandler.mockClear();
|
||||
mockOpenIDCallbackMiddleware.mockClear();
|
||||
mockBuildOAuthFailureLog.mockClear();
|
||||
mockGetOAuthFailureMessage.mockClear();
|
||||
mockRedirectToAuthFailure.mockClear();
|
||||
mockPassportAuthenticate.mockClear();
|
||||
mockOpenIDCallbackAuthenticatorOptions = undefined;
|
||||
mockPassportAuthenticate.mockImplementation(() => (_req, _res, next) => next());
|
||||
mockCreateOpenIDCallbackAuthenticator.mockImplementation(setMockOpenIDCallbackAuthenticator);
|
||||
mockOpenIDCallbackMiddleware.mockImplementation((_req, _res, next) => next());
|
||||
mockOAuthHandler.mockImplementation((_req, res) => res.status(204).end());
|
||||
mockBuildOAuthFailureLog.mockImplementation(buildMockOAuthFailureLog);
|
||||
mockGetOAuthFailureMessage.mockImplementation(getMockOAuthFailureMessage);
|
||||
mockRedirectToAuthFailure.mockImplementation(redirectMockToAuthFailure);
|
||||
});
|
||||
|
||||
it('wires the package OpenID callback middleware into the route', async () => {
|
||||
|
|
|
|||
|
|
@ -56,10 +56,6 @@ function setTestUser(app, user) {
|
|||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
if (mongoose.connection.readyState !== 0) {
|
||||
await mongoose.disconnect();
|
||||
}
|
||||
|
||||
mongoServer = await MongoMemoryServer.create();
|
||||
const mongoUri = mongoServer.getUri();
|
||||
await mongoose.connect(mongoUri);
|
||||
|
|
@ -101,10 +97,8 @@ beforeAll(async () => {
|
|||
// Set default user
|
||||
currentTestUser = testUsers.owner;
|
||||
|
||||
// Import routes after middleware is set up and test-local mocks are registered.
|
||||
jest.isolateModules(() => {
|
||||
promptRoutes = require('./prompts');
|
||||
});
|
||||
// Import routes after middleware is set up
|
||||
promptRoutes = require('./prompts');
|
||||
app.use('/api/prompts', promptRoutes);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +1,45 @@
|
|||
const dataSchemasMock = {
|
||||
logger: { info: jest.fn(), warn: jest.fn(), debug: jest.fn(), error: jest.fn() },
|
||||
getTenantId: jest.fn(() => undefined),
|
||||
DEFAULT_SESSION_EXPIRY: 900000,
|
||||
DEFAULT_REFRESH_TOKEN_EXPIRY: 604800000,
|
||||
};
|
||||
const dataProviderMock = {
|
||||
ErrorTypes: {},
|
||||
SystemRoles: { USER: 'USER', ADMIN: 'ADMIN' },
|
||||
errorsToString: jest.fn(),
|
||||
};
|
||||
const apiMock = {
|
||||
isEnabled: jest.fn((val) => val === 'true' || val === true),
|
||||
checkEmailConfig: jest.fn(),
|
||||
isEmailDomainAllowed: jest.fn(),
|
||||
math: jest.fn((val, fallback) => (val ? Number(val) : fallback)),
|
||||
shouldUseSecureCookie: jest.fn(() => false),
|
||||
resolveAppConfigForUser: jest.fn(async (_getAppConfig, _user) => ({})),
|
||||
setCloudFrontCookies: jest.fn(() => true),
|
||||
getCloudFrontConfig: jest.fn(() => ({
|
||||
domain: 'https://cdn.example.com',
|
||||
imageSigning: 'cookies',
|
||||
cookieDomain: '.example.com',
|
||||
privateKey: 'test-private-key',
|
||||
keyPairId: 'K123ABC',
|
||||
})),
|
||||
parseCloudFrontCookieScope: jest.fn(() => null),
|
||||
CLOUDFRONT_SCOPE_COOKIE: 'LibreChat-CloudFront-Scope',
|
||||
};
|
||||
const modelsMock = {
|
||||
jest.mock(
|
||||
'@librechat/data-schemas',
|
||||
() => ({
|
||||
logger: { info: jest.fn(), warn: jest.fn(), debug: jest.fn(), error: jest.fn() },
|
||||
getTenantId: jest.fn(() => undefined),
|
||||
DEFAULT_SESSION_EXPIRY: 900000,
|
||||
DEFAULT_REFRESH_TOKEN_EXPIRY: 604800000,
|
||||
}),
|
||||
{ virtual: true },
|
||||
);
|
||||
jest.mock(
|
||||
'librechat-data-provider',
|
||||
() => ({
|
||||
ErrorTypes: {},
|
||||
SystemRoles: { USER: 'USER', ADMIN: 'ADMIN' },
|
||||
errorsToString: jest.fn(),
|
||||
}),
|
||||
{ virtual: true },
|
||||
);
|
||||
jest.mock(
|
||||
'@librechat/api',
|
||||
() => ({
|
||||
isEnabled: jest.fn((val) => val === 'true' || val === true),
|
||||
checkEmailConfig: jest.fn(),
|
||||
isEmailDomainAllowed: jest.fn(),
|
||||
math: jest.fn((val, fallback) => (val ? Number(val) : fallback)),
|
||||
shouldUseSecureCookie: jest.fn(() => false),
|
||||
resolveAppConfigForUser: jest.fn(async (_getAppConfig, _user) => ({})),
|
||||
setCloudFrontCookies: jest.fn(() => true),
|
||||
getCloudFrontConfig: jest.fn(() => ({
|
||||
domain: 'https://cdn.example.com',
|
||||
imageSigning: 'cookies',
|
||||
cookieDomain: '.example.com',
|
||||
privateKey: 'test-private-key',
|
||||
keyPairId: 'K123ABC',
|
||||
})),
|
||||
parseCloudFrontCookieScope: jest.fn(() => null),
|
||||
CLOUDFRONT_SCOPE_COOKIE: 'LibreChat-CloudFront-Scope',
|
||||
}),
|
||||
{ virtual: true },
|
||||
);
|
||||
jest.mock('~/models', () => ({
|
||||
findUser: jest.fn(),
|
||||
findToken: jest.fn(),
|
||||
createUser: jest.fn(),
|
||||
|
|
@ -42,8 +54,8 @@ const modelsMock = {
|
|||
generateToken: jest.fn(),
|
||||
deleteUserById: jest.fn(),
|
||||
generateRefreshToken: jest.fn(),
|
||||
};
|
||||
const validatorsMock = {
|
||||
}));
|
||||
jest.mock('~/strategies/validators', () => ({
|
||||
registerSchema: {
|
||||
safeParse: jest.fn((user) => ({
|
||||
success: true,
|
||||
|
|
@ -56,18 +68,9 @@ const validatorsMock = {
|
|||
},
|
||||
})),
|
||||
},
|
||||
};
|
||||
const configMock = { getAppConfig: jest.fn() };
|
||||
const serverUtilsMock = { sendEmail: jest.fn() };
|
||||
|
||||
jest.resetModules();
|
||||
jest.doMock('@librechat/data-schemas', () => dataSchemasMock);
|
||||
jest.doMock('librechat-data-provider', () => dataProviderMock);
|
||||
jest.doMock('@librechat/api', () => apiMock);
|
||||
jest.doMock('~/models', () => modelsMock);
|
||||
jest.doMock('~/strategies/validators', () => validatorsMock);
|
||||
jest.doMock('~/server/services/Config', () => configMock);
|
||||
jest.doMock('~/server/utils', () => serverUtilsMock);
|
||||
}));
|
||||
jest.mock('~/server/services/Config', () => ({ getAppConfig: jest.fn() }));
|
||||
jest.mock('~/server/utils', () => ({ sendEmail: jest.fn() }));
|
||||
|
||||
const {
|
||||
checkEmailConfig,
|
||||
|
|
@ -77,9 +80,9 @@ const {
|
|||
setCloudFrontCookies,
|
||||
getCloudFrontConfig,
|
||||
parseCloudFrontCookieScope,
|
||||
} = apiMock;
|
||||
} = require('@librechat/api');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const { logger, getTenantId } = dataSchemasMock;
|
||||
const { logger, getTenantId } = require('@librechat/data-schemas');
|
||||
const {
|
||||
findUser,
|
||||
findToken,
|
||||
|
|
@ -92,9 +95,9 @@ const {
|
|||
createSession,
|
||||
createToken,
|
||||
deleteTokens,
|
||||
} = modelsMock;
|
||||
const { getAppConfig } = configMock;
|
||||
const { sendEmail } = serverUtilsMock;
|
||||
} = require('~/models');
|
||||
const { getAppConfig } = require('~/server/services/Config');
|
||||
const { sendEmail } = require('~/server/utils');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const {
|
||||
setOpenIDAuthTokens,
|
||||
|
|
@ -127,36 +130,6 @@ function mockRequest(sessionData = {}, cookies = {}) {
|
|||
};
|
||||
}
|
||||
|
||||
const originalEnv = { ...process.env };
|
||||
const defaultCloudFrontCookieConfig = {
|
||||
domain: 'https://cdn.example.com',
|
||||
imageSigning: 'cookies',
|
||||
cookieDomain: '.example.com',
|
||||
privateKey: 'test-private-key',
|
||||
keyPairId: 'K123ABC',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
JWT_REFRESH_SECRET: 'test-refresh-secret',
|
||||
OPENID_REUSE_TOKENS: 'true',
|
||||
};
|
||||
checkEmailConfig.mockReturnValue(false);
|
||||
shouldUseSecureCookie.mockReturnValue(false);
|
||||
isEmailDomainAllowed.mockReturnValue(true);
|
||||
resolveAppConfigForUser.mockResolvedValue({});
|
||||
setCloudFrontCookies.mockReturnValue(true);
|
||||
getCloudFrontConfig.mockReturnValue(defaultCloudFrontCookieConfig);
|
||||
parseCloudFrontCookieScope.mockReturnValue(null);
|
||||
getTenantId.mockReturnValue(undefined);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
describe('setOpenIDAuthTokens', () => {
|
||||
const env = process.env;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const express = require('express');
|
||||
const request = require('supertest');
|
||||
const zlib = require('zlib');
|
||||
const staticCache = require('../staticCache');
|
||||
|
||||
const binaryParser = (res, callback) => {
|
||||
const chunks = [];
|
||||
|
|
@ -18,9 +18,15 @@ describe('staticCache', () => {
|
|||
let indexFile;
|
||||
let manifestFile;
|
||||
let swFile;
|
||||
let staticCache;
|
||||
|
||||
const createTestFiles = () => {
|
||||
beforeAll(() => {
|
||||
// Create a test directory and files
|
||||
testDir = path.join(__dirname, 'test-static');
|
||||
if (!fs.existsSync(testDir)) {
|
||||
fs.mkdirSync(testDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Create test files
|
||||
testFile = path.join(testDir, 'test.js');
|
||||
indexFile = path.join(testDir, 'index.html');
|
||||
manifestFile = path.join(testDir, 'manifest.json');
|
||||
|
|
@ -56,10 +62,6 @@ describe('staticCache', () => {
|
|||
const distImagesDir = path.join(testDir, 'dist', 'images');
|
||||
fs.mkdirSync(distImagesDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(distImagesDir, 'logo.png'), 'fake-png-data');
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'librechat-static-cache-'));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
|
@ -77,15 +79,6 @@ describe('staticCache', () => {
|
|||
delete process.env.STATIC_CACHE_S_MAX_AGE;
|
||||
delete process.env.STATIC_CACHE_MAX_AGE;
|
||||
delete process.env.ENABLE_STATIC_ASSET_BROTLI;
|
||||
|
||||
if (fs.existsSync(testDir)) {
|
||||
fs.rmSync(testDir, { recursive: true, force: true });
|
||||
}
|
||||
fs.mkdirSync(testDir, { recursive: true });
|
||||
createTestFiles();
|
||||
|
||||
jest.resetModules();
|
||||
staticCache = require('../staticCache');
|
||||
});
|
||||
describe('cache headers in production', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import type { FileConfigInput } from 'librechat-data-provider';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { FileConfigInput } from 'librechat-data-provider';
|
||||
import UploadSkillDialog from '../UploadSkillDialog';
|
||||
|
||||
const mockMutate = jest.fn();
|
||||
|
|
@ -70,14 +70,12 @@ jest.mock('~/utils', () => ({
|
|||
cn: (...classes: Array<string | false | null | undefined>) => classes.filter(Boolean).join(' '),
|
||||
}));
|
||||
|
||||
async function getFileInput(baseElement: HTMLElement): Promise<HTMLInputElement> {
|
||||
return await waitFor(() => {
|
||||
const input = baseElement.querySelector('input[type="file"]');
|
||||
if (!(input instanceof HTMLInputElement)) {
|
||||
throw new Error('Upload input was not rendered');
|
||||
}
|
||||
return input;
|
||||
});
|
||||
function getFileInput(container: HTMLElement): HTMLInputElement {
|
||||
const input = container.querySelector('input[type="file"]');
|
||||
if (!(input instanceof HTMLInputElement)) {
|
||||
throw new Error('Upload input was not rendered');
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
describe('UploadSkillDialog', () => {
|
||||
|
|
@ -108,13 +106,13 @@ describe('UploadSkillDialog', () => {
|
|||
expect(screen.getByText('File size must not exceed 1.06 MB')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('rejects files above the configured skill import limit before upload', async () => {
|
||||
const { baseElement } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
it('rejects files above the configured skill import limit before upload', () => {
|
||||
const { container } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
const file = new File([new Uint8Array(1024 * 1024 + 1)], 'too-large.skill', {
|
||||
type: 'application/zip',
|
||||
});
|
||||
|
||||
fireEvent.change(await getFileInput(baseElement), {
|
||||
fireEvent.change(getFileInput(container), {
|
||||
target: {
|
||||
files: [file],
|
||||
},
|
||||
|
|
@ -127,14 +125,14 @@ describe('UploadSkillDialog', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('uploads files exactly at the configured skill import limit', async () => {
|
||||
it('uploads files exactly at the configured skill import limit', () => {
|
||||
const appendSpy = jest.spyOn(FormData.prototype, 'append');
|
||||
const { baseElement } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
const { container } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
const file = new File([new Uint8Array(1024 * 1024)], 'exact-limit.skill', {
|
||||
type: 'application/zip',
|
||||
});
|
||||
|
||||
fireEvent.change(await getFileInput(baseElement), {
|
||||
fireEvent.change(getFileInput(container), {
|
||||
target: {
|
||||
files: [file],
|
||||
},
|
||||
|
|
@ -146,14 +144,14 @@ describe('UploadSkillDialog', () => {
|
|||
appendSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('uploads files under the configured skill import limit', async () => {
|
||||
it('uploads files under the configured skill import limit', () => {
|
||||
const appendSpy = jest.spyOn(FormData.prototype, 'append');
|
||||
const { baseElement } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
const { container } = render(<UploadSkillDialog isOpen={true} setIsOpen={mockSetIsOpen} />);
|
||||
const file = new File([new Uint8Array(1024)], 'small.skill', {
|
||||
type: 'application/zip',
|
||||
});
|
||||
|
||||
fireEvent.change(await getFileInput(baseElement), {
|
||||
fireEvent.change(getFileInput(container), {
|
||||
target: {
|
||||
files: [file],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,9 +26,7 @@
|
|||
"update:deployed": "node config/deployed-update.js",
|
||||
"rebase:deployed": "node config/deployed-update.js --rebase",
|
||||
"start:deployed": "docker compose -f ./deploy-compose.yml up -d || docker-compose -f ./deploy-compose.yml up -d",
|
||||
"start:deployed:langfuse-fanout": "docker compose -f ./deploy-compose.yml -f ./deploy-compose.langfuse-fanout.yml up -d || docker-compose -f ./deploy-compose.yml -f ./deploy-compose.langfuse-fanout.yml up -d",
|
||||
"stop:deployed": "docker compose -f ./deploy-compose.yml down || docker-compose -f ./deploy-compose.yml down",
|
||||
"stop:deployed:langfuse-fanout": "docker compose -f ./deploy-compose.yml -f ./deploy-compose.langfuse-fanout.yml down || docker-compose -f ./deploy-compose.yml -f ./deploy-compose.langfuse-fanout.yml down",
|
||||
"upgrade": "node config/upgrade.js",
|
||||
"create-user": "node config/create-user.js",
|
||||
"invite-user": "node config/invite-user.js",
|
||||
|
|
@ -78,8 +76,8 @@
|
|||
"test:all": "npm run test:client && npm run test:api && npm run test:packages:api && npm run test:packages:data-provider && npm run test:packages:data-schemas",
|
||||
"e2e:update": "npm run e2e:prepare && playwright test --config=e2e/playwright.config.local.ts --update-snapshots",
|
||||
"e2e:report": "npx playwright show-report e2e/playwright-report",
|
||||
"lint:fix": "eslint --fix --no-error-on-unmatched-pattern \"**/*.{js,jsx,ts,tsx}\"",
|
||||
"lint": "eslint --no-error-on-unmatched-pattern \"**/*.{js,jsx,ts,tsx}\"",
|
||||
"lint:fix": "eslint --fix \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
||||
"lint": "eslint \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
||||
"sort-imports": "node scripts/sort-imports.mts",
|
||||
"sort-imports:check": "node scripts/sort-imports.mts --check",
|
||||
"format": "npx prettier --write \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import mongoose, { Mongoose, Types } from 'mongoose';
|
||||
import mongoose, { Types } from 'mongoose';
|
||||
import { MongoMemoryServer } from 'mongodb-memory-server';
|
||||
import { PrincipalType, PrincipalModel } from 'librechat-data-provider';
|
||||
import type { IConfig } from '~/types';
|
||||
|
|
@ -6,25 +6,24 @@ import { createConfigMethods } from './config';
|
|||
import configSchema from '~/schema/config';
|
||||
|
||||
let mongoServer: MongoMemoryServer;
|
||||
let testMongoose: Mongoose;
|
||||
let methods: ReturnType<typeof createConfigMethods>;
|
||||
|
||||
beforeAll(async () => {
|
||||
mongoServer = await MongoMemoryServer.create();
|
||||
testMongoose = new mongoose.Mongoose();
|
||||
await testMongoose.connect(mongoServer.getUri());
|
||||
testMongoose.model<IConfig>('Config', configSchema.clone());
|
||||
await testMongoose.models.Config.init();
|
||||
methods = createConfigMethods(testMongoose as unknown as typeof mongoose);
|
||||
await mongoose.connect(mongoServer.getUri());
|
||||
if (!mongoose.models.Config) {
|
||||
mongoose.model<IConfig>('Config', configSchema);
|
||||
}
|
||||
methods = createConfigMethods(mongoose);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await testMongoose.disconnect();
|
||||
await mongoose.disconnect();
|
||||
await mongoServer.stop();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await testMongoose.models.Config.deleteMany({});
|
||||
await mongoose.models.Config.deleteMany({});
|
||||
});
|
||||
|
||||
describe('upsertConfig tombstone preservation', () => {
|
||||
|
|
@ -62,7 +61,7 @@ describe('upsertConfig tombstone preservation', () => {
|
|||
10,
|
||||
);
|
||||
|
||||
const count = await testMongoose.models.Config.countDocuments({});
|
||||
const count = await mongoose.models.Config.countDocuments({});
|
||||
expect(count).toBe(1);
|
||||
});
|
||||
|
||||
|
|
@ -487,7 +486,7 @@ describe('expectEmpty atomic guard', () => {
|
|||
});
|
||||
expect(result).toBeTruthy();
|
||||
|
||||
const remaining = await testMongoose.models.Config.countDocuments({});
|
||||
const remaining = await mongoose.models.Config.countDocuments({});
|
||||
expect(remaining).toBe(0);
|
||||
});
|
||||
|
||||
|
|
@ -505,12 +504,12 @@ describe('expectEmpty atomic guard', () => {
|
|||
});
|
||||
expect(result).toBeNull();
|
||||
|
||||
const remaining = await testMongoose.models.Config.countDocuments({});
|
||||
const remaining = await mongoose.models.Config.countDocuments({});
|
||||
expect(remaining).toBe(1);
|
||||
});
|
||||
|
||||
it('deleteConfig with expectEmpty returns null when tombstones is non-empty (doc preserved)', async () => {
|
||||
await testMongoose.models.Config.create({
|
||||
await mongoose.models.Config.create({
|
||||
principalType: PrincipalType.ROLE,
|
||||
principalId: 'admin',
|
||||
principalModel: PrincipalModel.ROLE,
|
||||
|
|
@ -526,7 +525,7 @@ describe('expectEmpty atomic guard', () => {
|
|||
});
|
||||
expect(result).toBeNull();
|
||||
|
||||
const remaining = await testMongoose.models.Config.countDocuments({});
|
||||
const remaining = await mongoose.models.Config.countDocuments({});
|
||||
expect(remaining).toBe(1);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -21,11 +21,10 @@ let methods: ReturnType<typeof createSystemGrantMethods>;
|
|||
|
||||
beforeAll(async () => {
|
||||
mongoServer = await MongoMemoryServer.create();
|
||||
await mongoose.connect(mongoServer.getUri());
|
||||
SystemGrant =
|
||||
mongoose.models.SystemGrant || mongoose.model<t.ISystemGrant>('SystemGrant', systemGrantSchema);
|
||||
await SystemGrant.init();
|
||||
methods = createSystemGrantMethods(mongoose);
|
||||
await mongoose.connect(mongoServer.getUri());
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue