chore: ingest source code

58 files from https://github.com/gothinkster/node-express-realworld-example-app
This commit is contained in:
2026-03-13 11:38:49 +00:00
commit 1d0b844e76
58 changed files with 12898 additions and 0 deletions

17
src/tests/prisma-mock.ts Normal file
View File

@@ -0,0 +1,17 @@
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended';
import prisma from '../prisma/prisma-client';
import { PrismaClient } from '@prisma/client';
jest.mock('../prisma/prisma-client', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}));
const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>;
beforeEach(() => {
mockReset(prismaMock);
});
export default prismaMock;

View File

@@ -0,0 +1,144 @@
import prismaMock from '../prisma-mock';
import {
deleteComment,
favoriteArticle,
unfavoriteArticle,
} from '../../app/routes/article/article.service';
describe('ArticleService', () => {
describe('deleteComment', () => {
test('should throw an error ', () => {
// Given
const id = 123;
const idUser = 456;
// When
// @ts-ignore
prismaMock.comment.findFirst.mockResolvedValue(null);
// Then
expect(deleteComment(id, idUser)).rejects.toThrowError();
});
});
describe('favoriteArticle', () => {
test('should return the favorited article', async () => {
// Given
const slug = 'How-to-train-your-dragon';
const username = 'RealWorld';
const mockedUserResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
const mockedArticleResponse = {
id: 123,
slug: 'How-to-train-your-dragon',
title: 'How to train your dragon',
description: '',
body: '',
createdAt: new Date(),
updatedAt: new Date(),
authorId: 456,
tagList: [],
favoritedBy: [],
author: {
username: 'RealWorld',
bio: null,
image: null,
followedBy: [],
},
};
// When
// @ts-ignore
prismaMock.user.findUnique.mockResolvedValue(mockedUserResponse);
// @ts-ignore
prismaMock.article.update.mockResolvedValue(mockedArticleResponse);
// Then
await expect(favoriteArticle(slug, mockedUserResponse.id)).resolves.toHaveProperty(
'favoritesCount',
);
});
test('should throw an error if no user is found', async () => {
// Given
const id = 123;
const slug = 'how-to-train-your-dragon';
const username = 'RealWorld';
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
await expect(favoriteArticle(slug, id)).rejects.toThrowError();
});
});
describe('unfavoriteArticle', () => {
test('should return the unfavorited article', async () => {
// Given
const slug = 'How-to-train-your-dragon';
const username = 'RealWorld';
const mockedUserResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
const mockedArticleResponse = {
id: 123,
slug: 'How-to-train-your-dragon',
title: 'How to train your dragon',
description: '',
body: '',
createdAt: new Date(),
updatedAt: new Date(),
authorId: 456,
tagList: [],
favoritedBy: [],
author: {
username: 'RealWorld',
bio: null,
image: null,
followedBy: [],
},
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedUserResponse);
prismaMock.article.update.mockResolvedValue(mockedArticleResponse);
// Then
await expect(unfavoriteArticle(slug, mockedUserResponse.id)).resolves.toHaveProperty(
'favoritesCount',
);
});
test('should throw an error if no user is found', async () => {
// Given
const id = 123;
const slug = 'how-to-train-your-dragon';
const username = 'RealWorld';
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
await expect(unfavoriteArticle(slug, id)).rejects.toThrowError();
});
});
});

View File

@@ -0,0 +1,254 @@
import * as bcrypt from 'bcryptjs';
import { createUser, getCurrentUser, login, updateUser } from '../../app/routes/auth/auth.service';
import prismaMock from '../prisma-mock';
describe('AuthService', () => {
describe('createUser', () => {
test('should create new user ', async () => {
// Given
const user = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
};
const mockedResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
// When
// @ts-ignore
prismaMock.user.create.mockResolvedValue(mockedResponse);
// Then
await expect(createUser(user)).resolves.toHaveProperty('token');
});
test('should throw an error when creating new user with empty username ', async () => {
// Given
const user = {
id: 123,
username: ' ',
email: 'realworld@me',
password: '1234',
};
// Then
const error = String({ errors: { username: ["can't be blank"] } });
await expect(createUser(user)).rejects.toThrow(error);
});
test('should throw an error when creating new user with empty email ', async () => {
// Given
const user = {
id: 123,
username: 'RealWorld',
email: ' ',
password: '1234',
};
// Then
const error = String({ errors: { email: ["can't be blank"] } });
await expect(createUser(user)).rejects.toThrow(error);
});
test('should throw an error when creating new user with empty password ', async () => {
// Given
const user = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: ' ',
};
// Then
const error = String({ errors: { password: ["can't be blank"] } });
await expect(createUser(user)).rejects.toThrow(error);
});
test('should throw an exception when creating a new user with already existing user on same username ', async () => {
// Given
const user = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
};
const mockedExistingUser = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedExistingUser);
// Then
const error = { email: ['has already been taken'] }.toString();
await expect(createUser(user)).rejects.toThrow(error);
});
});
describe('login', () => {
test('should return a token', async () => {
// Given
const user = {
email: 'realworld@me',
password: '1234',
};
const hashedPassword = await bcrypt.hash(user.password, 10);
const mockedResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: hashedPassword,
bio: null,
image: null,
token: '',
demo: false,
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedResponse);
// Then
await expect(login(user)).resolves.toHaveProperty('token');
});
test('should throw an error when the email is empty', async () => {
// Given
const user = {
email: ' ',
password: '1234',
};
// Then
const error = String({ errors: { email: ["can't be blank"] } });
await expect(login(user)).rejects.toThrow(error);
});
test('should throw an error when the password is empty', async () => {
// Given
const user = {
email: 'realworld@me',
password: ' ',
};
// Then
const error = String({ errors: { password: ["can't be blank"] } });
await expect(login(user)).rejects.toThrow(error);
});
test('should throw an error when no user is found', async () => {
// Given
const user = {
email: 'realworld@me',
password: '1234',
};
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
const error = String({ errors: { 'email or password': ['is invalid'] } });
await expect(login(user)).rejects.toThrow(error);
});
test('should throw an error if the password is wrong', async () => {
// Given
const user = {
email: 'realworld@me',
password: '1234',
};
const hashedPassword = await bcrypt.hash('4321', 10);
const mockedResponse = {
id: 123,
username: 'Gerome',
email: 'realworld@me',
password: hashedPassword,
bio: null,
image: null,
token: '',
demo: false,
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedResponse);
// Then
const error = String({ errors: { 'email or password': ['is invalid'] } });
await expect(login(user)).rejects.toThrow(error);
});
});
describe('getCurrentUser', () => {
test('should return a token', async () => {
// Given
const id = 123;
const mockedResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedResponse);
// Then
await expect(getCurrentUser(id)).resolves.toHaveProperty('token');
});
});
describe('updateUser', () => {
test('should return a token', async () => {
// Given
const user = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
};
const mockedResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
};
// When
prismaMock.user.update.mockResolvedValue(mockedResponse);
// Then
await expect(updateUser(user, user.id)).resolves.toHaveProperty('token');
});
});
});

View File

@@ -0,0 +1,145 @@
import prismaMock from '../prisma-mock';
import { followUser, getProfile, unfollowUser } from '../../app/routes/profile/profile.service';
describe('ProfileService', () => {
describe('getProfile', () => {
test('should return a following property', async () => {
// Given
const username = 'RealWorld';
const id = 123;
const mockedResponse = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
followedBy: [],
};
// When
// @ts-ignore
prismaMock.user.findUnique.mockResolvedValue(mockedResponse);
// Then
await expect(getProfile(username, id)).resolves.toHaveProperty('following');
});
test('should throw an error if no user is found', async () => {
// Given
const username = 'RealWorld';
const id = 123;
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
await expect(getProfile(username, id)).rejects.toThrowError();
});
});
describe('followUser', () => {
test('shoud return a following property', async () => {
// Given
const usernamePayload = 'AnotherUser';
const id = 123;
const mockedAuthUser = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
followedBy: [],
};
const mockedResponse = {
id: 123,
username: 'AnotherUser',
email: 'another@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
followedBy: [],
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedAuthUser);
prismaMock.user.update.mockResolvedValue(mockedResponse);
// Then
await expect(followUser(usernamePayload, id)).resolves.toHaveProperty('following');
});
test('shoud throw an error if no user is found', async () => {
// Given
const usernamePayload = 'AnotherUser';
const id = 123;
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
await expect(followUser(usernamePayload, id)).rejects.toThrowError();
});
});
describe('unfollowUser', () => {
test('shoud return a following property', async () => {
// Given
const usernamePayload = 'AnotherUser';
const id = 123;
const mockedAuthUser = {
id: 123,
username: 'RealWorld',
email: 'realworld@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
followedBy: [],
};
const mockedResponse = {
id: 123,
username: 'AnotherUser',
email: 'another@me',
password: '1234',
bio: null,
image: null,
token: '',
demo: false,
followedBy: [],
};
// When
prismaMock.user.findUnique.mockResolvedValue(mockedAuthUser);
prismaMock.user.update.mockResolvedValue(mockedResponse);
// Then
await expect(unfollowUser(usernamePayload, id)).resolves.toHaveProperty('following');
});
test('shoud throw an error if no user is found', async () => {
// Given
const usernamePayload = 'AnotherUser';
const id = 123;
// When
prismaMock.user.findUnique.mockResolvedValue(null);
// Then
await expect(unfollowUser(usernamePayload, id)).rejects.toThrowError();
});
});
});

View File

@@ -0,0 +1,6 @@
describe('TagService', () => {
describe('getTags', () => {
// TODO : prismaMock.tag.groupBy.mockResolvedValue(mockedResponse) doesn't work
test.todo('should return a list of strings');
});
});

View File

@@ -0,0 +1,79 @@
import profileMapper from '../../app/routes/profile/profile.utils';
describe('ProfileUtils', () => {
describe('profileMapper', () => {
test('should return a profile', () => {
// Given
const user = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
followedBy: [],
};
const id = 123;
// When
const expected = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
following: false,
};
// Then
expect(profileMapper(user, id)).toEqual(expected);
});
test('should return a profile followed by the user', () => {
// Given
const user = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
followedBy: [
{
id: 123,
},
],
};
const id = 123;
// When
const expected = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
following: true,
};
// Then
expect(profileMapper(user, id)).toEqual(expected);
});
test('should return a profile not followed by the user', () => {
// Given
const user = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
followedBy: [
{
username: 'NotRealWorld',
},
],
};
const id = 123;
// When
const expected = {
username: 'RealWorld',
bio: 'My happy life',
image: null,
following: false,
};
// Then
expect(profileMapper(user, id)).toEqual(expected);
});
});
});