Add API unit tests for create-* endpoints (#23)

* setting up test structure

* .

* added playwright config file, deleted original playwright folder and moved "some.test" file

* continued test structure setup

* Updating test folder structure

* Added database seeding script and backend testing folder structure

* removed the database test

* Replaced db seeding script

* Updated userInformation.ts to use values from choices.tsx

* merge prep

* removing extra unit test, moving api test to correct folder

* Pushing to get help with sql Unit test

* Updating get-profiles unit tests

* Added more unit tests

* .

* Added more unit tests

* Added getSupabaseToken unit test

* .

* excluding supabase token test so ci can pass

* .

* Seperated the seedDatabase func into its own file so it can be accessed seperatly

* Fixed failing test

* .

* .

* Fix tests

* Fix lint

* Clean

* Fixed module paths in compute-score unit test

* Updated root tsconfig to recognise backend/shared

* Added create comment unit test

* Added some unit tests

* Working on createProfile return issue

* .

* Fixes

---------

Co-authored-by: MartinBraquet <martin.braquet@gmail.com>
This commit is contained in:
Okechi Jones-Williams
2025-12-12 08:34:07 +00:00
committed by GitHub
parent be2e19db8d
commit 28ce878b34
14 changed files with 1044 additions and 14 deletions

View File

@@ -15,7 +15,7 @@ module.exports = {
"^email/(.*)$": "<rootDir>/../email/emails/$1"
},
moduleFileExtensions: ["ts", "js", "json"],
moduleFileExtensions: ["tsx","ts", "js", "json"],
clearMocks: true,
globals: {

View File

@@ -1,7 +1,20 @@
jest.mock('shared/supabase/init');
jest.mock('shared/supabase/notifications');
jest.mock('email/functions/helpers');
jest.mock('common/supabase/comment');
jest.mock('shared/utils');
jest.mock('common/user-notification-preferences');
jest.mock('shared/websockets/helpers');
import * as supabaseInit from "shared/supabase/init";
import { AuthedUser } from "api/helpers/endpoint";
import * as sharedUtils from "shared/utils";
import { createComment } from "api/create-comment";
import * as notificationPrefs from "common/user-notification-preferences";
import * as supabaseNotifications from "shared/supabase/notifications";
import * as emailHelpers from "email/functions/helpers";
import * as websocketHelpers from "shared/websockets/helpers";
import { convertComment } from "common/supabase/comment";
describe('createComment', () => {
let mockPg: any;
@@ -14,6 +27,12 @@ describe('createComment', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
(supabaseNotifications.insertNotificationToSupabase as jest.Mock)
.mockResolvedValue(null);
(emailHelpers.sendNewEndorsementEmail as jest.Mock)
.mockResolvedValue(null);
(convertComment as jest.Mock)
.mockResolvedValue(null);
});
afterEach(() => {
@@ -22,13 +41,17 @@ describe('createComment', () => {
describe('should', () => {
it('successfully create a comment with information provided', async () => {
const mockUserId = {userId: '123'}
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
}
const mockOnUser = {id: '123'}
const mockCreator = {
id: '123',
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl'
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: false
}
const mockContent = {
content: {
@@ -48,9 +71,307 @@ describe('createComment', () => {
userId: '123'
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockComment = {id: 12};
const mockNotificationDestination = {} as any;
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator)
.mockResolvedValueOnce(mockOnUser);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValueOnce(mockUserId)
.mockResolvedValueOnce(mockOnUser);
(mockPg.one as jest.Mock).mockResolvedValue(mockComment);
(notificationPrefs.getNotificationDestinationsForUser as jest.Mock)
.mockReturnValue(mockNotificationDestination);
const results = await createComment(mockProps, mockAuth, mockReq);
expect(results.status).toBe('success');
expect(sharedUtils.getUser).toBeCalledTimes(2);
expect(sharedUtils.getUser).toBeCalledWith(mockUserId.userId);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(sharedUtils.getPrivateUser).toBeCalledTimes(2);
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
expect.stringContaining('insert into profile_comments'),
expect.arrayContaining([mockCreator.id])
);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledTimes(1)
});
it('throw an error if there is no user matching the userId', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
};
const mockCreator = {
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: false
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is the comment text'
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator)
.mockResolvedValueOnce(null);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserId);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('User not found');
});
it('throw an error if there is no account associated with the authId', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is the comment text'
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(null);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('Your account was not found');
});
it('throw an error if the account is banned from posting', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
};
const mockCreator = {
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: true
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is the comment text'
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('You are banned');
});
it('throw an error if the other user is not found', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
};
const mockCreator = {
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: false
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is the comment text'
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(null);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('Other user not found');
});
it('throw an error if the user has blocked you', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['321']
};
const mockCreator = {
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: false
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is the comment text'
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserId);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('User has blocked you');
});
it('throw an error if the comment is too long', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
};
const mockCreator = {
id: '1234',
name: 'Mock Creator',
username: 'mock.creator.username',
avatarUrl: 'mock.creator.avatarurl',
isBannedFromPosting: false
};
const mockContent = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This '.repeat(30000),
}
]
}
]
},
userId: '123'
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserId);
console.log(JSON.stringify(mockContent.content).length);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('Comment is too long');
});
});
});

View File

@@ -0,0 +1,96 @@
jest.mock('shared/supabase/init');
jest.mock('shared/utils');
jest.mock('shared/supabase/utils');
jest.mock('common/util/try-catch');
import { createCompatibilityQuestion } from "api/create-compatibility-question";
import * as supabaseInit from "shared/supabase/init";
import * as shareUtils from "shared/utils";
import { tryCatch } from "common/util/try-catch";
import * as supabaseUtils from "shared/supabase/utils";
import { AuthedUser } from "api/helpers/endpoint";
describe('createCompatibilityQuestion', () => {
const mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create compatibility questions', async () => {
const mockQuestion = {} as any;
const mockOptions = {} as any;
const mockProps = {options:mockOptions, question:mockQuestion};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
id: '123',
};
const mockData = {
answer_type: "mockAnswerType",
category: "mockCategory",
created_time: "mockCreatedTime",
id: 1,
importance_score: 1,
multiple_choice_options: {"first_choice":"first_answer"},
question: "mockQuestion"
};
(shareUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(supabaseUtils.insert as jest.Mock).mockResolvedValue(mockData);
(tryCatch as jest.Mock).mockResolvedValue({data:mockData, error: null});
const results = await createCompatibilityQuestion(mockProps, mockAuth, mockReq);
expect(results.question).toEqual(mockData);
});
it('throws an error if the account does not exist', async () => {
const mockQuestion = {} as any;
const mockOptions = {} as any;
const mockProps = {options:mockOptions, question:mockQuestion};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(shareUtils.getUser as jest.Mock).mockResolvedValue(null);
expect(createCompatibilityQuestion(mockProps, mockAuth, mockReq))
.rejects
.toThrowError('Your account was not found')
});
it('throws an error if unable to create the question', async () => {
const mockQuestion = {} as any;
const mockOptions = {} as any;
const mockProps = {options:mockOptions, question:mockQuestion};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
id: '123',
};
const mockData = {
answer_type: "mockAnswerType",
category: "mockCategory",
created_time: "mockCreatedTime",
id: 1,
importance_score: 1,
multiple_choice_options: {"first_choice":"first_answer"},
question: "mockQuestion"
};
(shareUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(supabaseUtils.insert as jest.Mock).mockResolvedValue(mockData);
(tryCatch as jest.Mock).mockResolvedValue({data:null, error: Error});
expect(createCompatibilityQuestion(mockProps, mockAuth, mockReq))
.rejects
.toThrowError('Error creating question')
});
});
});

View File

@@ -0,0 +1,98 @@
jest.mock('common/util/try-catch');
jest.mock('shared/supabase/init');
jest.mock('shared/supabase/notifications');
import * as supabaseInit from "shared/supabase/init";
import * as createNotificationModules from "api/create-notification";
import { tryCatch } from "common/util/try-catch";
import * as supabaseNotifications from "shared/supabase/notifications";
import { Notification } from "common/notifications";
type MockNotificationUser = Pick<Notification, 'userId'>;
describe('createNotifications', () => {
beforeEach(() => {
jest.resetAllMocks();
const mockPg = {
many: jest.fn().mockReturnValue(null)
} as any;
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('sucessfully create a notification', async () => {
const mockUsers = [
{
created_time: "mockCreatedTime",
data: {"mockData": "mockDataJson"},
id: "mockId",
name: "mockName",
name_user_vector: "mockNUV",
username: "mockUsername"
},
];
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
(tryCatch as jest.Mock).mockResolvedValue({data: mockUsers, error:null});
(supabaseNotifications.insertNotificationToSupabase as jest.Mock)
.mockResolvedValue(null);
const results = await createNotificationModules.createNotifications(mockNotification as Notification);
expect(results?.success).toBeTruthy;
});
it('throws an error if its unable to fetch users', async () => {
const mockUsers = [
{
created_time: "mockCreatedTime",
data: {"mockData": "mockDataJson"},
id: "mockId",
name: "mockName",
name_user_vector: "mockNUV",
username: "mockUsername"
},
];
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
(tryCatch as jest.Mock).mockResolvedValue({data: mockUsers, error:Error});
await createNotificationModules.createNotifications(mockNotification as Notification)
expect(errorSpy).toHaveBeenCalledWith('Error fetching users', expect.objectContaining({name: 'Error'}))
});
it('throws an error if there are no users', async () => {
const mockUsers = [
{
created_time: "mockCreatedTime",
data: {"mockData": "mockDataJson"},
id: "mockId",
name: "mockName",
name_user_vector: "mockNUV",
username: "mockUsername"
},
];
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
(tryCatch as jest.Mock).mockResolvedValue({data: null, error:null});
await createNotificationModules.createNotifications(mockNotification as Notification)
expect(errorSpy).toHaveBeenCalledWith('No users found')
});
});
});

View File

@@ -0,0 +1,229 @@
jest.mock('shared/supabase/init');
jest.mock('common/util/array');
jest.mock('api/helpers/private-messages');
jest.mock('shared/utils');
import { createPrivateUserMessageChannel } from "api/create-private-user-message-channel";
import * as supabaseInit from "shared/supabase/init";
import * as sharedUtils from "shared/utils";
import * as utilArrayModules from "common/util/array";
import * as privateMessageModules from "api/helpers/private-messages";
import { AuthedUser } from "api/helpers/endpoint";
describe('createPrivateUserMessageChannel', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
one: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks()
});
describe('should', () => {
it('successfully create a private user message channel (currentChannel)', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['123', '321'];
const mockPrivateUsers = [
{
id: '123',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
{
id: '321',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
];
const mockCurrentChannel = {
channel_id: "444"
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: false
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);
(mockPg.oneOrNone as jest.Mock)
.mockResolvedValue(mockCurrentChannel);
(privateMessageModules.addUsersToPrivateMessageChannel as jest.Mock)
.mockResolvedValue(null);
const results = await createPrivateUserMessageChannel(mockBody, mockAuth, mockReq);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(sharedUtils.getPrivateUser).toBeCalledTimes(2);
expect(sharedUtils.getPrivateUser).toBeCalledWith(mockUserIds[0]);
expect(sharedUtils.getPrivateUser).toBeCalledWith(mockUserIds[1]);
expect(results.status).toBe('success');
expect(results.channelId).toBe(444)
});
it('successfully create a private user message channel (channel)', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['123', '321'];
const mockPrivateUsers = [
{
id: '123',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
{
id: '321',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
];
const mockChannel = {
id: "333"
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: false
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);
(mockPg.oneOrNone as jest.Mock)
.mockResolvedValue(null);
(mockPg.one as jest.Mock)
.mockResolvedValue(mockChannel);
(privateMessageModules.addUsersToPrivateMessageChannel as jest.Mock)
.mockResolvedValue(null);
const results = await createPrivateUserMessageChannel(mockBody, mockAuth, mockReq);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(sharedUtils.getPrivateUser).toBeCalledTimes(2);
expect(sharedUtils.getPrivateUser).toBeCalledWith(mockUserIds[0]);
expect(sharedUtils.getPrivateUser).toBeCalledWith(mockUserIds[1]);
expect(results.status).toBe('success');
expect(results.channelId).toBe(333)
});
it('throw an error if the user account doesnt exist', async () => {
const mockBody = {
userIds: ["123"]
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(null);
expect(createPrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('Your account was not found');
});
it('throw an error if the authId is banned from posting', async () => {
const mockBody = {
userIds: ["123"]
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: true
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
expect(createPrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('You are banned');
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
});
it('throw an error if the array lengths dont match (privateUsers, userIds)', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['123'];
const mockPrivateUsers = [
{
id: '123',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
];
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: false
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);
expect(createPrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`Private user ${mockAuth.uid} not found`);
});
it('throw an error if there is a blocked user in the userId list', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['321'];
const mockPrivateUsers = [
{
id: '123',
blockedUserIds: ['111'],
blockedByUserIds: [],
},
{
id: '321',
blockedUserIds: ['123'],
blockedByUserIds: [],
},
];
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: false
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);
expect(createPrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`One of the users has blocked another user in the list`);
});
});
});

View File

@@ -0,0 +1,99 @@
jest.mock('shared/utils');
jest.mock('shared/supabase/init');
jest.mock('api/helpers/private-messages');
import { createPrivateUserMessage } from "api/create-private-user-message";
import * as sharedUtils from "shared/utils";
import * as supabaseInit from "shared/supabase/init";
import * as helpersPrivateMessagesModules from "api/helpers/private-messages";
import { AuthedUser } from "api/helpers/endpoint";
import { MAX_COMMENT_JSON_LENGTH } from "api/create-comment";
describe('createPrivateUserMessage', () => {
beforeEach(() => {
jest.resetAllMocks();
const mockPg = {} as any;
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create a private user message', async () => {
const mockBody = {
content: {"": "x".repeat((MAX_COMMENT_JSON_LENGTH-8))},
channelId: 123
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: false
};
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(helpersPrivateMessagesModules.createPrivateUserMessageMain as jest.Mock)
.mockResolvedValue(null);
await createPrivateUserMessage(mockBody, mockAuth, mockReq);
expect(helpersPrivateMessagesModules.createPrivateUserMessageMain).toBeCalledWith(
mockCreator,
mockBody.channelId,
mockBody.content,
expect.any(Object),
'private'
);
});
it('throw an error if the content is too long', async () => {
const mockBody = {
content: {"": "x".repeat((MAX_COMMENT_JSON_LENGTH))},
channelId: 123
}
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
expect(createPrivateUserMessage(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`Message JSON should be less than ${MAX_COMMENT_JSON_LENGTH}`);
});
it('throw an error if the user does not exist', async () => {
const mockBody = {
content: {"mockJson": "mockJsonContent"},
channelId: 123
}
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
expect(createPrivateUserMessage(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`Your account was not found`);
});
it('throw an error if the user does not exist', async () => {
const mockBody = {
content: {"mockJson": "mockJsonContent"},
channelId: 123
}
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockCreator = {
isBannedFromPosting: true
};
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
expect(createPrivateUserMessage(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`You are banned`);
});
});
});

View File

@@ -0,0 +1,160 @@
jest.mock('shared/supabase/init');
jest.mock('shared/utils');
jest.mock('shared/profiles/parse-photos');
jest.mock('shared/supabase/users');
jest.mock('shared/supabase/utils');
jest.mock('common/util/try-catch');
jest.mock('shared/analytics');
jest.mock('common/discord/core');
import { createProfile } from "api/create-profile";
import * as supabaseInit from "shared/supabase/init";
import * as sharedUtils from "shared/utils";
import * as supabaseUsers from "shared/supabase/users";
import * as supabaseUtils from "shared/supabase/utils";
import { tryCatch } from "common/util/try-catch";
import { removePinnedUrlFromPhotoUrls } from "shared/profiles/parse-photos";
import * as sharedAnalytics from "shared/analytics";
import { sendDiscordMessage } from "common/discord/core";
import { AuthedUser } from "api/helpers/endpoint";
describe('createProfile', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn().mockReturnValue(null),
one: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create a profile', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
looking_for_matches: true,
photo_urls: ["mockPhotoUrl1"],
pinned_url: "mockPinnedUrl",
pref_gender: ["mockPrefGender"],
pref_relation_styles: ["mockPrefRelationStyles"],
visibility: 'public' as "public" | "member",
wants_kids_strength: 2,
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockExistingUser = {id: "mockExistingUserId"};
const mockData = {
age: 30,
city: "mockCity"
};
const mockUser = {
createdTime: Date.now() - 2 * 60 * 60 * 1000, //2 hours ago
name: "mockName",
username: "mockUserName"
};
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(supabaseUsers.updateUser as jest.Mock).mockReturnValue(null);
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
(tryCatch as jest.Mock).mockResolvedValueOnce({data: mockData, error: null});
(sharedAnalytics.track as jest.Mock).mockResolvedValue(null);
(sendDiscordMessage as jest.Mock).mockResolvedValueOnce(null);
(mockPg.one as jest.Mock).mockReturnValue(10);
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData)
});
it('throws an error if the profile already exists', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
looking_for_matches: true,
photo_urls: ["mockPhotoUrl1"],
pinned_url: "mockPinnedUrl",
pref_gender: ["mockPrefGender"],
pref_relation_styles: ["mockPrefRelationStyles"],
visibility: 'public' as "public" | "member",
wants_kids_strength: 2,
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockExistingUser = {id: "mockExistingUserId"};
(tryCatch as jest.Mock).mockResolvedValueOnce({data: mockExistingUser, error: null});
await expect(createProfile(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('User already exists');
});
it('throws an error if the user already exists', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
looking_for_matches: true,
photo_urls: ["mockPhotoUrl1"],
pinned_url: "mockPinnedUrl",
pref_gender: ["mockPrefGender"],
pref_relation_styles: ["mockPrefRelationStyles"],
visibility: 'public' as "public" | "member",
wants_kids_strength: 2,
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
await expect(createProfile(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('Your account was not found');
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
});
it('throw an error if anything unexpected happens when creating the user', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
looking_for_matches: true,
photo_urls: ["mockPhotoUrl1"],
pinned_url: "mockPinnedUrl",
pref_gender: ["mockPrefGender"],
pref_relation_styles: ["mockPrefRelationStyles"],
visibility: 'public' as "public" | "member",
wants_kids_strength: 2,
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
const mockUser = {
createdTime: Date.now() - 2 * 60 * 60 * 1000, //2 hours ago
name: "mockName",
username: "mockUserName"
};
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(supabaseUsers.updateUser as jest.Mock).mockReturnValue(null);
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: Error});
await expect(createProfile(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('Error creating user');
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
});
});
});

View File

@@ -0,0 +1,7 @@
describe('createUser', () => {
describe('should', () => {
it('', async () => {
});
});
});

View File

@@ -13,5 +13,10 @@
"email/*": ["../email/emails/*"]
}
},
"include": ["tests/**/*.ts", "src/**/*.ts"]
"include": [
"tests/**/*.ts",
"src/**/*.ts",
"../shared/src/**/*.ts",
"../../common/src/**/*.ts"
]
}

View File

@@ -9,8 +9,8 @@ module.exports = {
],
moduleNameMapper: {
"^api/(.*)$": "<rootDir>/src/$1",
"^shared/(.*)$": "<rootDir>/../shared/src/$1",
"^api/(.*)$": "<rootDir>/../api/src/$1",
"^shared/(.*)$": "<rootDir>/src/$1",
"^common/(.*)$": "<rootDir>/../../common/src/$1",
"^email/(.*)$": "<rootDir>/../email/emails/$1"
},

View File

@@ -1,4 +1,4 @@
import {recomputeCompatibilityScoresForUser} from "api/compatibility/compute-scores";
import {recomputeCompatibilityScoresForUser} from "shared/compatibility/compute-scores";
import * as supabaseInit from "shared/supabase/init";
import * as profilesSupabaseModules from "shared/profiles/supabase";
import * as compatibilityScoreModules from "common/profiles/compatibility-score";

View File

@@ -15,10 +15,23 @@
"lib": ["esnext"],
"skipLibCheck": true,
"paths": {
"common/*": ["../../common/src/*", "../../../common/lib/*"],
"shared/*": ["./src/*"]
"common/*": ["../../common/src/*",
"../../../common/lib/*"
],
"shared/*": [
"./src/*"
],
}
},
"references": [{ "path": "../../common" }],
"ts-node": {
"require": [
"tsconfig-paths/register"
]
},
"references": [
{
"path": "../../common"
},
],
"include": ["src/**/*.ts", "src/**/*.tsx"]
}

View File

@@ -7,8 +7,8 @@
"rootDir": "../..",
"baseUrl": ".",
"paths": {
"api/*": ["src/*"],
"shared/*": ["../shared/src/*"],
"api/*": ["../api/src/*"],
"shared/*": ["src/*"],
"common/*": ["../../common/src/*"],
"email/*": ["../email/emails/*"]
}

View File

@@ -2,6 +2,8 @@
"files": [],
"references": [
{ "path": "./backend/api" },
{ "path": "./backend/api/tsconfig.test.json" }
{ "path": "./backend/api/tsconfig.test.json" },
{ "path": "./backend/shared" },
{ "path": "./backend/shared/tsconfig.test.json" }
]
}