mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
feat: Setup Unit Test Environment and Refactor Typescript Config (#365)
* modify tsconfig and set up unit tests * generate .d.ts files * setup project dependencies and configuration for unit tests * Add test setup and layout-test-utils along with first spec * Add paths back to tsconfig * remove type=module from package.json * Add typescript definition for .env * update package-lock
This commit is contained in:
parent
dbfef342e2
commit
4eda4542b7
14 changed files with 8805 additions and 14010 deletions
|
@ -10,6 +10,7 @@ module.exports = {
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:react/recommended',
|
'plugin:react/recommended',
|
||||||
'plugin:react-hooks/recommended',
|
'plugin:react-hooks/recommended',
|
||||||
|
"plugin:jest/recommended",
|
||||||
'prettier'
|
'prettier'
|
||||||
],
|
],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
|
@ -64,7 +65,7 @@ module.exports = {
|
||||||
{
|
{
|
||||||
files: ['rollup.config.js', '.eslintrc.js', 'jest.config.js'],
|
files: ['rollup.config.js', '.eslintrc.js', 'jest.config.js'],
|
||||||
env: {
|
env: {
|
||||||
node: true
|
node: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -95,7 +96,7 @@ module.exports = {
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: './client/tsconfig.json'
|
project: './client/tsconfig.json'
|
||||||
},
|
},
|
||||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
plugins: ['@typescript-eslint/eslint-plugin', 'jest'],
|
||||||
extends: [
|
extends: [
|
||||||
'plugin:@typescript-eslint/eslint-recommended',
|
'plugin:@typescript-eslint/eslint-recommended',
|
||||||
'plugin:@typescript-eslint/recommended'
|
'plugin:@typescript-eslint/recommended'
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
/*
|
|
||||||
a preset is a set of plugins used to support particular language features.
|
|
||||||
The two presets Babel uses by default: es2015, react
|
|
||||||
*/
|
|
||||||
"presets": [
|
|
||||||
"@babel/preset-env", //compiling ES2015+ syntax
|
|
||||||
"@babel/preset-react" //for react
|
|
||||||
],
|
|
||||||
/*
|
|
||||||
Babel's code transformations are enabled by applying plugins (or presets) to your configuration file.
|
|
||||||
*/
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-transform-runtime",
|
|
||||||
[
|
|
||||||
"babel-plugin-root-import",
|
|
||||||
{
|
|
||||||
"rootPathPrefix": "~/",
|
|
||||||
"rootPathSuffix": "./src"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
23
client/babel.config.cjs
Normal file
23
client/babel.config.cjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
["@babel/preset-env", { "targets": { "node": "current" } }], //compiling ES2015+ syntax
|
||||||
|
['@babel/preset-react', {runtime: 'automatic'}],
|
||||||
|
"@babel/preset-typescript"
|
||||||
|
],
|
||||||
|
/*
|
||||||
|
Babel's code transformations are enabled by applying plugins (or presets) to your configuration file.
|
||||||
|
*/
|
||||||
|
plugins: [
|
||||||
|
"@babel/plugin-transform-runtime",
|
||||||
|
'babel-plugin-transform-import-meta',
|
||||||
|
'babel-plugin-transform-vite-meta-env',
|
||||||
|
'babel-plugin-replace-ts-export-assignment',
|
||||||
|
[
|
||||||
|
"babel-plugin-root-import",
|
||||||
|
{
|
||||||
|
"rootPathPrefix": "~/",
|
||||||
|
"rootPathSuffix": "./src"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
12
client/env.d.ts
vendored
Normal file
12
client/env.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_SERVER_URL_DEV: string;
|
||||||
|
readonly VITE_SERVER_URL_PROD: string;
|
||||||
|
readonly VITE_SHOW_GOOGLE_LOGIN_OPTION: string;
|
||||||
|
readonly VITE_CLIENT_URL_DEV: string;
|
||||||
|
readonly VITE_CLIENT_URL_PROD: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
47
client/jest.config.cjs
Normal file
47
client/jest.config.cjs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
module.exports = {
|
||||||
|
roots: ['<rootDir>/src'],
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
testEnvironmentOptions: {
|
||||||
|
url: 'http://localhost:3080',
|
||||||
|
},
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.{js,jsx,ts,tsx}',
|
||||||
|
'!<rootDir>/node_modules/',
|
||||||
|
'!src/**/*.css.d.ts',
|
||||||
|
'!src/**/*.d.ts',
|
||||||
|
],
|
||||||
|
coveragePathIgnorePatterns: [
|
||||||
|
'<rootDir>/node_modules/',
|
||||||
|
'<rootDir>/test/setupTests.js',
|
||||||
|
],
|
||||||
|
// Todo: Add coverageThreshold once we have enough coverage
|
||||||
|
// Note: eventually we want to have these values set to 80%
|
||||||
|
// coverageThreshold: {
|
||||||
|
// global: {
|
||||||
|
// functions: 9,
|
||||||
|
// lines: 40,
|
||||||
|
// statements: 40,
|
||||||
|
// branches: 12,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
moduleNameMapper: {
|
||||||
|
'\\.(css)$': 'identity-obj-proxy',
|
||||||
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||||
|
'jest-file-loader',
|
||||||
|
'layout-test-utils': '<rootDir>/test/layout-test-utils',
|
||||||
|
'^@src/(.*)$': '<rootDir>/src/$1',
|
||||||
|
'^modules/(.*)$': '<rootDir>/src/modules/$1',
|
||||||
|
},
|
||||||
|
restoreMocks: true,
|
||||||
|
testResultsProcessor: 'jest-junit',
|
||||||
|
coverageReporters: ['text', 'cobertura', 'lcov'],
|
||||||
|
transform: {
|
||||||
|
'\\.[jt]sx?$': 'babel-jest',
|
||||||
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||||
|
'jest-file-loader',
|
||||||
|
},
|
||||||
|
preset: 'ts-jest',
|
||||||
|
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect', '<rootDir>/test/setupTests.js'],
|
||||||
|
clearMocks: true,
|
||||||
|
};
|
7
client/junit.xml
Normal file
7
client/junit.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites name="jest tests" tests="1" failures="0" errors="0" time="0.704">
|
||||||
|
<testsuite name="undefined" errors="0" failures="0" skipped="0" timestamp="2023-05-22T20:54:42" time="0.541" tests="1">
|
||||||
|
<testcase classname=" renders login form" name=" renders login form" time="0.035">
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
|
@ -2,11 +2,12 @@
|
||||||
"name": "chat-frontend",
|
"name": "chat-frontend",
|
||||||
"version": "0.4.6",
|
"version": "0.4.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"preview-prod": "vite preview"
|
"preview-prod": "vite preview",
|
||||||
|
"test": "jest --watch",
|
||||||
|
"test:ci": "jest --ci"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -80,24 +81,38 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.20.7",
|
"@babel/cli": "^7.20.7",
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.21.8",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.19.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.4",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.21.5",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.21.0",
|
"@babel/preset-typescript": "^7.21.0",
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@tanstack/react-query-devtools": "^4.29.0",
|
"@tanstack/react-query-devtools": "^4.29.0",
|
||||||
"@types/jest": "^29.5.0",
|
"@testing-library/dom": "^9.3.0",
|
||||||
"@types/node": "^20.2.3",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@types/react": "^18.0.30",
|
"@testing-library/react": "^14.0.0",
|
||||||
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@types/jest": "^29.5.1",
|
||||||
|
"@types/node": "^18.16.13",
|
||||||
|
"@types/react": "^18.2.6",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
|
"babel-jest": "^29.5.0",
|
||||||
"babel-loader": "^9.1.2",
|
"babel-loader": "^9.1.2",
|
||||||
|
"babel-plugin-replace-ts-export-assignment": "^0.0.2",
|
||||||
"babel-plugin-root-import": "^6.6.0",
|
"babel-plugin-root-import": "^6.6.0",
|
||||||
|
"babel-plugin-transform-import-meta": "^2.2.0",
|
||||||
|
"babel-plugin-transform-vite-meta-env": "^1.0.3",
|
||||||
"babel-preset-react": "^6.24.1",
|
"babel-preset-react": "^6.24.1",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
|
"jest": "^29.5.0",
|
||||||
|
"jest-canvas-mock": "^2.5.1",
|
||||||
|
"jest-environment-jsdom": "^29.5.0",
|
||||||
|
"jest-file-loader": "^1.0.3",
|
||||||
|
"jest-junit": "^16.0.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
"postcss-loader": "^7.1.0",
|
"postcss-loader": "^7.1.0",
|
||||||
|
@ -105,6 +120,7 @@
|
||||||
"source-map-loader": "^4.0.1",
|
"source-map-loader": "^4.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"tailwindcss": "^3.2.6",
|
"tailwindcss": "^3.2.6",
|
||||||
|
"ts-jest": "^29.1.0",
|
||||||
"ts-loader": "^9.4.2",
|
"ts-loader": "^9.4.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"vite": "^4.2.1",
|
"vite": "^4.2.1",
|
||||||
|
|
8
client/src/components/Auth/__tests__/Login.spec.tsx
Normal file
8
client/src/components/Auth/__tests__/Login.spec.tsx
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { render } from 'layout-test-utils';
|
||||||
|
import Login from '../Login';
|
||||||
|
|
||||||
|
test('renders login form', () => {
|
||||||
|
const { getByLabelText } = render(<Login />);
|
||||||
|
expect(getByLabelText(/email/i)).toBeInTheDocument();
|
||||||
|
expect(getByLabelText(/password/i)).toBeInTheDocument();
|
||||||
|
});
|
21
client/test/layout-test-utils.tsx
Normal file
21
client/test/layout-test-utils.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { render as rtlRender } from '@testing-library/react';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { AuthContextProvider } from '~/hooks/AuthContext';
|
||||||
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
|
||||||
|
const client = new QueryClient();
|
||||||
|
|
||||||
|
function renderWithProvidersWrapper(ui, { ...options } = {}) {
|
||||||
|
function Wrapper({ children }) {
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={client}>
|
||||||
|
<Router>
|
||||||
|
<AuthContextProvider>{children}</AuthContextProvider>
|
||||||
|
</Router>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return rtlRender(ui, { wrapper: Wrapper, ...options });
|
||||||
|
}
|
||||||
|
export * from '@testing-library/react';
|
||||||
|
export { renderWithProvidersWrapper as render };
|
18
client/test/setupTests.js
Normal file
18
client/test/setupTests.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* This file is automatically executed before running tests
|
||||||
|
* https://create-react-app.dev/docs/running-tests/#initializing-test-environment
|
||||||
|
*/
|
||||||
|
|
||||||
|
// react-testing-library renders your components to document.body,
|
||||||
|
// this adds jest-dom's custom assertions
|
||||||
|
// https://github.com/testing-library/jest-dom#table-of-contents
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import '@testing-library/jest-dom/extend-expect';
|
||||||
|
|
||||||
|
// Mock canvas when run unit test cases with jest.
|
||||||
|
// 'react-lottie' uses canvas
|
||||||
|
import 'jest-canvas-mock';
|
|
@ -2,14 +2,10 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": [
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
"DOM",
|
|
||||||
"DOM.Iterable",
|
|
||||||
"ESNext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": false,
|
"skipLibCheck": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": false,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": false,
|
"forceConsistentCasingInFileNames": false,
|
||||||
|
@ -19,13 +15,20 @@
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"noEmit": false,
|
"noEmit": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./types",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./src/*"]
|
"~/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"types": ["node", "jest", "@testing-library/jest-dom"],
|
||||||
"src"
|
"exclude": ["node_modules"],
|
||||||
],
|
"include": ["src/**/*", "setupTests.js", "vite.config.ts", "env.d.ts"],
|
||||||
}
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
9
client/tsconfig.node.json
Normal file
9
client/tsconfig.node.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
|
@ -14,10 +14,6 @@ export default defineConfig({
|
||||||
target: 'http://localhost:3080',
|
target: 'http://localhost:3080',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
},
|
},
|
||||||
'/auth': {
|
|
||||||
target: 'http://localhost:3080',
|
|
||||||
changeOrigin: true
|
|
||||||
},
|
|
||||||
'/oauth': {
|
'/oauth': {
|
||||||
target: 'http://localhost:3080',
|
target: 'http://localhost:3080',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
|
|
22583
package-lock.json
generated
22583
package-lock.json
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue