mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(api): setup jest in new api (#49709)
* feat(api): setup jest in new api * feat: sample tests
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
import request, { Response } from 'supertest';
|
||||||
|
import { API_LOCATION as api } from './utils/env';
|
||||||
|
|
||||||
|
describe('GET /', () => {
|
||||||
|
let res: undefined | Response;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
res = await request(api).get('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('have a 200 response', () => {
|
||||||
|
expect(res?.statusCode).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('return { "hello": "world"}', () => {
|
||||||
|
expect(res?.body).toEqual({ hello: 'world' });
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import type { Config } from 'jest';
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
verbose: true,
|
||||||
|
testRegex: '\\.test\\.ts$',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts$': 'ts-jest'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
+11
-7
@@ -8,14 +8,22 @@
|
|||||||
"@fastify/middie": "8.1",
|
"@fastify/middie": "8.1",
|
||||||
"@fastify/session": "^10.1.1",
|
"@fastify/session": "^10.1.1",
|
||||||
"@prisma/client": "4.10.1",
|
"@prisma/client": "4.10.1",
|
||||||
"connect-mongo": "4.6.0",
|
|
||||||
"@sinclair/typebox": "0.25.24",
|
"@sinclair/typebox": "0.25.24",
|
||||||
|
"connect-mongo": "4.6.0",
|
||||||
"fastify": "4.14.1",
|
"fastify": "4.14.1",
|
||||||
"fastify-auth0-verify": "^1.0.0",
|
"fastify-auth0-verify": "^1.0.0",
|
||||||
"fastify-plugin": "^4.3.0",
|
"fastify-plugin": "^4.3.0",
|
||||||
"nodemon": "2.0.21"
|
"nodemon": "2.0.21"
|
||||||
},
|
},
|
||||||
"description": "The freeCodeCamp.org open-source codebase and curriculum",
|
"description": "The freeCodeCamp.org open-source codebase and curriculum",
|
||||||
|
"devDependencies": {
|
||||||
|
"@fastify/type-provider-typebox": "2.4.0",
|
||||||
|
"@types/supertest": "2.0.12",
|
||||||
|
"jest": "29.5.0",
|
||||||
|
"prisma": "4.10.1",
|
||||||
|
"supertest": "6.3.3",
|
||||||
|
"ts-jest": "29.0.5"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18",
|
"node": ">=18",
|
||||||
"npm": ">=8"
|
"npm": ">=8"
|
||||||
@@ -40,14 +48,10 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"develop": "nodemon index.ts",
|
"develop": "nodemon index.ts",
|
||||||
"start": "NODE_ENV=production node index.js",
|
"start": "NODE_ENV=production node index.ts",
|
||||||
"test": "node --test -r ts-node/register **/*.test.ts",
|
"test": "node --test -r ts-node/register **/*.test.ts",
|
||||||
"prisma": "MONGOHQ_URL=mongodb://localhost:27017/freecodecamp?directConnection=true prisma",
|
"prisma": "MONGOHQ_URL=mongodb://localhost:27017/freecodecamp?directConnection=true prisma",
|
||||||
"postinstall": "prisma generate"
|
"postinstall": "prisma generate"
|
||||||
},
|
},
|
||||||
"version": "0.0.1",
|
"version": "0.0.1"
|
||||||
"devDependencies": {
|
|
||||||
"prisma": "4.10.1",
|
|
||||||
"@fastify/type-provider-typebox": "2.4.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from 'node:assert';
|
|
||||||
// eslint-disable-next-line import/no-unresolved
|
|
||||||
import { describe, it } from 'node:test';
|
|
||||||
import Fastify from 'fastify';
|
import Fastify from 'fastify';
|
||||||
import jwtAuthz from './fastify-jwt-authz';
|
import jwtAuthz from './fastify-jwt-authz';
|
||||||
|
|
||||||
@@ -34,13 +31,14 @@ interface ErrorResponse {
|
|||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('fastify-jwt-authz', { only: true }, () => {
|
describe('fastify-jwt-authz', () => {
|
||||||
it('should decorate request instance with jwtAuthz method', async () => {
|
test('should decorate request instance with jwtAuthz method', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
fastify.get('/test', function (request) {
|
fastify.get('/', req => {
|
||||||
assert(request.jwtAuthz);
|
expect(req).toHaveProperty('jwtAuthz');
|
||||||
|
expect(req.jwtAuthz).toBeInstanceOf(Function);
|
||||||
return { foo: 'bar' };
|
return { foo: 'bar' };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -50,13 +48,13 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
|
|
||||||
const res = await fastify.inject({
|
const res = await fastify.inject({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/test'
|
url: '/'
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 200);
|
expect(res.statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error "Scopes cannot be empty" with an empty scopes parameter', async () => {
|
test('should throw an error "Scopes cannot be empty" with an empty scopes parameter', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -82,11 +80,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: ErrorResponse = res.json();
|
const resData: ErrorResponse = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 500);
|
expect(res.statusCode).toEqual(500);
|
||||||
assert.strictEqual(resData.message, 'Scopes cannot be empty');
|
expect(resData.message).toEqual('Scopes cannot be empty');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error "request.user does not exist" non existing request.user', async () => {
|
test('should throw an error "request.user does not exist" non existing request.user', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -112,11 +110,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: ErrorResponse = res.json();
|
const resData: ErrorResponse = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 500);
|
expect(res.statusCode).toEqual(500);
|
||||||
assert.strictEqual(resData.message, 'request.user does not exist');
|
expect(resData.message).toEqual('request.user does not exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error "request.user.scope must be a string"', async () => {
|
test('should throw an error "request.user.scope must be a string"', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -146,11 +144,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: ErrorResponse = res.json();
|
const resData: ErrorResponse = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 500);
|
expect(res.statusCode).toEqual(500);
|
||||||
assert.strictEqual(resData.message, 'request.user.scope must be a string');
|
expect(resData.message).toEqual('request.user.scope must be a string');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error "Insufficient scope"', async () => {
|
test('should throw an error "Insufficient scope"', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -180,11 +178,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: ErrorResponse = res.json();
|
const resData: ErrorResponse = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 500);
|
expect(res.statusCode).toEqual(500);
|
||||||
assert.strictEqual(resData.message, 'Insufficient scope');
|
expect(resData.message).toEqual('Insufficient scope');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should verify user scope', async () => {
|
test('should verify user scope', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -215,11 +213,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
|
|
||||||
const resData: { foo: string } = res.json();
|
const resData: { foo: string } = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 200);
|
expect(res.statusCode).toEqual(200);
|
||||||
assert.strictEqual(resData.foo, 'bar');
|
expect(resData.foo).toEqual('bar');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when there is no callback', async () => {
|
test('should throw an error when there is no callback', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -251,11 +249,11 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: ErrorResponse = res.json();
|
const resData: ErrorResponse = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 500);
|
expect(res.statusCode).toEqual(500);
|
||||||
assert.strictEqual(resData.message, 'request.user.scope must be a string');
|
expect(resData.message).toEqual('request.user.scope must be a string');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should verify user scope when there is no callback', async () => {
|
test('should verify user scope when there is no callback', async () => {
|
||||||
const fastify = Fastify();
|
const fastify = Fastify();
|
||||||
await fastify.register(jwtAuthz);
|
await fastify.register(jwtAuthz);
|
||||||
|
|
||||||
@@ -286,7 +284,7 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
|||||||
});
|
});
|
||||||
const resData: { foo: string } = res.json();
|
const resData: { foo: string } = res.json();
|
||||||
|
|
||||||
assert.strictEqual(res.statusCode, 200);
|
expect(res.statusCode).toEqual(200);
|
||||||
assert.strictEqual(resData.foo, 'bar');
|
expect(resData.foo).toEqual('bar');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ if (error) {
|
|||||||
assert.ok(process.env.NODE_ENV);
|
assert.ok(process.env.NODE_ENV);
|
||||||
assert.ok(process.env.AUTH0_DOMAIN);
|
assert.ok(process.env.AUTH0_DOMAIN);
|
||||||
assert.ok(process.env.AUTH0_AUDIENCE);
|
assert.ok(process.env.AUTH0_AUDIENCE);
|
||||||
|
assert.ok(process.env.API_LOCATION);
|
||||||
assert.ok(process.env.SESSION_SECRET);
|
assert.ok(process.env.SESSION_SECRET);
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
@@ -35,4 +36,5 @@ export const NODE_ENV = process.env.NODE_ENV;
|
|||||||
export const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN;
|
export const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN;
|
||||||
export const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE;
|
export const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE;
|
||||||
export const PORT = process.env.PORT || '3000';
|
export const PORT = process.env.PORT || '3000';
|
||||||
|
export const API_LOCATION = process.env.API_LOCATION;
|
||||||
export const SESSION_SECRET = process.env.SESSION_SECRET;
|
export const SESSION_SECRET = process.env.SESSION_SECRET;
|
||||||
|
|||||||
+9
-12
@@ -1,18 +1,15 @@
|
|||||||
import assert from 'node:assert';
|
|
||||||
// eslint-disable-next-line import/no-unresolved
|
|
||||||
import { describe, it } from 'node:test';
|
|
||||||
import { base64URLEncode, challenge, verifier } from '.';
|
import { base64URLEncode, challenge, verifier } from '.';
|
||||||
|
|
||||||
describe('utils', { only: true }, () => {
|
describe('utils', () => {
|
||||||
it('base64URLEncode', () => {
|
test('base64URLEncode', () => {
|
||||||
assert.strictEqual(base64URLEncode(Buffer.from('test')), 'dGVzdA');
|
expect(base64URLEncode(Buffer.from('test'))).toEqual('dGVzdA');
|
||||||
});
|
});
|
||||||
it('verifier', () => {
|
|
||||||
const v = verifier;
|
test('verifier', () => {
|
||||||
assert.strictEqual(v.length, 43);
|
expect(verifier).toHaveLength(43);
|
||||||
});
|
});
|
||||||
it('challenge', () => {
|
|
||||||
const c = challenge;
|
test('challenge', () => {
|
||||||
assert.strictEqual(c.length, 43);
|
expect(challenge).toHaveLength(43);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
"test": "run-s create:* build:curriculum build-workers test:*",
|
"test": "run-s create:* build:curriculum build-workers test:*",
|
||||||
"test:source": "jest",
|
"test:source": "jest",
|
||||||
"test:curriculum": "cd ./curriculum && pnpm test",
|
"test:curriculum": "cd ./curriculum && pnpm test",
|
||||||
|
"test-api": "cd api && jest",
|
||||||
"test-curriculum-full-output": "cd ./curriculum && pnpm run test:full-output",
|
"test-curriculum-full-output": "cd ./curriculum && pnpm run test:full-output",
|
||||||
"test-client": "jest client",
|
"test-client": "jest client",
|
||||||
"test-config": "jest config",
|
"test-config": "jest config",
|
||||||
|
|||||||
Generated
+733
-1
File diff suppressed because it is too large
Load Diff
@@ -69,3 +69,9 @@ PEER=stuff
|
|||||||
DEBUG=true
|
DEBUG=true
|
||||||
LOCAL_MOCK_AUTH=true
|
LOCAL_MOCK_AUTH=true
|
||||||
CODESEE=false
|
CODESEE=false
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# New API
|
||||||
|
# ---------------------
|
||||||
|
NODE_ENV=development
|
||||||
|
PORT=3000
|
||||||
|
|||||||
Reference in New Issue
Block a user