apps/bot: add vitest
This commit is contained in:
parent
44d5c77037
commit
23e29f90cd
@ -16,7 +16,8 @@
|
||||
"start": "node dist/src/index.js",
|
||||
"dev": "dotenv -e ../../.env.local tsx watch src/index.ts",
|
||||
"lint": "eslint",
|
||||
"lint-staged": "lint-staged"
|
||||
"lint-staged": "lint-staged",
|
||||
"test:unit": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/eslint-config": "workspace:*",
|
||||
@ -29,6 +30,8 @@
|
||||
"lint-staged": "catalog:",
|
||||
"rimraf": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
"typescript": "catalog:",
|
||||
"vite-tsconfig-paths": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { getClientWithToken } from '../apollo/client';
|
||||
import { createApolloClient, getClientWithToken } from '../apollo/client';
|
||||
import { env as environment } from '../config/env';
|
||||
import * as GQL from '@repo/graphql/types';
|
||||
|
||||
export async function createCustomer(variables: GQL.CreateCustomerMutationVariables) {
|
||||
@ -18,3 +19,17 @@ export async function getCustomer(variables: GQL.GetCustomerQueryVariables) {
|
||||
variables,
|
||||
});
|
||||
}
|
||||
|
||||
export async function login() {
|
||||
const { mutate } = createApolloClient();
|
||||
|
||||
const response = await mutate({
|
||||
mutation: GQL.LoginDocument,
|
||||
variables: {
|
||||
identifier: environment.LOGIN_GRAPHQL,
|
||||
password: environment.PASSWORD_GRAPHQL,
|
||||
},
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { env as environment } from '../config/env';
|
||||
import { getToken } from '../utils/jwt';
|
||||
import { getToken } from '../config/token';
|
||||
import { ApolloClient, InMemoryCache } from '@apollo/client/core';
|
||||
|
||||
type Parameters_ = { token: null | string | undefined };
|
||||
|
||||
13
apps/bot/src/config/token.ts
Normal file
13
apps/bot/src/config/token.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { login } from '../api/query';
|
||||
import { isTokenExpired } from '../utils/jwt';
|
||||
|
||||
export const token: null | string = null;
|
||||
|
||||
export async function getToken() {
|
||||
if (!token || isTokenExpired(token)) {
|
||||
const response = await login();
|
||||
return response?.data?.login.jwt;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
61
apps/bot/src/utils/jwt.test.ts
Normal file
61
apps/bot/src/utils/jwt.test.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/* eslint-disable unicorn/consistent-function-scoping */
|
||||
import { isTokenExpired } from './jwt';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
describe('isTokenExpired', () => {
|
||||
const mockDateNow = (timestamp: number) => {
|
||||
vi.spyOn(Date, 'now').mockReturnValue(timestamp);
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks(); // Сбрасываем все моки после каждого теста
|
||||
});
|
||||
|
||||
it('should return true if the token is expired', () => {
|
||||
const token = jwt.sign({}, 'secret', { expiresIn: -10 }); // Токен с истекшим временем
|
||||
mockDateNow(Date.now());
|
||||
|
||||
const result = isTokenExpired(token);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the token is not expired', () => {
|
||||
const token = jwt.sign({}, 'secret', { expiresIn: 3_600 }); // Токен с временем жизни 1 час
|
||||
mockDateNow(Date.now());
|
||||
|
||||
const result = isTokenExpired(token);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the token will expire within the threshold', () => {
|
||||
const threshold = 300; // 5 минут
|
||||
const token = jwt.sign({}, 'secret', { expiresIn: threshold - 10 }); // Токен с временем жизни чуть меньше порога
|
||||
mockDateNow(Date.now());
|
||||
|
||||
const result = isTokenExpired(token, threshold);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the token will expire outside the threshold', () => {
|
||||
const threshold = 300; // 5 минут
|
||||
const token = jwt.sign({}, 'secret', { expiresIn: threshold + 100 }); // Токен с временем жизни больше порога
|
||||
mockDateNow(Date.now());
|
||||
|
||||
const result = isTokenExpired(token, threshold);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the token is invalid', () => {
|
||||
const invalidToken = 'invalid.token.string';
|
||||
|
||||
const result = isTokenExpired(invalidToken);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should throw an error if the token doesn't have an exp field", () => {
|
||||
const token = jwt.sign({ data: 'no exp' }, 'secret', { noTimestamp: true }); // Токен без exp
|
||||
const result = isTokenExpired(token);
|
||||
expect(result).toBe(true); // Ожидается, что вернётся true
|
||||
});
|
||||
});
|
||||
@ -1,22 +1,6 @@
|
||||
import { createApolloClient } from '../apollo/client';
|
||||
import { env as environment } from '../config/env';
|
||||
import * as GQL from '@repo/graphql/types';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
|
||||
const token: null | string = null;
|
||||
|
||||
export async function getToken() {
|
||||
if (!token || isTokenExpired()) {
|
||||
const response = await login();
|
||||
return response?.data?.login.jwt;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
function isTokenExpired(threshold: number = 300) {
|
||||
if (!token) throw new Error('Token is missing');
|
||||
|
||||
export function isTokenExpired(token: string, threshold: number = 300) {
|
||||
try {
|
||||
const decoded = jwt.decode(token);
|
||||
|
||||
@ -32,17 +16,3 @@ function isTokenExpired(threshold: number = 300) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function login() {
|
||||
const { mutate } = createApolloClient();
|
||||
|
||||
const response = await mutate({
|
||||
mutation: GQL.LoginDocument,
|
||||
variables: {
|
||||
identifier: environment.LOGIN_GRAPHQL,
|
||||
password: environment.PASSWORD_GRAPHQL,
|
||||
},
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@ -213,6 +213,12 @@ importers:
|
||||
typescript:
|
||||
specifier: 'catalog:'
|
||||
version: 5.7.2
|
||||
vite-tsconfig-paths:
|
||||
specifier: 'catalog:'
|
||||
version: 5.1.4(typescript@5.7.2)(vite@5.4.11(@types/node@20.17.8))
|
||||
vitest:
|
||||
specifier: 'catalog:'
|
||||
version: 2.1.8(@types/node@20.17.8)(jsdom@25.0.1)
|
||||
|
||||
apps/web:
|
||||
dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user