Issue description
I'm going to test the service in api used in Next.js app and using babel jest for that specific tests file. The problem that I struggle is issue regarding finding a module and the error that appears in terminal is as in the listing below.
Cannot find module '#node-web-compat' from 'node_modules/aws-jwt-verify/dist/cjs/https.js'
Require stack:
node_modules/aws-jwt-verify/dist/cjs/https.js
node_modules/aws-jwt-verify/dist/cjs/jwk.js
node_modules/aws-jwt-verify/dist/cjs/jwt-rsa.js
node_modules/aws-jwt-verify/dist/cjs/index.js
pages/api/auth/auth.service.ts
__tests__/sign-up/api/auth/auth-service.test.ts
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:491:11)
at Object.<anonymous> (node_modules/aws-jwt-verify/dist/cjs/https.js:9:28)
The tested service is used by TypeScript decorator in middleware. It works as expected when I'm testing it manually but the issue appears only while running tests.
Goal
My goal is unit testing service that uses library aws-jwt-verify
to verify JWT accessToken. I would like to mock it and use in my jest
unit tests.
tried methods
I've tried to copy dependency to devDependencies
and reinstall packages but it didn't help
dependencies in package.json
{
...
"dependencies": {
"@aws-sdk/client-cognito-identity-provider": "^3.137.0",
"@chakra-ui/react": "^2.2.3",
"@emotion/react": "^11",
"@emotion/styled": "^11",
"@hookform/resolvers": "^2.9.7",
"@storyofams/next-api-decorators": "^1.8.2",
"@tanstack/react-query": "^4.0.10",
"@tanstack/react-query-devtools": "^4.0.10",
"aws-jwt-verify": "^3.1.0",
"axios": "^0.27.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"cookie": "^0.5.0",
"framer-motion": "^6",
"next": "latest",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-hook-form": "^7.34.0",
"react-icons": "^4.4.0",
"storybook-addon-next-router": "^4.0.0",
"zod": "^3.17.10"
},
...
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
test environment
dir: './'
});
const customJestConfig = {for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/']
};
module.exports = createJestConfig(customJestConfig);
auth.service.ts
// auth.service.ts
import { CognitoJwtVerifier } from 'aws-jwt-verify';
import { BadRequestException } from '@storyofams/next-api-decorators';
import { CognitoAccessTokenPayload } from 'aws-jwt-verify/jwt-model';
export class AuthService {
async verifyToken(token: string): Promise<boolean> {
const verifier = CognitoJwtVerifier.create({
userPoolId: process.env.COGNITO_USER_POOL_ID,
tokenUse: 'access',
clientId: process.env.COGNITO_WEB_CLIENT_ID
});
try {
const verifyResult: CognitoAccessTokenPayload = await verifier.verify(token);
const isNotExpired = verifyResult.exp > Math.floor(Date.now() / 1000);
const isCorrectClient = verifyResult.client_id === process.env.COGNITO_WEB_CLIENT_ID;
const isCorrectUserPool =
verifyResult.iss ===
`https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`;
const isTokenUseValid = verifyResult.token_use === 'access';
return isNotExpired && isCorrectClient && isCorrectUserPool && isTokenUseValid;
} catch (e) {
throw new BadRequestException(e.message);
}
}
}
auth-service.test.ts
// auth-service.test.ts
describe('Auth Service', () => {
describe('verifyToken', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should verify token successfully', async () => {
jest.mock('aws-jwt-verify', () => {
return {
CognitoJwtVerifier: jest.fn().mockImplementation(() => {
return {
verify: jest.fn().mockResolvedValue({
exp: Math.floor(Date.now() / 1000) 3600,
client_id: process.env.COGNITO_WEB_CLIENT_ID,
iss: `https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`,
token_use: 'access'
})
};
})
};
});
const authService = new AuthService();
const result = await authService.verifyToken('token');
expect(result).toBeTruthy();
});
});
});
CodePudding user response:
issue with mock library After trying to downgrade library version to 2.1.3 it helped. I was inspired by issue
Issue with mocking
I decided to use spyOn
import { CognitoJwtVerifier } from 'aws-jwt-verify';
...
jest.mock('aws-jwt-verify');
test('my test', () => {
jest.spyOn(CognitoJwtVerifier, 'create').mockImplementation(() => {
return {
verify: jest.fn().mockResolvedValue({
exp: Math.floor(Date.now() / 1000) 3600,
client_id: process.env.COGNITO_WEB_CLIENT_ID,
iss: `https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`,
token_use: 'access'
})
};
});
})
CodePudding user response:
I faced this issue using typescript, jest, and ts-jest. For me this gitHub issue provided the answer. https://github.com/facebook/jest/issues/12619
needed to add this to my jest.config
moduleNameMapper: {
'#node-web-compat': "./node-web-compat-node.js",
}