Adding/Updating API unit tests (#26)

This commit is contained in:
Okechi Jones-Williams
2026-01-15 15:54:29 +00:00
committed by GitHub
parent a3c479ff92
commit 449b32d4bc
47 changed files with 3331 additions and 962 deletions

View File

@@ -11,8 +11,7 @@ import { throwErrorIfNotMod } from "shared/helpers/auth";
import * as constants from "common/envs/constants";
import * as supabaseUsers from "shared/supabase/users";
import * as sharedAnalytics from "shared/analytics";
import { } from "shared/helpers/auth";
import { APIError, AuthedUser } from "api/helpers/endpoint"
import { AuthedUser } from "api/helpers/endpoint"
describe('banUser', () => {
@@ -24,13 +23,13 @@ describe('banUser', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('ban a user successfully', async () => {
describe('when given valid input', () => {
it('should ban a user successfully', async () => {
const mockUser = {
userId: '123',
unban: false
@@ -42,15 +41,25 @@ describe('banUser', () => {
await banUser(mockUser, mockAuth, mockReq);
expect(throwErrorIfNotMod).toBeCalledTimes(1);
expect(throwErrorIfNotMod).toBeCalledWith(mockAuth.uid);
expect(constants.isAdminId).toBeCalledTimes(1);
expect(constants.isAdminId).toBeCalledWith(mockUser.userId);
expect(sharedAnalytics.trackPublicEvent)
.toBeCalledWith(mockAuth.uid, 'ban user', {userId: mockUser.userId});
expect(supabaseUsers.updateUser)
.toBeCalledWith(mockPg, mockUser.userId, {isBannedFromPosting: true});
expect(sharedAnalytics.trackPublicEvent).toBeCalledTimes(1);
expect(sharedAnalytics.trackPublicEvent).toBeCalledWith(
mockAuth.uid,
'ban user',
{userId: mockUser.userId}
);
expect(supabaseUsers.updateUser).toBeCalledTimes(1);
expect(supabaseUsers.updateUser).toBeCalledWith(
mockPg,
mockUser.userId,
{isBannedFromPosting: true}
);
});
it('unban a user successfully', async () => {
it('should unban a user successfully', async () => {
const mockUser = {
userId: '123',
unban: true
@@ -64,13 +73,20 @@ describe('banUser', () => {
expect(throwErrorIfNotMod).toBeCalledWith(mockAuth.uid);
expect(constants.isAdminId).toBeCalledWith(mockUser.userId);
expect(sharedAnalytics.trackPublicEvent)
.toBeCalledWith(mockAuth.uid, 'ban user', {userId: mockUser.userId});
expect(supabaseUsers.updateUser)
.toBeCalledWith(mockPg, mockUser.userId, {isBannedFromPosting: false});
expect(sharedAnalytics.trackPublicEvent).toBeCalledWith(
mockAuth.uid,
'ban user',
{userId: mockUser.userId}
);
expect(supabaseUsers.updateUser).toBeCalledWith(
mockPg,
mockUser.userId,
{isBannedFromPosting: false}
);
});
it('throw and error if the ban requester is not a mod or admin', async () => {
});
describe('when an error occurs', () => {
it('throw if the ban requester is not a mod or admin', async () => {
const mockUser = {
userId: '123',
unban: false
@@ -79,21 +95,16 @@ describe('banUser', () => {
const mockReq = {} as any;
(throwErrorIfNotMod as jest.Mock).mockRejectedValue(
new APIError(
403,
`User ${mockAuth.uid} must be an admin or trusted to perform this action.`
)
new Error(`User ${mockAuth.uid} must be an admin or trusted to perform this action.`)
);
await expect(banUser(mockUser, mockAuth, mockReq))
.rejects
.toThrowError(`User ${mockAuth.uid} must be an admin or trusted to perform this action.`);
expect(throwErrorIfNotMod).toBeCalledWith(mockAuth.uid);
expect(sharedAnalytics.trackPublicEvent).toBeCalledTimes(0);
expect(supabaseUsers.updateUser).toBeCalledTimes(0);
});
it('throw an error if the ban target is an admin', async () => {
it('throw if the ban target is an admin', async () => {
const mockUser = {
userId: '123',
unban: false
@@ -108,8 +119,6 @@ describe('banUser', () => {
.toThrowError('Cannot ban admin');
expect(throwErrorIfNotMod).toBeCalledWith(mockAuth.uid);
expect(constants.isAdminId).toBeCalledWith(mockUser.userId);
expect(sharedAnalytics.trackPublicEvent).toBeCalledTimes(0);
expect(supabaseUsers.updateUser).toBeCalledTimes(0);
});
});
});

View File

@@ -23,37 +23,35 @@ describe('blockUser', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
describe('when given valid input', () => {
it('block the user successfully', async () => {
const mockParams = { id: '123' }
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(supabaseUsers.updatePrivateUser as jest.Mock).mockResolvedValue(null);
await blockUserModule.blockUser(mockParams, mockAuth, mockReq)
expect(mockPg.tx).toHaveBeenCalledTimes(1)
expect(supabaseUsers.updatePrivateUser)
.toHaveBeenCalledWith(
expect.any(Object),
mockAuth.uid,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockParams.id)}
);
expect(supabaseUsers.updatePrivateUser)
.toHaveBeenCalledWith(
expect.any(Object),
mockParams.id,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockAuth.uid)}
);
expect(mockPg.tx).toHaveBeenCalledTimes(1);
expect(supabaseUsers.updatePrivateUser).toBeCalledTimes(2);
expect(supabaseUsers.updatePrivateUser).toHaveBeenNthCalledWith(
1,
expect.any(Object),
mockAuth.uid,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockParams.id)}
);
expect(supabaseUsers.updatePrivateUser).toHaveBeenNthCalledWith(
2,
expect.any(Object),
mockParams.id,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockAuth.uid)}
);
});
});
describe('when an error occurs', () => {
it('throw an error if the user tries to block themselves', async () => {
const mockParams = { id: '123' }
const mockAuth = {uid: '123'} as AuthedUser;
@@ -61,12 +59,9 @@ describe('blockUser', () => {
expect(blockUserModule.blockUser(mockParams, mockAuth, mockReq))
.rejects
.toThrowError('You cannot block yourself')
expect(mockPg.tx).toHaveBeenCalledTimes(0)
.toThrowError('You cannot block yourself');
});
});
});
describe('unblockUser', () => {
@@ -84,35 +79,32 @@ describe('unblockUser', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('block the user successfully', async () => {
describe('when given valid input', () => {
it('should block the user successfully', async () => {
const mockParams = { id: '123' }
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(supabaseUsers.updatePrivateUser as jest.Mock).mockResolvedValue(null);
await blockUserModule.unblockUser(mockParams, mockAuth, mockReq)
expect(mockPg.tx).toHaveBeenCalledTimes(1)
expect(supabaseUsers.updatePrivateUser)
.toHaveBeenCalledWith(
expect.any(Object),
mockAuth.uid,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockParams.id)}
);
expect(supabaseUsers.updatePrivateUser)
.toHaveBeenCalledWith(
expect.any(Object),
mockParams.id,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockAuth.uid)}
);
expect(mockPg.tx).toHaveBeenCalledTimes(1);
expect(supabaseUsers.updatePrivateUser).toBeCalledTimes(2);
expect(supabaseUsers.updatePrivateUser).toHaveBeenNthCalledWith(
1,
expect.any(Object),
mockAuth.uid,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockParams.id)}
);
expect(supabaseUsers.updatePrivateUser).toHaveBeenNthCalledWith(
2,
expect.any(Object),
mockParams.id,
{ blockedByUserIds: supabaseUtils.FieldVal.arrayConcat(mockAuth.uid)}
);
});
});

View File

@@ -1,32 +1,41 @@
import * as supabaseInit from "shared/supabase/init";
import {getCompatibleProfiles} from "api/compatible-profiles";
jest.mock('shared/supabase/init');
import {getCompatibleProfiles} from "api/compatible-profiles";
import * as supabaseInit from "shared/supabase/init";
jest.mock('shared/supabase/init')
describe('getCompatibleProfiles', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
const mockPg = {
none: jest.fn().mockResolvedValue(null),
one: jest.fn().mockResolvedValue(null),
oneOrNone: jest.fn().mockResolvedValue(null),
any: jest.fn().mockResolvedValue([]),
map: jest.fn().mockResolvedValue([["abc", {score: 0.69}]]),
} as any;
mockPg = {
map: jest.fn().mockResolvedValue([]),
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully get compatible profiles when supplied with a valid user Id', async () => {
const results = await getCompatibleProfiles("123");
expect(results.status).toEqual('success');
expect(results.profileCompatibilityScores).toEqual({"abc": {score: 0.69}});
});
describe('when given valid input', () => {
it('should successfully get compatible profiles', async () => {
const mockProps = '123';
const mockScores = ["abc", { score: 0.69 }];
const mockScoresFromEntries = {"abc": { score: 0.69 }};
(mockPg.map as jest.Mock).mockResolvedValue([mockScores]);
const results = await getCompatibleProfiles(mockProps);
const [sql, param, fn] = mockPg.map.mock.calls[0];
expect(results.status).toEqual('success');
expect(results.profileCompatibilityScores).toEqual(mockScoresFromEntries);
expect(mockPg.map).toBeCalledTimes(1);
expect(sql).toContain('select *');
expect(sql).toContain('from compatibility_scores');
expect(param).toStrictEqual([mockProps]);
expect(fn).toEqual(expect.any(Function));
});
});
});

View File

@@ -14,7 +14,6 @@ describe('contact', () => {
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
};
@@ -22,13 +21,12 @@ describe('contact', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('send a discord message to the user', async () => {
describe('when given valid input', () => {
it('should send a discord message to the user', async () => {
const mockProps = {
content: {
type: 'doc',
@@ -52,29 +50,42 @@ describe('contact', () => {
const mockReturnData = {} as any;
(tryCatch as jest.Mock).mockResolvedValue({ data: mockReturnData, error: null });
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockDbUser);
(sendDiscordMessage as jest.Mock).mockResolvedValue(null);
const results = await contact(mockProps, mockAuth, mockReq);
expect(results.success).toBe(true);
expect(results.result).toStrictEqual({});
expect(tryCatch).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledTimes(1)
expect(supabaseUtils.insert).toBeCalledWith(
mockPg,
expect.any(Object),
'contact',
{
user_id: mockProps.userId,
content: JSON.stringify(mockProps.content)
}
);
expect(results.success).toBe(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockDbUser);
await results.continue();
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select name from users where id = $1'),
[mockProps.userId]
);
expect(sendDiscordMessage).toBeCalledTimes(1);
expect(sendDiscordMessage).toBeCalledWith(
expect.stringContaining(`New message from ${mockDbUser.name}`),
'contact'
)
expect(sendDiscordMessage).toBeCalledTimes(1);
);
});
it('throw an error if the inser function fails', async () => {
});
describe('when an error occurs', () => {
it('should throw if the insert function fails', async () => {
const mockProps = {
content: {
type: 'doc',
@@ -100,15 +111,59 @@ describe('contact', () => {
expect(contact(mockProps, mockAuth, mockReq))
.rejects
.toThrowError('Failed to submit contact message');
});
it('should throw if unable to send discord message', async () => {
const mockProps = {
content: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Error test message'
}
]
}
]
},
userId: '123'
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockDbUser = { name: 'Humphrey Mocker' };
const mockReturnData = {} as any;
(tryCatch as jest.Mock).mockResolvedValue({ data: mockReturnData, error: null });
const results = await contact(mockProps, mockAuth, mockReq);
expect(results.success).toBe(true);
expect(results.result).toStrictEqual({});
expect(tryCatch).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledTimes(1)
expect(supabaseUtils.insert).toBeCalledWith(
mockPg,
expect.any(Object),
'contact',
{
user_id: mockProps.userId,
content: JSON.stringify(mockProps.content)
}
);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockDbUser);
(sendDiscordMessage as jest.Mock).mockRejectedValue(new Error('Unable to send message'));
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
await results.continue();
expect(errorSpy).toBeCalledTimes(1);
expect(errorSpy).toBeCalledWith(
expect.stringContaining('Failed to send discord contact'),
expect.objectContaining({name: 'Error'})
);
});
});
});

View File

@@ -8,7 +8,6 @@ describe('createBookmarkedSearch', () => {
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
one: jest.fn(),
};
@@ -16,13 +15,12 @@ describe('createBookmarkedSearch', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('insert a bookmarked search into the database', async () => {
describe('when given valid input', () => {
it('should insert a bookmarked search into the database', async () => {
const mockProps = {
search_filters: 'mock_search_filters',
location: 'mock_location',
@@ -30,9 +28,14 @@ describe('createBookmarkedSearch', () => {
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockInserted = "mockInsertedReturn";
await createBookmarkedSearch(mockProps, mockAuth, mockReq)
expect(mockPg.one).toBeCalledTimes(1)
(mockPg.one as jest.Mock).mockResolvedValue(mockInserted);
const result = await createBookmarkedSearch(mockProps, mockAuth, mockReq);
expect(result).toBe(mockInserted);
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toHaveBeenCalledWith(
expect.stringContaining('INSERT INTO bookmarked_searches'),
[

View File

@@ -15,32 +15,26 @@ 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";
import { richTextToString } from "common/util/parse";
describe('createComment', () => {
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
one: jest.fn()
};
(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(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create a comment with information provided', async () => {
describe('when given valid input', () => {
it('should successfully create a comment', async () => {
const mockUserId = {
userId: '123',
blockedUserIds: ['111']
@@ -74,12 +68,17 @@ describe('createComment', () => {
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
const mockComment = {id: 12};
const mockNotificationDestination = {} as any;
const mockNotificationDestination = {
sendToBrowser: true,
sendToMobile: false,
sendToEmail: true
};
const mockProps = {
userId: mockUserId.userId,
content: mockContent.content,
replyToCommentId: mockReplyToCommentId
};
const mockConvertCommentReturn = 'mockConverComment';
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator)
@@ -90,24 +89,51 @@ describe('createComment', () => {
(mockPg.one as jest.Mock).mockResolvedValue(mockComment);
(notificationPrefs.getNotificationDestinationsForUser as jest.Mock)
.mockReturnValue(mockNotificationDestination);
(convertComment as jest.Mock).mockReturnValue(mockConvertCommentReturn);
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.getUser).toHaveBeenNthCalledWith(1, mockAuth.uid);
expect(sharedUtils.getUser).toHaveBeenNthCalledWith(2, mockUserId.userId);
expect(sharedUtils.getPrivateUser).toBeCalledTimes(2);
expect(sharedUtils.getPrivateUser).toHaveBeenNthCalledWith(1, mockProps.userId);
expect(sharedUtils.getPrivateUser).toHaveBeenNthCalledWith(2, mockOnUser.id);
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
expect.stringContaining('insert into profile_comments'),
expect.arrayContaining([mockCreator.id])
[
mockCreator.id,
mockCreator.name,
mockCreator.username,
mockCreator.avatarUrl,
mockProps.userId,
mockProps.content,
mockProps.replyToCommentId
]
);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledTimes(1)
expect(notificationPrefs.getNotificationDestinationsForUser).toBeCalledTimes(1);
expect(notificationPrefs.getNotificationDestinationsForUser).toBeCalledWith(mockOnUser, 'new_endorsement');
expect(supabaseNotifications.insertNotificationToSupabase).toBeCalledTimes(1);
expect(supabaseNotifications.insertNotificationToSupabase).toBeCalledWith(
expect.any(Object),
expect.any(Object)
);
expect(emailHelpers.sendNewEndorsementEmail).toBeCalledTimes(1);
expect(emailHelpers.sendNewEndorsementEmail).toBeCalledWith(
mockOnUser,
mockCreator,
mockOnUser,
richTextToString(mockProps.content)
);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledTimes(1);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledWith(mockConvertCommentReturn);
});
});
it('throw an error if there is no user matching the userId', async () => {
describe('when an error occurs', () => {
it('should throw if there is no user matching the userId', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -147,14 +173,16 @@ describe('createComment', () => {
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator)
.mockResolvedValueOnce(null);
.mockResolvedValueOnce(false);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserId);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('User not found');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('User not found');
});
it('throw an error if there is no account associated with the authId', async () => {
it('throw if there is no account associated with the authId', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -188,10 +216,12 @@ describe('createComment', () => {
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(null);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('Your account was not found');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('Your account was not found');
});
it('throw an error if the account is banned from posting', async () => {
it('throw if the account is banned from posting', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -232,10 +262,12 @@ describe('createComment', () => {
(sharedUtils.getUser as jest.Mock)
.mockResolvedValueOnce(mockCreator);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('You are banned');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('You are banned');
});
it('throw an error if the other user is not found', async () => {
it('throw if the other user is not found', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -278,10 +310,12 @@ describe('createComment', () => {
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(null);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('Other user not found');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('Other user not found');
});
it('throw an error if the user has blocked you', async () => {
it('throw if the user has blocked you', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -324,10 +358,12 @@ describe('createComment', () => {
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserId);
expect(createComment( mockProps, mockAuth, mockReq )).rejects.toThrowError('User has blocked you');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('User has blocked you');
});
it('throw an error if the comment is too long', async () => {
it('throw if the comment is too long', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReplyToCommentId = {} as any;
@@ -369,9 +405,10 @@ describe('createComment', () => {
.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');
expect(createComment( mockProps, mockAuth, mockReq ))
.rejects
.toThrowError('Comment is too long');
});
});
});

View File

@@ -18,12 +18,12 @@ describe('createCompatibilityQuestion', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create compatibility questions', async () => {
describe('when given valid input', () => {
it('should successfully create compatibility questions', async () => {
const mockQuestion = {} as any;
const mockOptions = {} as any;
const mockProps = {options:mockOptions, question:mockQuestion};
@@ -41,31 +41,45 @@ describe('createCompatibilityQuestion', () => {
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);
expect(shareUtils.getUser).toBeCalledTimes(1);
expect(shareUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(supabaseUtils.insert).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledWith(
expect.any(Object),
'compatibility_prompts',
{
creator_id: mockCreator.id,
question: mockQuestion,
answer_type: 'compatibility_multiple_choice',
multiple_choice_options: mockOptions
}
);
});
it('throws an error if the account does not exist', async () => {
});
describe('when an error occurs', () => {
it('throws 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);
(shareUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(createCompatibilityQuestion(mockProps, mockAuth, mockReq))
.rejects
.toThrowError('Your account was not found')
.toThrowError('Your account was not found');
});
it('throws an error if unable to create the question', async () => {
it('throws if unable to create the question', async () => {
const mockQuestion = {} as any;
const mockOptions = {} as any;
const mockProps = {options:mockOptions, question:mockQuestion};
@@ -74,23 +88,13 @@ describe('createCompatibilityQuestion', () => {
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')
.toThrowError('Error creating question');
});
});
});

View File

@@ -8,25 +8,23 @@ 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', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
const mockPg = {
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 () => {
describe('when given valid input', () => {
it('should sucessfully create a notification', async () => {
const mockUsers = [
{
created_time: "mockCreatedTime",
@@ -39,60 +37,89 @@ describe('createNotifications', () => {
];
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
} as Notification;
(tryCatch as jest.Mock).mockResolvedValue({data: mockUsers, error:null});
(supabaseNotifications.insertNotificationToSupabase as jest.Mock)
.mockResolvedValue(null);
jest.spyOn(createNotificationModules, 'createNotification');
const results = await createNotificationModules.createNotifications(mockNotification);
const results = await createNotificationModules.createNotifications(mockNotification as Notification);
expect(results?.success).toBeTruthy;
expect(tryCatch).toBeCalledTimes(1);
expect(mockPg.many).toBeCalledTimes(1);
expect(mockPg.many).toBeCalledWith('select * from users');
expect(createNotificationModules.createNotification).toBeCalledTimes(1);
expect(createNotificationModules.createNotification).toBeCalledWith(
mockUsers[0],
mockNotification,
expect.any(Object)
);
expect(supabaseNotifications.insertNotificationToSupabase).toBeCalledTimes(1);
expect(supabaseNotifications.insertNotificationToSupabase).toBeCalledWith(
mockNotification,
expect.any(Object)
);
});
});
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"
},
];
describe('when an error occurs', () => {
it('should throw if its unable to fetch users', async () => {
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
} as Notification;
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
(tryCatch as jest.Mock).mockResolvedValue({data: mockUsers, error:Error});
(tryCatch as jest.Mock).mockResolvedValue({data: null, error:Error});
await createNotificationModules.createNotifications(mockNotification as Notification)
expect(errorSpy).toHaveBeenCalledWith('Error fetching users', expect.objectContaining({name: 'Error'}))
await createNotificationModules.createNotifications(mockNotification);
expect(errorSpy).toBeCalledWith(
'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"
},
];
it('should throw if there are no users', async () => {
const mockNotification = {
userId: "mockUserId"
} as MockNotificationUser;
} as Notification;
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')
await createNotificationModules.createNotifications(mockNotification);
expect(errorSpy).toBeCalledWith('No users found');
});
it('should throw if unable to create 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 Notification;
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
(tryCatch as jest.Mock).mockResolvedValue({data: mockUsers, error:null});
jest.spyOn(createNotificationModules, 'createNotification').mockRejectedValue(new Error('Creation failure'));
await createNotificationModules.createNotifications(mockNotification);
expect(errorSpy).toBeCalledWith(
'Failed to create notification',
expect.objectContaining({name: 'Error'}),
mockUsers[0]
);
});
});
});

View File

@@ -23,13 +23,12 @@ describe('createPrivateUserMessageChannel', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks()
});
describe('should', () => {
it('successfully create a private user message channel (currentChannel)', async () => {
describe('when given valid input', () => {
it('should successfully create a private user message channel (currentChannel)', async () => {
const mockBody = {
userIds: ["123"]
};
@@ -55,29 +54,27 @@ describe('createPrivateUserMessageChannel', () => {
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);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(utilArrayModules.filterDefined as jest.Mock).mockReturnValue(mockPrivateUsers);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockCurrentChannel);
const results = await createPrivateUserMessageChannel(mockBody, mockAuth, mockReq);
expect(results.status).toBe('success');
expect(results.channelId).toBe(444);
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)
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select channel_id from private_user_message_channel_members'),
[mockUserIds]
);
});
it('successfully create a private user message channel (channel)', async () => {
it('should successfully create a private user message channel (channel)', async () => {
const mockBody = {
userIds: ["123"]
};
@@ -103,45 +100,54 @@ describe('createPrivateUserMessageChannel', () => {
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);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(utilArrayModules.filterDefined as jest.Mock).mockReturnValue(mockPrivateUsers);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
(mockPg.one as jest.Mock).mockResolvedValue(mockChannel);
const results = await createPrivateUserMessageChannel(mockBody, mockAuth, mockReq);
expect(results.status).toBe('success');
expect(results.channelId).toBe(333);
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)
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
expect.stringContaining('insert into private_user_message_channels default values returning id')
);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('insert into private_user_message_channel_members (channel_id, user_id, role, status)'),
[mockChannel.id, mockAuth.uid]
);
expect(privateMessageModules.addUsersToPrivateMessageChannel).toBeCalledTimes(1);
expect(privateMessageModules.addUsersToPrivateMessageChannel).toBeCalledWith(
[mockUserIds[0]],
mockChannel.id,
expect.any(Object)
);
});
it('throw an error if the user account doesnt exist', async () => {
});
describe('when an error occurs', () => {
it('should throw 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);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(createPrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('Your account was not found');
});
it('throw an error if the authId is banned from posting', async () => {
it('should throw if the authId is banned from posting', async () => {
const mockBody = {
userIds: ["123"]
};
@@ -151,21 +157,17 @@ describe('createPrivateUserMessageChannel', () => {
isBannedFromPosting: true
};
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(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 () => {
it('should throw if the array lengths dont match (privateUsers, userIds)', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['123'];
const mockPrivateUsers = [
{
id: '123',
@@ -181,8 +183,6 @@ describe('createPrivateUserMessageChannel', () => {
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);
@@ -191,11 +191,10 @@ describe('createPrivateUserMessageChannel', () => {
.toThrowError(`Private user ${mockAuth.uid} not found`);
});
it('throw an error if there is a blocked user in the userId list', async () => {
it('should throw if there is a blocked user in the userId list', async () => {
const mockBody = {
userIds: ["123"]
};
const mockUserIds = ['321'];
const mockPrivateUsers = [
{
id: '123',
@@ -216,8 +215,6 @@ describe('createPrivateUserMessageChannel', () => {
(sharedUtils.getUser as jest.Mock)
.mockResolvedValue(mockCreator);
(sharedUtils.getPrivateUser as jest.Mock)
.mockResolvedValue(mockUserIds);
(utilArrayModules.filterDefined as jest.Mock)
.mockReturnValue(mockPrivateUsers);

View File

@@ -23,7 +23,7 @@ describe('createPrivateUserMessage', () => {
jest.restoreAllMocks();
});
describe('should', () => {
describe('when given valid input', () => {
it('successfully create a private user message', async () => {
const mockBody = {
content: {"": "x".repeat((MAX_COMMENT_JSON_LENGTH-8))},
@@ -36,10 +36,12 @@ describe('createPrivateUserMessage', () => {
};
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockCreator);
(helpersPrivateMessagesModules.createPrivateUserMessageMain as jest.Mock)
.mockResolvedValue(null);
await createPrivateUserMessage(mockBody, mockAuth, mockReq);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(helpersPrivateMessagesModules.createPrivateUserMessageMain).toBeCalledTimes(1);
expect(helpersPrivateMessagesModules.createPrivateUserMessageMain).toBeCalledWith(
mockCreator,
mockBody.channelId,
@@ -48,8 +50,9 @@ describe('createPrivateUserMessage', () => {
'private'
);
});
it('throw an error if the content is too long', async () => {
});
describe('when an error occurs', () => {
it('should throw if the content is too long', async () => {
const mockBody = {
content: {"": "x".repeat((MAX_COMMENT_JSON_LENGTH))},
channelId: 123
@@ -62,7 +65,7 @@ describe('createPrivateUserMessage', () => {
.toThrowError(`Message JSON should be less than ${MAX_COMMENT_JSON_LENGTH}`);
});
it('throw an error if the user does not exist', async () => {
it('should throw if the user does not exist', async () => {
const mockBody = {
content: {"mockJson": "mockJsonContent"},
channelId: 123
@@ -70,14 +73,14 @@ describe('createPrivateUserMessage', () => {
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(createPrivateUserMessage(mockBody, mockAuth, mockReq))
.rejects
.toThrowError(`Your account was not found`);
});
it('throw an error if the user does not exist', async () => {
it('should throw if the user does not exist', async () => {
const mockBody = {
content: {"mockJson": "mockJsonContent"},
channelId: 123

View File

@@ -6,10 +6,7 @@ jest.mock('shared/supabase/utils');
jest.mock('common/util/try-catch');
jest.mock('shared/analytics');
jest.mock('common/discord/core');
jest.mock('common/util/time', () => {
const actual = jest.requireActual('common/util/time');
return{ ...actual, sleep: () => Promise.resolve()}
});
jest.mock('common/util/time');
import { createProfile } from "api/create-profile";
import * as supabaseInit from "shared/supabase/init";
@@ -24,25 +21,22 @@ import { AuthedUser } from "api/helpers/endpoint";
describe('createProfile', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn().mockReturnValue(null),
oneOrNone: jest.fn(),
one: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('should', () => {
it('successfully create a profile', async () => {
describe('when given valid input', () => {
it('should successfully create a profile', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
@@ -62,29 +56,41 @@ describe('createProfile', () => {
city: "mockCity"
};
const mockUser = {
createdTime: Date.now() - 2 * 60 * 60 * 1000, //2 hours ago
createdTime: Date.now(),
name: "mockName",
username: "mockUserName"
};
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: null});
(tryCatch as jest.Mock).mockResolvedValueOnce({data: false, 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});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1)
expect(tryCatch).toBeCalledTimes(2);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select id from profiles where user_id = $1'),
[mockAuth.uid]
);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1);
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockBody);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(supabaseUsers.updateUser).toBeCalledTimes(1);
expect(supabaseUsers.updateUser).toBeCalledWith(
expect.any(Object),
mockAuth.uid,
{avatarUrl: mockBody.pinned_url}
);
expect(supabaseUtils.insert).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledWith(
expect.any(Object),
'profiles',
expect.objectContaining({user_id: mockAuth.uid})
);
(sharedAnalytics.track as jest.Mock).mockResolvedValue(null);
(sendDiscordMessage as jest.Mock)
.mockResolvedValueOnce(null)
.mockResolvedValueOnce(null);
(mockPg.one as jest.Mock).mockReturnValue(mockNProfiles);
await results.continue();
@@ -102,7 +108,146 @@ describe('createProfile', () => {
);
});
it('successfully create milestone profile', async () => {
it('should successfully create milestone 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 mockNProfiles = 15
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: false, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(tryCatch as jest.Mock).mockResolvedValueOnce({data: mockData, error: null});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
(mockPg.one as jest.Mock).mockReturnValue(mockNProfiles);
await results.continue();
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
expect.stringContaining('SELECT count(*) FROM profiles'),
[],
expect.any(Function)
);
expect(sendDiscordMessage).toBeCalledTimes(2);
expect(sendDiscordMessage).toHaveBeenNthCalledWith(
2,
expect.stringContaining(String(mockNProfiles)),
'general'
);
});
});
describe('when an error occurs', () => {
it('should throw if it failed to track create 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 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: false, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(tryCatch as jest.Mock).mockResolvedValueOnce({data: mockData, error: null});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sharedAnalytics.track as jest.Mock).mockRejectedValue(new Error('Track error'));
await results.continue();
expect(errorSpy).toBeCalledWith(
'Failed to track create profile',
expect.objectContaining({name: 'Error'})
);
});
it('should throw if it failed to send discord new 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 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);
(tryCatch as jest.Mock).mockResolvedValueOnce({data: mockData, error: null});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sendDiscordMessage as jest.Mock).mockRejectedValue(new Error('Sending error'));
await results.continue();
expect(errorSpy).toBeCalledWith(
'Failed to send discord new profile',
expect.objectContaining({name: 'Error'})
);
});
it('should throw if it failed to send discord user milestone', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
@@ -129,47 +274,34 @@ describe('createProfile', () => {
(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});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1)
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockBody);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
(sharedAnalytics.track as jest.Mock).mockResolvedValue(null);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sendDiscordMessage as jest.Mock)
.mockResolvedValueOnce(null)
.mockResolvedValueOnce(null);
.mockRejectedValueOnce(new Error('Discord error'));
(mockPg.one as jest.Mock).mockReturnValue(mockNProfiles);
await results.continue();
expect(sharedAnalytics.track).toBeCalledTimes(1);
expect(sharedAnalytics.track).toBeCalledWith(
mockAuth.uid,
'create profile',
{username: mockUser.username}
);
expect(sendDiscordMessage).toBeCalledTimes(2);
expect(sendDiscordMessage).toHaveBeenNthCalledWith(
1,
expect.stringContaining(mockUser.name && mockUser.username),
'members'
);
expect(sendDiscordMessage).toHaveBeenNthCalledWith(
2,
expect.stringContaining(String(mockNProfiles)),
'general'
);
expect(errorSpy).toBeCalledWith(
'Failed to send discord user milestone',
expect.objectContaining({name: 'Error'})
);
});
it('throws an error if it failed to track create profile', async () => {
it('should throw if the user already exists', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
@@ -183,183 +315,15 @@ describe('createProfile', () => {
};
const mockAuth = {uid: '321'} as AuthedUser;
const mockReq = {} as any;
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});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1)
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockBody);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sharedAnalytics.track as jest.Mock).mockRejectedValue(null);
await results.continue();
expect(errorSpy).toBeCalledWith('Failed to track create profile', null)
});
it('throws an error if it failed to send discord new 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 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});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1)
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockBody);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sharedAnalytics.track as jest.Mock).mockResolvedValue(null);
(sendDiscordMessage as jest.Mock).mockRejectedValue(null);
await results.continue();
expect(sharedAnalytics.track).toBeCalledTimes(1);
expect(sharedAnalytics.track).toBeCalledWith(
mockAuth.uid,
'create profile',
{username: mockUser.username}
);
expect(errorSpy).toBeCalledWith('Failed to send discord new profile', null);
});
it('throws an error if it failed to send discord user milestone', 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 mockNProfiles = 15
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});
const results: any = await createProfile(mockBody, mockAuth, mockReq);
expect(results.result).toEqual(mockData);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1)
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockBody);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
const errorSpy = jest.spyOn(console , 'error').mockImplementation(() => {});
(sharedAnalytics.track as jest.Mock).mockResolvedValue(null);
(sendDiscordMessage as jest.Mock)
.mockResolvedValueOnce(null)
.mockRejectedValueOnce(null);
(mockPg.one as jest.Mock).mockReturnValue(mockNProfiles);
await results.continue();
expect(sharedAnalytics.track).toBeCalledTimes(1);
expect(sharedAnalytics.track).toBeCalledWith(
mockAuth.uid,
'create profile',
{username: mockUser.username}
);
expect(sendDiscordMessage).toBeCalledTimes(2);
expect(sendDiscordMessage).toHaveBeenNthCalledWith(
1,
expect.stringContaining(mockUser.name && mockUser.username),
'members'
);
expect(sendDiscordMessage).toHaveBeenNthCalledWith(
2,
expect.stringContaining(String(mockNProfiles)),
'general'
);
expect(errorSpy).toBeCalledWith('Failed to send discord user milestone', null);
});
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});
(tryCatch as jest.Mock).mockResolvedValueOnce({data: true, error: null});
await expect(createProfile(mockBody, mockAuth, mockReq))
.rejects
.toThrowError('User already exists');
});
it('throws an error if the user already exists', async () => {
it('should throw if unable to find the account', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
@@ -375,16 +339,14 @@ describe('createProfile', () => {
const mockReq = {} as any;
(tryCatch as jest.Mock).mockResolvedValueOnce({data: null, error: null});
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
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 () => {
it('should throw if anything unexpected happens when creating the user', async () => {
const mockBody = {
city: "mockCity",
gender: "mockGender",
@@ -406,15 +368,11 @@ describe('createProfile', () => {
(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

@@ -507,7 +507,7 @@ describe('createUser', () => {
});
describe('when an error occurs', () => {
it('should throw an error if the user already exists', async () => {
it('should throw if the user already exists', async () => {
const mockProps = {
deviceToken: "mockDeviceToken",
adminToken: "mockAdminToken"
@@ -556,7 +556,7 @@ describe('createUser', () => {
.toThrowError('User already exists');
});
it('should throw an error if the username is already taken', async () => {
it('should throw if the username is already taken', async () => {
const mockProps = {
deviceToken: "mockDeviceToken",
adminToken: "mockAdminToken"
@@ -606,7 +606,7 @@ describe('createUser', () => {
.toThrowError('Username already taken');
});
it('should throw an error if failed to track create profile', async () => {
it('should throw if failed to track create profile', async () => {
const mockProps = {
deviceToken: "mockDeviceToken",
adminToken: "mockAdminToken"
@@ -679,7 +679,7 @@ describe('createUser', () => {
expect(errorSpy).toHaveBeenCalledWith('Failed to track create profile', expect.any(Error));
});
it('should throw an error if failed to send a welcome email', async () => {
it('should throw if failed to send a welcome email', async () => {
Object.defineProperty(hostingConstants, 'IS_LOCAL', {
value: false,
writable: true
@@ -757,7 +757,7 @@ describe('createUser', () => {
expect(errorSpy).toBeCalledWith('Failed to sendWelcomeEmail', expect.any(Error));
});
it('should throw an error if failed to set last time online', async () => {
it('should throw if failed to set last time online', async () => {
const mockProps = {
deviceToken: "mockDeviceToken",
adminToken: "mockAdminToken"

View File

@@ -22,7 +22,7 @@ describe('createVote', () => {
});
describe('when given valid input', () => {
it('successfully creates a vote', async () => {
it('should successfully creates a vote', async () => {
const mockProps = {
title: 'mockTitle',
description: {'mockDescription': 'mockDescriptionValue'},
@@ -61,7 +61,7 @@ describe('createVote', () => {
});
});
describe('when an error occurs', () => {
it('should throw an error if the account was not found', async () => {
it('should throw if the account was not found', async () => {
const mockProps = {
title: 'mockTitle',
description: {'mockDescription': 'mockDescriptionValue'},
@@ -77,7 +77,7 @@ describe('createVote', () => {
.toThrow('Your account was not found');
});
it('should throw an error if unable to create a question', async () => {
it('should throw if unable to create a question', async () => {
const mockProps = {
title: 'mockTitle',
description: {'mockDescription': 'mockDescriptionValue'},

View File

@@ -20,7 +20,7 @@ describe('deleteBookmarkedSearch', () => {
});
describe('when given valid input', () => {
it('successfully deletes a bookmarked search', async () => {
it('should successfully deletes a bookmarked search', async () => {
const mockProps = {
id: 123
};
@@ -28,6 +28,7 @@ describe('deleteBookmarkedSearch', () => {
const mockReq = {} as any;
const result = await deleteBookmarkedSearch(mockProps, mockAuth, mockReq);
expect(result).toStrictEqual({});
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(

View File

@@ -54,7 +54,7 @@ describe('deleteCompatibilityAnswers', () => {
});
});
describe('when an error occurs', () => {
it('should throw an error if the user is not the answers author', async () => {
it('should throw if the user is not the answers author', async () => {
const mockProps = {
id: 123
};

View File

@@ -22,10 +22,10 @@ describe('deleteMe', () => {
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should delete the user account from supabase and firebase', async () => {
const mockUser = {
@@ -72,13 +72,11 @@ describe('deleteMe', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockRef = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
expect(deleteMe(mockRef, mockAuth, mockRef))
.rejects
.toThrow('Your account was not found');
});
it('should throw an error if there is no userId', async () => {
@@ -88,14 +86,11 @@ describe('deleteMe', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockRef = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
expect(deleteMe(mockRef, mockAuth, mockRef))
.rejects
.toThrow('Invalid user ID');
});
it('should throw if unable to remove user from firebase auth', async () => {

View File

@@ -21,6 +21,7 @@ describe('deleteMessage', () => {
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should delete a message', async () => {
const mockMessageId = {

View File

@@ -72,6 +72,7 @@ describe('editMessage', () => {
);
});
});
describe('when an error occurs', () => {
it('should throw if there is an issue with the message', async () => {
const mockProps = {

View File

@@ -16,6 +16,7 @@ describe('getCompatibilityQuestions', () => {
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should get compatibility questions', async () => {
const mockProps = {} as any;

View File

@@ -41,6 +41,7 @@ describe('getCurrentPrivateUser', () => {
);
});
});
describe('when an error occurs', () => {
it('should throw if unable to get users private data', async () => {
const mockAuth = { uid: '321' } as AuthedUser;

View File

@@ -43,6 +43,7 @@ describe('getOptions', () => {
expect(tryCatch).toBeCalledTimes(1);
});
});
describe('when an error occurs', () => {
it('should throw if the table is invalid', async () => {
const mockTable = "causes";
@@ -60,9 +61,6 @@ describe('getOptions', () => {
const mockTable = "causes";
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockData = [
{ name: "mockName" },
];
jest.spyOn(Array.prototype, 'includes').mockReturnValue(true);
(mockPg.manyOrNone as jest.Mock).mockResolvedValue(null);

View File

@@ -186,6 +186,7 @@ describe('getChannelMessagesEndpoint', () => {
});
});
describe('when an error occurs', () => {
it('should throw if unable to get messages', async () => {
const mockProps = {

View File

@@ -1,6 +1,7 @@
import * as profilesModule from "api/get-profiles";
import { Profile } from "common/profiles/profile";
import * as supabaseInit from "shared/supabase/init";
import * as sqlBuilder from "shared/supabase/sql-builder";
describe('getProfiles', () => {
beforeEach(() => {
@@ -11,8 +12,8 @@ describe('getProfiles', () => {
jest.restoreAllMocks();
});
describe('should fetch the user profiles', () => {
it('successfully', async ()=> {
describe('when given valid input', () => {
it('should successfully return profile information and count', async ()=> {
const mockProfiles = [
{
diet: ['Jonathon Hammon'],
@@ -27,19 +28,15 @@ describe('getProfiles', () => {
has_kids: 2,
}
] as Profile [];
jest.spyOn(profilesModule, 'loadProfiles').mockResolvedValue({profiles: mockProfiles, count: 3});
const props = {
limit: 2,
orderBy: "last_online_time" as const,
};
const mockReq = {} as any;
const results = await profilesModule.getProfiles(props, mockReq, mockReq);
if('continue' in results) {
throw new Error('Expected direct response')
};
jest.spyOn(profilesModule, 'loadProfiles').mockResolvedValue({profiles: mockProfiles, count: 3});
const results: any = await profilesModule.getProfiles(props, mockReq, mockReq);
expect(results.status).toEqual('success');
expect(results.profiles).toEqual(mockProfiles);
@@ -47,8 +44,10 @@ describe('getProfiles', () => {
expect(profilesModule.loadProfiles).toHaveBeenCalledWith(props);
expect(profilesModule.loadProfiles).toHaveBeenCalledTimes(1);
});
});
it('unsuccessfully', async () => {
describe('when an error occurs', () => {
it('should not return profile information', async () => {
jest.spyOn(profilesModule, 'loadProfiles').mockRejectedValue(null);
const props = {
@@ -56,278 +55,274 @@ describe('getProfiles', () => {
orderBy: "last_online_time" as const,
};
const mockReq = {} as any;
const results = await profilesModule.getProfiles(props, mockReq, mockReq);
if('continue' in results) {
throw new Error('Expected direct response')
};
const results: any = await profilesModule.getProfiles(props, mockReq, mockReq);
expect(results.status).toEqual('fail');
expect(results.profiles).toEqual([]);
expect(profilesModule.loadProfiles).toHaveBeenCalledWith(props);
expect(profilesModule.loadProfiles).toHaveBeenCalledTimes(1);
});
});
});
describe('loadProfiles', () => {
let mockPg: any;
describe('should call pg.map with an SQL query', () => {
beforeEach(() => {
jest.clearAllMocks();
mockPg = {
map: jest.fn().mockResolvedValue([]),
one: jest.fn().mockResolvedValue(1),
};
jest.spyOn(supabaseInit, 'createSupabaseDirectClient')
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
it('successfully', async () => {
await profilesModule.loadProfiles({
limit: 10,
name: 'John',
is_smoker: true,
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain('select');
expect(query).toContain('from profiles');
expect(query).toContain('where');
expect(query).toContain('limit 10');
expect(query).toContain(`John`);
expect(query).toContain(`is_smoker`);
expect(query).not.toContain(`gender`);
expect(query).not.toContain(`education_level`);
expect(query).not.toContain(`pref_gender`);
expect(query).not.toContain(`age`);
expect(query).not.toContain(`drinks_per_month`);
expect(query).not.toContain(`pref_relation_styles`);
expect(query).not.toContain(`pref_romantic_styles`);
expect(query).not.toContain(`diet`);
expect(query).not.toContain(`political_beliefs`);
expect(query).not.toContain(`religion`);
expect(query).not.toContain(`has_kids`);
});
beforeEach(() => {
jest.clearAllMocks();
mockPg = {
map: jest.fn(),
one: jest.fn()
};
it('that contains a gender filter', async () => {
await profilesModule.loadProfiles({
genders: ['Electrical_gender'],
jest.spyOn(supabaseInit, 'createSupabaseDirectClient')
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
describe('should call pg.map with an SQL query', () => {
it('successfully', async () => {
const mockProps = {
limit: 10,
name: 'John',
is_smoker: true,
};
(mockPg.map as jest.Mock).mockResolvedValue([]);
(mockPg.one as jest.Mock).mockResolvedValue(1);
jest.spyOn(sqlBuilder, 'renderSql');
jest.spyOn(sqlBuilder, 'select');
jest.spyOn(sqlBuilder, 'from');
jest.spyOn(sqlBuilder, 'where');
jest.spyOn(sqlBuilder, 'join');
await profilesModule.loadProfiles(mockProps);
const [query, values, cb] = mockPg.map.mock.calls[0];
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain('select');
expect(query).toContain('from profiles');
expect(query).toContain('where');
expect(query).toContain('limit 10');
expect(query).toContain(`John`);
expect(query).toContain(`is_smoker`);
expect(query).not.toContain(`gender`);
expect(query).not.toContain(`education_level`);
expect(query).not.toContain(`pref_gender`);
expect(query).not.toContain(`age`);
expect(query).not.toContain(`drinks_per_month`);
expect(query).not.toContain(`pref_relation_styles`);
expect(query).not.toContain(`pref_romantic_styles`);
expect(query).not.toContain(`diet`);
expect(query).not.toContain(`political_beliefs`);
expect(query).not.toContain(`religion`);
expect(query).not.toContain(`has_kids`);
expect(sqlBuilder.renderSql).toBeCalledTimes(3);
expect(sqlBuilder.select).toBeCalledTimes(3);
expect(sqlBuilder.from).toBeCalledTimes(2);
expect(sqlBuilder.where).toBeCalledTimes(8);
expect(sqlBuilder.join).toBeCalledTimes(1);
});
it('that contains a gender filter', async () => {
await profilesModule.loadProfiles({
genders: ['Electrical_gender'],
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`gender`);
expect(query).toContain(`Electrical_gender`);
});
it('that contains a education level filter', async () => {
await profilesModule.loadProfiles({
education_levels: ['High School'],
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`education_level`);
expect(query).toContain(`High School`);
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`gender`);
expect(query).toContain(`Electrical_gender`);
});
it('that contains a education level filter', async () => {
await profilesModule.loadProfiles({
education_levels: ['High School'],
it('that contains a prefer gender filter', async () => {
await profilesModule.loadProfiles({
pref_gender: ['female'],
});
const [query, values, cb] = mockPg.map.mock.calls[0]
console.log(query);
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_gender`);
expect(query).toContain(`female`);
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`education_level`);
expect(query).toContain(`High School`);
});
it('that contains a prefer gender filter', async () => {
await profilesModule.loadProfiles({
pref_gender: ['female'],
it('that contains a minimum age filter', async () => {
await profilesModule.loadProfiles({
pref_age_min: 20,
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`age`);
expect(query).toContain(`>= 20`);
});
const [query, values, cb] = mockPg.map.mock.calls[0]
console.log(query);
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_gender`);
expect(query).toContain(`female`);
});
it('that contains a maximum age filter', async () => {
await profilesModule.loadProfiles({
pref_age_max: 40,
});
it('that contains a minimum age filter', async () => {
await profilesModule.loadProfiles({
pref_age_min: 20,
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`age`);
expect(query).toContain(`<= 40`);
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`age`);
expect(query).toContain(`>= 20`);
});
it('that contains a minimum drinks per month filter', async () => {
await profilesModule.loadProfiles({
drinks_min: 4,
});
it('that contains a maximum age filter', async () => {
await profilesModule.loadProfiles({
pref_age_max: 40,
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`drinks_per_month`);
expect(query).toContain('4');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`age`);
expect(query).toContain(`<= 40`);
});
it('that contains a maximum drinks per month filter', async () => {
await profilesModule.loadProfiles({
drinks_max: 20,
});
it('that contains a minimum drinks per month filter', async () => {
await profilesModule.loadProfiles({
drinks_min: 4,
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`drinks_per_month`);
expect(query).toContain('20');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`drinks_per_month`);
expect(query).toContain('4');
});
it('that contains a relationship style filter', async () => {
await profilesModule.loadProfiles({
pref_relation_styles: ['Chill and relaxing'],
});
it('that contains a maximum drinks per month filter', async () => {
await profilesModule.loadProfiles({
drinks_max: 20,
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_relation_styles`);
expect(query).toContain('Chill and relaxing');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`drinks_per_month`);
expect(query).toContain('20');
});
it('that contains a romantic style filter', async () => {
await profilesModule.loadProfiles({
pref_romantic_styles: ['Sexy'],
});
it('that contains a relationship style filter', async () => {
await profilesModule.loadProfiles({
pref_relation_styles: ['Chill and relaxing'],
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_romantic_styles`);
expect(query).toContain('Sexy');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_relation_styles`);
expect(query).toContain('Chill and relaxing');
});
it('that contains a diet filter', async () => {
await profilesModule.loadProfiles({
diet: ['Glutton'],
});
it('that contains a romantic style filter', async () => {
await profilesModule.loadProfiles({
pref_romantic_styles: ['Sexy'],
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`diet`);
expect(query).toContain('Glutton');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`pref_romantic_styles`);
expect(query).toContain('Sexy');
});
it('that contains a political beliefs filter', async () => {
await profilesModule.loadProfiles({
political_beliefs: ['For the people'],
});
it('that contains a diet filter', async () => {
await profilesModule.loadProfiles({
diet: ['Glutton'],
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`political_beliefs`);
expect(query).toContain('For the people');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`diet`);
expect(query).toContain('Glutton');
});
it('that contains a religion filter', async () => {
await profilesModule.loadProfiles({
religion: ['The blood god'],
});
it('that contains a political beliefs filter', async () => {
await profilesModule.loadProfiles({
political_beliefs: ['For the people'],
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`religion`);
expect(query).toContain('The blood god');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`political_beliefs`);
expect(query).toContain('For the people');
});
it('that contains a has kids filter', async () => {
await profilesModule.loadProfiles({
has_kids: 3,
});
it('that contains a religion filter', async () => {
await profilesModule.loadProfiles({
religion: ['The blood god'],
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`has_kids`);
expect(query).toContain('> 0');
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`religion`);
expect(query).toContain('The blood god');
});
it('should return profiles from the database', async () => {
const mockProfiles = [
{
diet: ['Jonathon Hammon'],
is_smoker: true,
has_kids: 0
},
{
diet: ['Joseph Hammon'],
is_smoker: false,
has_kids: 1
},
{
diet: ['Jolene Hammon'],
is_smoker: true,
has_kids: 2,
}
] as Profile [];
const props = {} as any;
it('that contains a has kids filter', async () => {
await profilesModule.loadProfiles({
has_kids: 3,
(mockPg.map as jest.Mock).mockResolvedValue(mockProfiles);
(mockPg.one as jest.Mock).mockResolvedValue(1);
const results = await profilesModule.loadProfiles(props);
expect(results).toEqual({profiles: mockProfiles, count: 1});
});
const [query, values, cb] = mockPg.map.mock.calls[0]
expect(mockPg.map.mock.calls).toHaveLength(1)
expect(query).toContain(`has_kids`);
expect(query).toContain('> 0');
});
});
describe('should', () => {
beforeEach(() => {
jest.clearAllMocks();
mockPg = {
map: jest.fn(),
one: jest.fn().mockResolvedValue(1),
};
jest.spyOn(supabaseInit, 'createSupabaseDirectClient')
.mockReturnValue(mockPg)
});
afterEach(() => {
jest.restoreAllMocks();
});
it('return profiles from the database', async () => {
const mockProfiles = [
{
diet: ['Jonathon Hammon'],
is_smoker: true,
has_kids: 0
},
{
diet: ['Joseph Hammon'],
is_smoker: false,
has_kids: 1
},
{
diet: ['Jolene Hammon'],
is_smoker: true,
has_kids: 2,
}
] as Profile [];
mockPg.map.mockResolvedValue(mockProfiles);
const props = {} as any;
const results = await profilesModule.loadProfiles(props);
expect(results).toEqual({profiles: mockProfiles, count: 1});
});
it('throw an error if there is no compatability', async () => {
describe('when an error occurs', () => {
it('throw if there is no compatability', async () => {
const props = {
orderBy: 'compatibility_score'
}
expect(profilesModule.loadProfiles(props))
.rejects
.toThrowError('Incompatible with user ID')
});
})
})
});
});

View File

@@ -1,163 +1,90 @@
jest.mock("shared/supabase/init");
jest.mock("common/supabase/users");
jest.mock("common/api/user-types");
import { getUser } from "api/get-user";
import { createSupabaseDirectClient } from "shared/supabase/init";
import * as supabaseInit from "shared/supabase/init";
import { toUserAPIResponse } from "common/api/user-types";
import { convertUser } from "common/supabase/users";
import { APIError } from "common/api/utils";
jest.spyOn(require("common/supabase/users"), 'convertUser')
jest.spyOn(require("common/api/user-types"), 'toUserAPIResponse')
describe('getUser', () =>{
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
};
(createSupabaseDirectClient as jest.Mock).mockReturnValue(mockPg);
jest.clearAllMocks();
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when fetching by id', () => {
it('should fetch user successfully by id', async () => {
const mockDbUser = {
created_time: '2025-11-11T16:42:05.188Z',
data: { link: {}, avatarUrl: "", isBannedFromPosting: false },
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
name_username_vector: "'buckridg':2,4 'franklin':1,3",
username: 'Franky_Buck'
};
const mockConvertedUser = {
created_time: new Date(),
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
name_username_vector: "'buckridg':2,4 'franklin':1,3",
username: 'Franky_Buck'
};
const mockApiResponse = {
created_time: '2025-11-11T16:42:05.188Z',
data: { link: {}, avatarUrl: "", isBannedFromPosting: false },
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
username: 'Franky_Buck'
};
mockPg.oneOrNone.mockImplementation((query: string, values: any[], cb: (value: any) => any) => {
const result = cb(mockDbUser);
return Promise.resolve(result);
});
(convertUser as jest.Mock).mockReturnValue(mockConvertedUser);
( toUserAPIResponse as jest.Mock).mockReturnValue(mockApiResponse);
const result = await getUser({id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP'})
expect(mockPg.oneOrNone).toHaveBeenCalledWith(
expect.stringContaining('where id = $1'),
['feUaIfcxVmJZHJOVVfawLTTPgZiP'],
expect.any(Function)
);
expect(convertUser).toHaveBeenCalledWith(mockDbUser);
expect(toUserAPIResponse).toHaveBeenCalledWith(mockConvertedUser);
expect(result).toEqual(mockApiResponse);
});
describe('when given valid input', () => {
describe('and fetching by id', () => {
it('should fetch user successfully by id', async () => {
const mockProps = {id: "mockId"};
const mockUser = {} as any;
it('should throw 404 when user is not found by id', async () => {
mockPg.oneOrNone.mockImplementation((query: string, values: any[], cb: (value: any) => any) => {
return Promise.resolve(null);
});
(convertUser as jest.Mock).mockReturnValue(null)
try {
await getUser({id: '3333'});
fail('Should have thrown');
} catch (error) {
const apiError = error as APIError;
expect(apiError.code).toBe(404)
expect(apiError.message).toBe('User not found')
expect(apiError.details).toBeUndefined()
expect(apiError.name).toBe('APIError')
}
})
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockUser);
(toUserAPIResponse as jest.Mock).mockReturnValue('mockApiResponse');
})
const result = await getUser(mockProps);
describe('when fetching by username', () => {
it('should fetch user successfully by username', async () => {
const mockDbUser = {
created_time: '2025-11-11T16:42:05.188Z',
data: { link: {}, avatarUrl: "", isBannedFromPosting: false },
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
name_username_vector: "'buckridg':2,4 'franklin':1,3",
username: 'Franky_Buck'
};
const mockConvertedUser = {
created_time: new Date(),
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
name_username_vector: "'buckridg':2,4 'franklin':1,3",
username: 'Franky_Buck'
};
const mockApiResponse = {
created_time: '2025-11-11T16:42:05.188Z',
data: { link: {}, avatarUrl: "", isBannedFromPosting: false },
id: 'feUaIfcxVmJZHJOVVfawLTTPgZiP',
name: 'Franklin Buckridge',
username: 'Franky_Buck'
};
mockPg.oneOrNone.mockImplementation((query: string, values: any[], cb: (value: any) => any) => {
const result = cb(mockDbUser);
return Promise.resolve(result);
expect(result).toBe('mockApiResponse');
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select * from users'),
[mockProps.id],
expect.any(Function)
);
expect(toUserAPIResponse).toBeCalledTimes(1);
expect(toUserAPIResponse).toBeCalledWith(mockUser);
});
(convertUser as jest.Mock).mockReturnValue(mockConvertedUser);
(toUserAPIResponse as jest.Mock).mockReturnValue(mockApiResponse);
const result = await getUser({username: 'Franky_Buck'})
expect(mockPg.oneOrNone).toHaveBeenCalledWith(
expect.stringContaining('where username = $1'),
['Franky_Buck'],
expect.any(Function)
);
expect(convertUser).toHaveBeenCalledWith(mockDbUser);
expect(toUserAPIResponse).toHaveBeenCalledWith(mockConvertedUser);
expect(result).toEqual(mockApiResponse);
});
it('should throw 404 when user is not found by id', async () => {
mockPg.oneOrNone.mockImplementation((query: string, values: any[], cb: (value: any) => any) => {
return Promise.resolve(null);
});
describe('when fetching by username', () => {
it('should fetch user successfully by username', async () => {
const mockProps = {username: "mockUsername"};
const mockUser = {} as any;
(convertUser as jest.Mock).mockReturnValue(null)
try {
await getUser({username: '3333'});
fail('Should have thrown');
} catch (error) {
const apiError = error as APIError;
expect(apiError.code).toBe(404)
expect(apiError.message).toBe('User not found')
expect(apiError.details).toBeUndefined()
expect(apiError.name).toBe('APIError')
}
})
})
})
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockUser);
await getUser(mockProps)
expect(mockPg.oneOrNone).toHaveBeenCalledWith(
expect.stringContaining('where username = $1'),
[mockProps.username],
expect.any(Function)
);
});
});
});
describe('when an error occurs', () => {
describe('and fetching by id', () => {
it('should throw when user is not found by id', async () => {
const mockProps = {id: "mockId"};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(getUser(mockProps))
.rejects
.toThrow('User not found');
});
});
describe('when fetching by username', () => {
it('should throw when user is not found by id', async () => {
const mockProps = {username: "mockUsername"};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(getUser(mockProps))
.rejects
.toThrow('User not found');
});
});
});
});

View File

@@ -45,12 +45,11 @@ describe('hideComment', () => {
user_name: "mockUserName",
user_username: "mockUserUsername",
};
const mockConvertedComment = "mockConvertedCommentValue";
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockComment);
jest.spyOn(envConsts, 'isAdminId').mockReturnValue(true);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(convertComment as jest.Mock).mockReturnValue(null);
(websocketHelpers.broadcastUpdatedComment as jest.Mock).mockReturnValue(null);
(convertComment as jest.Mock).mockReturnValue(mockConvertedComment);
await hideComment(mockProps, mockAuth, mockReq);
@@ -64,7 +63,7 @@ describe('hideComment', () => {
expect(convertComment).toBeCalledTimes(1);
expect(convertComment).toBeCalledWith(mockComment);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledTimes(1);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledWith(null);
expect(websocketHelpers.broadcastUpdatedComment).toBeCalledWith(mockConvertedComment);
});
it('should successfully hide the comment if the user is the one who made the comment', async () => {
@@ -89,9 +88,6 @@ describe('hideComment', () => {
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockComment);
jest.spyOn(envConsts, 'isAdminId').mockReturnValue(false);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(convertComment as jest.Mock).mockReturnValue(null);
(websocketHelpers.broadcastUpdatedComment as jest.Mock).mockReturnValue(null);
await hideComment(mockProps, mockAuth, mockReq);
});
@@ -118,9 +114,6 @@ describe('hideComment', () => {
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockComment);
jest.spyOn(envConsts, 'isAdminId').mockReturnValue(false);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(convertComment as jest.Mock).mockReturnValue(null);
(websocketHelpers.broadcastUpdatedComment as jest.Mock).mockReturnValue(null);
await hideComment(mockProps, mockAuth, mockReq);
});
@@ -134,7 +127,7 @@ describe('hideComment', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(hideComment(mockProps, mockAuth, mockReq))
.rejects
@@ -163,9 +156,6 @@ describe('hideComment', () => {
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockComment);
jest.spyOn(envConsts, 'isAdminId').mockReturnValue(false);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(convertComment as jest.Mock).mockReturnValue(null);
(websocketHelpers.broadcastUpdatedComment as jest.Mock).mockReturnValue(null);
expect(hideComment(mockProps, mockAuth, mockReq))
.rejects

View File

@@ -29,12 +29,11 @@ describe('leavePrivateUserMessageChannel', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUser = { name: "mockName" };
const mockLeaveChatContent = "mockLeaveChatContentValue";
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(true);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(messageHelpers.leaveChatContent as jest.Mock).mockReturnValue(null);
(messageHelpers.insertPrivateMessage as jest.Mock).mockResolvedValue(null);
(messageHelpers.leaveChatContent as jest.Mock).mockReturnValue(mockLeaveChatContent);
const results = await leavePrivateUserMessageChannel(mockProps, mockAuth, mockReq);
@@ -56,7 +55,7 @@ describe('leavePrivateUserMessageChannel', () => {
expect(messageHelpers.leaveChatContent).toBeCalledWith(mockUser.name);
expect(messageHelpers.insertPrivateMessage).toBeCalledTimes(1);
expect(messageHelpers.insertPrivateMessage).toBeCalledWith(
null,
mockLeaveChatContent,
mockProps.channelId,
mockAuth.uid,
'system_status',
@@ -70,7 +69,7 @@ describe('leavePrivateUserMessageChannel', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(null);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(leavePrivateUserMessageChannel(mockProps, mockAuth, mockReq))
.rejects

View File

@@ -41,12 +41,10 @@ describe('likeProfile', () => {
target_id: "mockTargetId"
};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: false})
.mockResolvedValueOnce({data: mockData, error: null});
(likeModules.getHasFreeLike as jest.Mock).mockResolvedValue(true);
(mockPg.one as jest.Mock).mockResolvedValue(null);
const result: any = await likeProfile(mockProps, mockAuth, mockReq);
@@ -79,7 +77,6 @@ describe('likeProfile', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: true});
const result: any = await likeProfile(mockProps, mockAuth, mockReq);
@@ -101,7 +98,6 @@ describe('likeProfile', () => {
target_id: "mockTargetId"
};
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockData, error: null});
const result: any = await likeProfile(mockProps, mockAuth, mockReq);
@@ -130,7 +126,6 @@ describe('likeProfile', () => {
target_id: "mockTargetId"
};
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: mockData, error: Error});
@@ -153,7 +148,6 @@ describe('likeProfile', () => {
target_id: "mockTargetId"
};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: false})
.mockResolvedValueOnce({data: mockData, error: null});
@@ -179,7 +173,6 @@ describe('likeProfile', () => {
target_id: "mockTargetId"
};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: false})
.mockResolvedValueOnce({data: mockData, error: Error});

View File

@@ -25,8 +25,6 @@ describe('markAllNotifsRead', () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
await markAllNotifsRead(mockProps, mockAuth, mockReq);
expect(mockPg.none).toBeCalledTimes(1);

View File

@@ -0,0 +1,139 @@
jest.mock('shared/supabase/init');
jest.mock('api/helpers/private-messages');
import { reactToMessage } from "api/react-to-message";
import * as supabaseInit from "shared/supabase/init";
import * as messageHelpers from "api/helpers/private-messages";
import { AuthedUser } from "api/helpers/endpoint";
describe('reactToMessage', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success', async () => {
const mockProps = {
messageId: 123,
reaction: "mockReaction",
toDelete: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockMessage = { channel_id: "mockChannelId"};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockMessage);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(messageHelpers.broadcastPrivateMessages as jest.Mock).mockResolvedValue(null);
const result = await reactToMessage(mockProps, mockAuth, mockReq);
const [sql, params] = mockPg.oneOrNone.mock.calls[0]
const [sql1, params1] = mockPg.none.mock.calls[0]
expect(result.success).toBeTruthy();
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(params).toEqual([mockAuth.uid, mockProps.messageId])
expect(sql).toEqual(
expect.stringContaining('SELECT *')
);
expect(sql).toEqual(
expect.stringContaining('FROM private_user_message_channel_members m')
);
expect(mockPg.none).toBeCalledTimes(1);
expect(params1).toEqual([mockProps.reaction, mockAuth.uid, mockProps.messageId])
expect(sql1).toEqual(
expect.stringContaining('UPDATE private_user_messages')
);
expect(sql1).toEqual(
expect.stringContaining('SET reactions =')
);
expect(messageHelpers.broadcastPrivateMessages).toBeCalledTimes(1);
expect(messageHelpers.broadcastPrivateMessages).toBeCalledWith(
expect.any(Object),
mockMessage.channel_id,
mockAuth.uid
);
});
it('should return success when removing a reaction', async () => {
const mockProps = {
messageId: 123,
reaction: "mockReaction",
toDelete: true
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockMessage = { channel_id: "mockChannelId"};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockMessage);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(messageHelpers.broadcastPrivateMessages as jest.Mock).mockResolvedValue(null);
const result = await reactToMessage(mockProps, mockAuth, mockReq);
const [sql, params] = mockPg.oneOrNone.mock.calls[0]
const [sql1, params1] = mockPg.none.mock.calls[0]
expect(result.success).toBeTruthy();
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledTimes(1);
expect(params1).toEqual([mockProps.reaction, mockProps.messageId, mockAuth.uid])
expect(sql1).toEqual(
expect.stringContaining('UPDATE private_user_messages')
);
expect(sql1).toEqual(
expect.stringContaining('SET reactions = reactions - $1')
);
});
});
describe('when an error occurs', () => {
it('should throw if user does not have the authorization to react', async () => {
const mockProps = {
messageId: 123,
reaction: "mockReaction",
toDelete: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(reactToMessage(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Not authorized to react to this message');
});
it('should return success', async () => {
const mockProps = {
messageId: 123,
reaction: "mockReaction",
toDelete: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockMessage = { channel_id: "mockChannelId"};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockMessage);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(messageHelpers.broadcastPrivateMessages as jest.Mock).mockRejectedValue(new Error('Broadcast error'));
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
await reactToMessage(mockProps, mockAuth, mockReq);
expect(errorSpy).toBeCalledWith(
expect.stringContaining('broadcastPrivateMessages failed'),
expect.any(Error)
);
});
});
});

View File

@@ -0,0 +1,75 @@
jest.mock('shared/supabase/init');
jest.mock('common/envs/constants');
jest.mock('common/util/try-catch');
import { removePinnedPhoto } from "api/remove-pinned-photo";
import * as supabaseInit from "shared/supabase/init";
import * as envConstants from "common/envs/constants";
import { tryCatch } from "common/util/try-catch";
import { AuthedUser } from "api/helpers/endpoint";
describe('removePinnedPhoto', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success', async () => {
const mockBody = { userId: "mockUserId"};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(envConstants, 'isAdminId').mockReturnValue(true);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({error: null});
const result: any = await removePinnedPhoto(mockBody, mockAuth, mockReq);
expect(result.success).toBeTruthy();
expect(envConstants.isAdminId).toBeCalledTimes(1);
expect(envConstants.isAdminId).toBeCalledWith(mockAuth.uid);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('update profiles set pinned_url = null where user_id = $1'),
[mockBody.userId]
);
});
});
describe('when an error occurs', () => {
it('should throw if user auth is not an admin', async () => {
const mockBody = { userId: "mockUserId"};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(envConstants, 'isAdminId').mockReturnValue(false);
expect(removePinnedPhoto(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Only admins can remove pinned photo');
});
it('should throw if failed to remove the pinned photo', async () => {
const mockBody = { userId: "mockUserId"};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(envConstants, 'isAdminId').mockReturnValue(true);
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({error: Error});
expect(removePinnedPhoto(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Failed to remove pinned photo');
});
});
});

View File

@@ -0,0 +1,225 @@
jest.mock('shared/supabase/init');
jest.mock('common/util/try-catch');
jest.mock('shared/supabase/utils');
jest.mock('common/discord/core');
import { report } from "api/report";
import * as supabaseInit from "shared/supabase/init";
import { tryCatch } from "common/util/try-catch";
import * as supabaseUtils from "shared/supabase/utils";
import { sendDiscordMessage } from "common/discord/core";
import { AuthedUser } from "api/helpers/endpoint";
describe('report', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should successfully file a report', async () => {
const mockBody = {
contentOwnerId: "mockContentOwnerId",
contentType: "user" as "user" | "comment" | "contract",
contentId: "mockContentId",
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReporter = {
created_time: "mockCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
};
const mockReported = {
created_time: "mockCreatedTimeReported",
data: {"mockDataReported" : "mockDataValueReported"},
id: "mockIdReported",
name: "mockNameReported",
name_username_vector: "mockNameUsernameVectorReported",
username: "mockUsernameReported",
};
(supabaseUtils.insert as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockBody, error: null});
const result = await report(mockBody, mockAuth, mockReq);
expect(result.success).toBeTruthy();
expect(result.result).toStrictEqual({});
(mockPg.oneOrNone as jest.Mock)
.mockReturnValueOnce(null)
.mockReturnValueOnce(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: mockReporter, error: null})
.mockResolvedValueOnce({data: mockReported, error: null});
(sendDiscordMessage as jest.Mock).mockResolvedValue(null);
await result.continue();
expect(mockPg.oneOrNone).toBeCalledTimes(2);
expect(mockPg.oneOrNone).toHaveBeenNthCalledWith(
1,
expect.stringContaining('select * from users where id = $1'),
[mockAuth.uid]
);
expect(mockPg.oneOrNone).toHaveBeenNthCalledWith(
2,
expect.stringContaining('select * from users where id = $1'),
[mockBody.contentOwnerId]
);
expect(sendDiscordMessage).toBeCalledTimes(1);
expect(sendDiscordMessage).toBeCalledWith(
expect.stringContaining('**New Report**'),
'reports'
);
});
});
describe('when an error occurs', () => {
it('should throw if failed to create the report', async () => {
const mockBody = {
contentOwnerId: "mockContentOwnerId",
contentType: "user" as "user" | "comment" | "contract",
contentId: "mockContentId",
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(supabaseUtils.insert as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: null, error: Error});
expect(report(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Failed to create report: ');
});
it('should throw if unable to get information about the user', async () => {
const mockBody = {
contentOwnerId: "mockContentOwnerId",
contentType: "user" as "user" | "comment" | "contract",
contentId: "mockContentId",
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(supabaseUtils.insert as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockBody, error: null});
const result = await report(mockBody, mockAuth, mockReq);
(mockPg.oneOrNone as jest.Mock)
.mockReturnValueOnce(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: null, error: Error});
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
await result.continue();
expect(errorSpy).toBeCalledWith(
expect.stringContaining('Failed to get user for report'),
expect.objectContaining({name: 'Error'})
);
});
it('should throw if unable to get information about the user being reported', async () => {
const mockBody = {
contentOwnerId: "mockContentOwnerId",
contentType: "user" as "user" | "comment" | "contract",
contentId: "mockContentId",
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReporter = {
created_time: "mockCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
};
(supabaseUtils.insert as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockBody, error: null});
const result = await report(mockBody, mockAuth, mockReq);
(mockPg.oneOrNone as jest.Mock)
.mockReturnValueOnce(null)
.mockReturnValueOnce(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: mockReporter, error: null})
.mockResolvedValueOnce({data: null, error: Error});
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
await result.continue();
expect(errorSpy).toBeCalledWith(
expect.stringContaining('Failed to get reported user for report'),
expect.objectContaining({name: 'Error'})
);
});
it('should throw if failed to send discord report', async () => {
const mockBody = {
contentOwnerId: "mockContentOwnerId",
contentType: "user" as "user" | "comment" | "contract",
contentId: "mockContentId",
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReporter = {
created_time: "mockCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
};
const mockReported = {
created_time: "mockCreatedTimeReported",
data: {"mockDataReported" : "mockDataValueReported"},
id: "mockIdReported",
name: "mockNameReported",
name_username_vector: "mockNameUsernameVectorReported",
username: "mockUsernameReported",
};
(supabaseUtils.insert as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockBody, error: null});
const result = await report(mockBody, mockAuth, mockReq);
(mockPg.oneOrNone as jest.Mock)
.mockReturnValueOnce(null)
.mockReturnValueOnce(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: mockReporter, error: null})
.mockResolvedValueOnce({data: mockReported, error: null});
(sendDiscordMessage as jest.Mock).mockRejectedValue(new Error('Discord error'));
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
await result.continue();
expect(errorSpy).toBeCalledWith(
expect.stringContaining('Failed to send discord reports'),
expect.any(Error)
);
});
});
});

View File

@@ -0,0 +1,70 @@
jest.mock('shared/supabase/init');
import { AuthedUser } from "api/helpers/endpoint";
import { saveSubscriptionMobile } from "api/save-subscription-mobile";
import * as supabaseInit from "shared/supabase/init";
describe('saveSubscriptionMobile', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success after saving the subscription', async () => {
const mockBody = { token: "mockToken" };
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
const result = await saveSubscriptionMobile(mockBody, mockAuth, mockReq);
expect(result.success).toBeTruthy();
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('insert into push_subscriptions_mobile(token, platform, user_id)'),
[mockBody.token, 'android', mockAuth.uid]
);
});
});
describe('when an error occurs', () => {
it('should throw if token is invalid', async () => {
const mockBody = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
expect(saveSubscriptionMobile(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Invalid subscription object');
});
it('should throw if unable to save subscription', async () => {
const mockBody = { token: "mockToken" };
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockRejectedValue(new Error('Saving error'));
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
expect(saveSubscriptionMobile(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Failed to save subscription');
// expect(errorSpy).toBeCalledTimes(1);
// expect(errorSpy).toBeCalledWith(
// expect.stringContaining('Error saving subscription'),
// expect.any(Error)
// );
});
});
});

View File

@@ -0,0 +1,118 @@
jest.mock('shared/supabase/init');
import { AuthedUser } from "api/helpers/endpoint";
import { saveSubscription } from "api/save-subscription";
import * as supabaseInit from "shared/supabase/init";
describe('saveSubscription', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should save user subscription', async () => {
const mockBody = {
subscription: {
endpoint: "mockEndpoint",
keys: "mockKeys",
}
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExists = { id: "mockId" };
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockExists);
(mockPg.none as jest.Mock).mockResolvedValue(null);
const result = await saveSubscription(mockBody, mockAuth, mockReq);
expect(result.success).toBeTruthy();
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select id from push_subscriptions where endpoint = $1'),
[mockBody.subscription.endpoint]
);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('update push_subscriptions set keys = $1, user_id = $2 where id = $3'),
[mockBody.subscription.keys, mockAuth.uid, mockExists.id]
);
});
it('should save user subscription even if this is their first one', async () => {
const mockBody = {
subscription: {
endpoint: "mockEndpoint",
keys: "mockKeys",
}
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
(mockPg.none as jest.Mock).mockResolvedValue(null);
const result = await saveSubscription(mockBody, mockAuth, mockReq);
expect(result.success).toBeTruthy();
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select id from push_subscriptions where endpoint = $1'),
[mockBody.subscription.endpoint]
);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('insert into push_subscriptions(endpoint, keys, user_id) values($1, $2, $3)'),
[mockBody.subscription.endpoint, mockBody.subscription.keys, mockAuth.uid]
);
});
});
describe('when an error occurs', () => {
it('should throw if the subscription object is invalid', async () => {
const mockBody = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
expect(saveSubscription(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Invalid subscription object');
});
it('should throw if unable to save subscription', async () => {
const mockBody = {
subscription: {
endpoint: "mockEndpoint",
keys: "mockKeys",
}
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExists = { id: "mockId" };
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockExists);
(mockPg.none as jest.Mock).mockRejectedValue(new Error('Saving error'));
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
expect(saveSubscription(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Failed to save subscription');
// expect(errorSpy).toBeCalledTimes(1);
// expect(errorSpy).toBeCalledWith(
// expect.stringContaining('Error saving subscription'),
// expect.any(Error)
// );
});
});
});

View File

@@ -0,0 +1,36 @@
jest.mock('common/geodb');
import { AuthedUser } from "api/helpers/endpoint";
import { searchLocation } from "api/search-location";
import * as geodbModules from "common/geodb";
describe('searchLocation', () => {
beforeEach(() => {
jest.resetAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return search location', async () => {
const mockBody = {
term: "mockTerm",
limit: 15
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReturn = "Pass";
(geodbModules.geodbFetch as jest.Mock).mockResolvedValue(mockReturn);
const result = await searchLocation(mockBody, mockAuth, mockReq);
expect(result).toBe(mockReturn);
expect(geodbModules.geodbFetch).toBeCalledTimes(1);
expect(geodbModules.geodbFetch).toBeCalledWith(
expect.stringContaining(`/cities?namePrefix=${mockBody.term}&limit=${mockBody.limit}&offset=0&sort=-population`)
);
});
});
});

View File

@@ -0,0 +1,72 @@
jest.mock('common/geodb');
import * as citySearchModules from "api/search-near-city";
import * as geoDbModules from "common/geodb";
import { AuthedUser } from "api/helpers/endpoint";
describe('searchNearCity', () => {
beforeEach(() => {
jest.resetAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return locations near a city', async () => {
const mockBody = {
radius: 123,
cityId: "mockCityId"
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockReturn = "Pass";
(geoDbModules.geodbFetch as jest.Mock).mockResolvedValue(mockReturn);
const result = await citySearchModules.searchNearCity(mockBody, mockAuth, mockReq);
expect(result).toBe(mockReturn);
expect(geoDbModules.geodbFetch).toBeCalledTimes(1);
expect(geoDbModules.geodbFetch).toBeCalledWith(
expect.stringContaining(`/cities/${mockBody.cityId}/nearbyCities?radius=${mockBody.radius}&offset=0&sort=-population&limit=100`)
);
});
});
});
describe('getNearCity', () => {
beforeEach(() => {
jest.resetAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return locations near a city', async () => {
const mockBody = {
radius: 123,
cityId: "mockCityId"
};
const mockReturn = {
status: "mockStatus",
data: {
data: [
{ id: "mockId" }
]
}
};
(geoDbModules.geodbFetch as jest.Mock).mockResolvedValue(mockReturn);
const result = await citySearchModules.getNearbyCities(mockBody.cityId, mockBody.radius);
expect(result).toStrictEqual([mockReturn.data.data[0].id]);
expect(geoDbModules.geodbFetch).toBeCalledTimes(1);
expect(geoDbModules.geodbFetch).toBeCalledWith(
expect.stringContaining(`/cities/${mockBody.cityId}/nearbyCities?radius=${mockBody.radius}&offset=0&sort=-population&limit=100`)
);
});
});
});

View File

@@ -0,0 +1,154 @@
jest.mock('shared/supabase/init');
jest.mock('shared/helpers/search');
jest.mock('shared/supabase/sql-builder');
jest.mock('common/supabase/users');
jest.mock('common/api/user-types');
import { searchUsers } from "api/search-users";
import * as supabaseInit from "shared/supabase/init";
import * as searchHelpers from "shared/helpers/search";
import * as sqlBuilderModules from "shared/supabase/sql-builder";
import * as supabaseUsers from "common/supabase/users";
import { toUserAPIResponse } from "common/api/user-types";
import { AuthedUser } from "api/helpers/endpoint";
describe('searchUsers', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
map: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks()
});
describe('when given valid input', () => {
it('should return an array of uniq users', async () => {
const mockProps = {
term: "mockTerm",
limit: 10,
page: 1
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockSearchAllSql = "mockSQL";
const mockAllUser = [
{id: "mockId 1"},
{id: "mockId 2"},
{id: "mockId 3"},
];
(sqlBuilderModules.renderSql as jest.Mock).mockReturnValue(mockSearchAllSql);
(sqlBuilderModules.select as jest.Mock).mockReturnValue('Select');
(sqlBuilderModules.from as jest.Mock).mockReturnValue('From');
(sqlBuilderModules.where as jest.Mock).mockReturnValue('Where');
(searchHelpers.constructPrefixTsQuery as jest.Mock).mockReturnValue('ConstructPrefix');
(sqlBuilderModules.orderBy as jest.Mock).mockReturnValue('OrderBy');
(sqlBuilderModules.limit as jest.Mock).mockReturnValue('Limit');
(supabaseUsers.convertUser as jest.Mock).mockResolvedValue(null);
(mockPg.map as jest.Mock).mockResolvedValue(mockAllUser);
(toUserAPIResponse as jest.Mock)
.mockReturnValueOnce(mockAllUser[0].id)
.mockReturnValueOnce(mockAllUser[1].id)
.mockReturnValueOnce(mockAllUser[2].id);
const result: any = await searchUsers(mockProps, mockAuth, mockReq);
expect(result[0]).toContain(mockAllUser[0].id);
expect(result[1]).toContain(mockAllUser[1].id);
expect(result[2]).toContain(mockAllUser[2].id);
expect(sqlBuilderModules.renderSql).toBeCalledTimes(1);
expect(sqlBuilderModules.renderSql).toBeCalledWith(
['Select', 'From'],
['Where', 'OrderBy'],
'Limit'
);
expect(sqlBuilderModules.select).toBeCalledTimes(1);
expect(sqlBuilderModules.select).toBeCalledWith('*');
expect(sqlBuilderModules.from).toBeCalledTimes(1);
expect(sqlBuilderModules.from).toBeCalledWith('users');
expect(sqlBuilderModules.where).toBeCalledTimes(1);
expect(sqlBuilderModules.where).toBeCalledWith(
expect.stringContaining("name_username_vector @@ websearch_to_tsquery('english', $1)"),
[mockProps.term, 'ConstructPrefix']
);
expect(sqlBuilderModules.orderBy).toBeCalledTimes(1);
expect(sqlBuilderModules.orderBy).toBeCalledWith(
expect.stringContaining("ts_rank(name_username_vector, websearch_to_tsquery($1)) desc,"),
[mockProps.term]
);
expect(sqlBuilderModules.limit).toBeCalledTimes(1);
expect(sqlBuilderModules.limit).toBeCalledWith(mockProps.limit, mockProps.page * mockProps.limit);
expect(mockPg.map).toBeCalledTimes(1);
expect(mockPg.map).toBeCalledWith(
mockSearchAllSql,
null,
expect.any(Function)
);
});
it('should return an array of uniq users if no term is supplied', async () => {
const mockProps = {
limit: 10,
page: 1
} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockSearchAllSql = "mockSQL";
const mockAllUser = [
{id: "mockId 1"},
{id: "mockId 2"},
{id: "mockId 3"},
];
(sqlBuilderModules.renderSql as jest.Mock).mockReturnValue(mockSearchAllSql);
(sqlBuilderModules.select as jest.Mock).mockReturnValue('Select');
(sqlBuilderModules.from as jest.Mock).mockReturnValue('From');
(sqlBuilderModules.orderBy as jest.Mock).mockReturnValue('OrderBy');
(sqlBuilderModules.limit as jest.Mock).mockReturnValue('Limit');
(supabaseUsers.convertUser as jest.Mock).mockResolvedValue(null);
(mockPg.map as jest.Mock).mockResolvedValue(mockAllUser);
(toUserAPIResponse as jest.Mock)
.mockReturnValueOnce(mockAllUser[0].id)
.mockReturnValueOnce(mockAllUser[1].id)
.mockReturnValueOnce(mockAllUser[2].id);
const result: any = await searchUsers(mockProps, mockAuth, mockReq);
expect(result[0]).toContain(mockAllUser[0].id);
expect(result[1]).toContain(mockAllUser[1].id);
expect(result[2]).toContain(mockAllUser[2].id);
expect(sqlBuilderModules.renderSql).toBeCalledTimes(1);
expect(sqlBuilderModules.renderSql).toBeCalledWith(
['Select', 'From'],
'OrderBy',
'Limit'
);
expect(sqlBuilderModules.select).toBeCalledTimes(1);
expect(sqlBuilderModules.select).toBeCalledWith('*');
expect(sqlBuilderModules.from).toBeCalledTimes(1);
expect(sqlBuilderModules.from).toBeCalledWith('users');
expect(sqlBuilderModules.orderBy).toBeCalledTimes(1);
expect(sqlBuilderModules.orderBy).toBeCalledWith(
expect.stringMatching(`data->'creatorTraders'->'allTime' desc nulls last`)
);
expect(sqlBuilderModules.limit).toBeCalledTimes(1);
expect(sqlBuilderModules.limit).toBeCalledWith(mockProps.limit, mockProps.page * mockProps.limit);
expect(mockPg.map).toBeCalledTimes(1);
expect(mockPg.map).toBeCalledWith(
mockSearchAllSql,
null,
expect.any(Function)
);
});
});
});

View File

@@ -0,0 +1,314 @@
jest.mock('shared/supabase/init');
jest.mock('shared/supabase/sql-builder');
jest.mock('api/get-profiles');
jest.mock('email/functions/helpers');
jest.mock('lodash');
import * as searchNotificationModules from "api/send-search-notifications";
import * as supabaseInit from "shared/supabase/init";
import * as sqlBuilderModules from "shared/supabase/sql-builder";
import * as profileModules from "api/get-profiles";
import * as helperModules from "email/functions/helpers";
import * as lodashModules from "lodash";
describe('sendSearchNotification', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
map: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should send search notification emails', async () => {
const mockSearchQuery = "mockSqlQuery";
const mockSearches = [
{
created_time: "mockSearchCreatedTime",
creator_id: "mockCreatorId",
id: 123,
last_notified_at: null,
location: {"mockLocation" : "mockLocationValue"},
search_filters: null,
search_name: null,
},
{
created_time: "mockCreatedTime1",
creator_id: "mockCreatorId1",
id: 1234,
last_notified_at: null,
location: {"mockLocation1" : "mockLocationValue1"},
search_filters: null,
search_name: null,
},
];
const _mockUsers = [
{
created_time: "mockUserCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
},
{
created_time: "mockUserCreatedTime1",
data: {"mockData1" : "mockDataValue1"},
id: "mockId1",
name: "mockName1",
name_username_vector: "mockNameUsernameVector1",
username: "mockUsername1",
},
];
const mockUsers = {
"user1": {
created_time: "mockUserCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
},
"user2": {
created_time: "mockUserCreatedTime1",
data: {"mockData1" : "mockDataValue1"},
id: "mockId1",
name: "mockName1",
name_username_vector: "mockNameUsernameVector1",
username: "mockUsername1",
},
};
const _mockPrivateUsers = [
{
data: {"mockData" : "mockDataValue"},
id: "mockId"
},
{
data: {"mockData1" : "mockDataValue1"},
id: "mockId1"
},
];
const mockPrivateUsers = {
"privateUser1": {
data: {"mockData" : "mockDataValue"},
id: "mockId"
},
"privateUser2": {
data: {"mockData1" : "mockDataValue1"},
id: "mockId1"
},
};
const mockProfiles = [
{
name: "mockProfileName",
username: "mockProfileUsername"
},
{
name: "mockProfileName1",
username: "mockProfileUsername1"
},
];
const mockProps = [
{
skipId: "mockCreatorId",
lastModificationWithin: '24 hours',
shortBio: true,
},
{
skipId: "mockCreatorId1",
lastModificationWithin: '24 hours',
shortBio: true,
},
];
(sqlBuilderModules.renderSql as jest.Mock)
.mockReturnValueOnce(mockSearchQuery)
.mockReturnValueOnce('usersRenderSql')
.mockReturnValueOnce('privateUsersRenderSql');
(sqlBuilderModules.select as jest.Mock).mockReturnValue('Select');
(sqlBuilderModules.from as jest.Mock).mockReturnValue('From');
(mockPg.map as jest.Mock)
.mockResolvedValueOnce(mockSearches)
.mockResolvedValueOnce(_mockUsers)
.mockResolvedValueOnce(_mockPrivateUsers);
(lodashModules.keyBy as jest.Mock)
.mockReturnValueOnce(mockUsers)
.mockReturnValueOnce(mockPrivateUsers);
(profileModules.loadProfiles as jest.Mock)
.mockResolvedValueOnce({profiles: mockProfiles})
.mockResolvedValueOnce({profiles: mockProfiles});
jest.spyOn(searchNotificationModules, 'notifyBookmarkedSearch');
(helperModules.sendSearchAlertsEmail as jest.Mock).mockResolvedValue(null);
const result = await searchNotificationModules.sendSearchNotifications();
expect(result.status).toBe('success');
expect(sqlBuilderModules.renderSql).toBeCalledTimes(3);
expect(sqlBuilderModules.renderSql).toHaveBeenNthCalledWith(
1,
'Select',
'From'
);
expect(sqlBuilderModules.renderSql).toHaveBeenNthCalledWith(
2,
'Select',
'From'
);
expect(sqlBuilderModules.renderSql).toHaveBeenNthCalledWith(
3,
'Select',
'From'
);
expect(mockPg.map).toBeCalledTimes(3);
expect(mockPg.map).toHaveBeenNthCalledWith(
1,
mockSearchQuery,
[],
expect.any(Function)
);
expect(mockPg.map).toHaveBeenNthCalledWith(
2,
'usersRenderSql',
[],
expect.any(Function)
);
expect(mockPg.map).toHaveBeenNthCalledWith(
3,
'privateUsersRenderSql',
[],
expect.any(Function)
);
expect(profileModules.loadProfiles).toBeCalledTimes(2);
expect(profileModules.loadProfiles).toHaveBeenNthCalledWith(
1,
mockProps[0]
);
expect(profileModules.loadProfiles).toHaveBeenNthCalledWith(
2,
mockProps[1]
);
expect(searchNotificationModules.notifyBookmarkedSearch).toBeCalledTimes(1);
expect(searchNotificationModules.notifyBookmarkedSearch).toBeCalledWith({});
});
it('should send search notification emails when there is a matching creator_id entry in private users', async () => {
const mockSearchQuery = "mockSqlQuery";
const mockSearches = [
{
created_time: "mockSearchCreatedTime",
creator_id: "mockCreatorId",
id: 123,
last_notified_at: null,
location: {"mockLocation" : "mockLocationValue"},
search_filters: null,
search_name: null,
},
{
created_time: "mockCreatedTime1",
creator_id: "mockCreatorId1",
id: 1234,
last_notified_at: null,
location: {"mockLocation1" : "mockLocationValue1"},
search_filters: null,
search_name: null,
},
];
const _mockUsers = [
{
created_time: "mockUserCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
},
{
created_time: "mockUserCreatedTime1",
data: {"mockData1" : "mockDataValue1"},
id: "mockId1",
name: "mockName1",
name_username_vector: "mockNameUsernameVector1",
username: "mockUsername1",
},
];
const mockUsers = {
"user1": {
created_time: "mockUserCreatedTime",
data: {"mockData" : "mockDataValue"},
id: "mockId",
name: "mockName",
name_username_vector: "mockNameUsernameVector",
username: "mockUsername",
},
"user2": {
created_time: "mockUserCreatedTime1",
data: {"mockData1" : "mockDataValue1"},
id: "mockId1",
name: "mockName1",
name_username_vector: "mockNameUsernameVector1",
username: "mockUsername1",
},
};
const _mockPrivateUsers = [
{
data: {"mockData" : "mockDataValue"},
id: "mockId"
},
{
data: {"mockData1" : "mockDataValue1"},
id: "mockId1"
},
];
const mockPrivateUsers = {
"mockCreatorId": {
data: {"mockData" : "mockDataValue"},
id: "mockId"
},
"mockCreatorId1": {
data: {"mockData1" : "mockDataValue1"},
id: "mockId1"
},
};
const mockProfiles = [
{
name: "mockProfileName",
username: "mockProfileUsername"
},
{
name: "mockProfileName1",
username: "mockProfileUsername1"
},
];
(sqlBuilderModules.renderSql as jest.Mock)
.mockReturnValueOnce(mockSearchQuery)
.mockReturnValueOnce('usersRenderSql')
.mockReturnValueOnce('privateUsersRenderSql');
(sqlBuilderModules.select as jest.Mock).mockReturnValue('Select');
(sqlBuilderModules.from as jest.Mock).mockReturnValue('From');
(mockPg.map as jest.Mock)
.mockResolvedValueOnce(mockSearches)
.mockResolvedValueOnce(_mockUsers)
.mockResolvedValueOnce(_mockPrivateUsers);
(lodashModules.keyBy as jest.Mock)
.mockReturnValueOnce(mockUsers)
.mockReturnValueOnce(mockPrivateUsers);
(profileModules.loadProfiles as jest.Mock)
.mockResolvedValueOnce({profiles: mockProfiles})
.mockResolvedValueOnce({profiles: mockProfiles});
jest.spyOn(searchNotificationModules, 'notifyBookmarkedSearch');
(helperModules.sendSearchAlertsEmail as jest.Mock).mockResolvedValue(null);
await searchNotificationModules.sendSearchNotifications();
expect(searchNotificationModules.notifyBookmarkedSearch).toBeCalledTimes(1);
expect(searchNotificationModules.notifyBookmarkedSearch).not.toBeCalledWith({});
});
});
});

View File

@@ -0,0 +1,74 @@
jest.mock('shared/supabase/init');
jest.mock('shared/compatibility/compute-scores');
import { setCompatibilityAnswer } from "api/set-compatibility-answer";
import * as supabaseInit from "shared/supabase/init";
import { recomputeCompatibilityScoresForUser } from "shared/compatibility/compute-scores";
import { AuthedUser } from "api/helpers/endpoint";
describe('setCompatibilityAnswer', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
one: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should set compatibility answers', async () => {
const mockProps = {
questionId: 1,
multipleChoice: 2,
prefChoices: [1,2,3,4,5],
importance: 1,
explanation: "mockExplanation"
};
const mockResult = {
created_time: "mockCreatedTime",
creator_id: "mockCreatorId",
explanation: "mockExplanation",
id: 123,
importance: 1,
multipleChoice: 2,
prefChoices: [1,2,3,4,5],
questionId: 1,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.one as jest.Mock).mockResolvedValue(mockResult);
(recomputeCompatibilityScoresForUser as jest.Mock).mockResolvedValue(null);
const result: any = await setCompatibilityAnswer(mockProps, mockAuth, mockReq);
expect(result.result).toBe(mockResult);
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
{
text: expect.stringContaining('INSERT INTO compatibility_answers'),
values: [
mockAuth.uid,
mockProps.questionId,
mockProps.multipleChoice,
mockProps.prefChoices,
mockProps.importance,
mockProps.explanation,
]
}
);
await result.continue();
expect(recomputeCompatibilityScoresForUser).toBeCalledTimes(1);
expect(recomputeCompatibilityScoresForUser).toBeCalledWith(mockAuth.uid, expect.any(Object));
});
});
});

View File

@@ -1,34 +1,56 @@
jest.mock('shared/supabase/init');
import { AuthedUser } from "api/helpers/endpoint";
import * as setLastTimeOnlineModule from "api/set-last-online-time";
import * as supabaseInit from "shared/supabase/init";
describe('Should', () => {
describe('setLastOnlineTimeUser', () => {
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
none: jest.fn(),
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
jest.clearAllMocks();
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
it('change the users last online time', async () => {
const mockProfile = {user_id: 'Jonathon'};
await setLastTimeOnlineModule.setLastOnlineTimeUser(mockProfile.user_id);
describe('when given valid input', () => {
it('should change the users last online time', async () => {
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockProps = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
jest.spyOn(setLastTimeOnlineModule, 'setLastOnlineTimeUser');
expect(mockPg.none).toBeCalledTimes(1);
await setLastTimeOnlineModule.setLastOnlineTime(mockProps, mockAuth, mockReq);
const [query, userId] = mockPg.none.mock.calls[0];
expect(setLastTimeOnlineModule.setLastOnlineTimeUser).toBeCalledTimes(1);
expect(setLastTimeOnlineModule.setLastOnlineTimeUser).toBeCalledWith(mockAuth.uid);
expect(mockPg.none).toBeCalledTimes(1);
expect(userId).toContain(mockAuth.uid);
expect(query).toContain("VALUES ($1, now())");
expect(query).toContain("ON CONFLICT (user_id)");
expect(query).toContain("DO UPDATE");
expect(query).toContain("user_activity.last_online_time < now() - interval '1 minute'");
});
const [query, userId] = mockPg.none.mock.calls[0];
expect(userId).toContain(mockProfile.user_id);
expect(query).toContain("VALUES ($1, now())")
expect(query).toContain("ON CONFLICT (user_id)")
expect(query).toContain("DO UPDATE")
expect(query).toContain("user_activity.last_online_time < now() - interval '1 minute'")
it('should return if there is no auth', async () => {
const mockAuth = { } as any;
const mockReq = {} as any;
const mockProps = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
jest.spyOn(setLastTimeOnlineModule, 'setLastOnlineTimeUser');
await setLastTimeOnlineModule.setLastOnlineTime(mockProps, mockAuth, mockReq);
expect(setLastTimeOnlineModule.setLastOnlineTimeUser).not.toBeCalled();
});
});
})
});

View File

@@ -0,0 +1,227 @@
jest.mock('shared/supabase/init');
jest.mock('common/util/try-catch');
jest.mock('shared/supabase/utils');
jest.mock('shared/create-profile-notification');
import { shipProfiles } from "api/ship-profiles";
import * as supabaseInit from "shared/supabase/init";
import { tryCatch } from "common/util/try-catch";
import * as supabaseUtils from "shared/supabase/utils";
import * as profileNotificationModules from "shared/create-profile-notification";
import { AuthedUser } from "api/helpers/endpoint";
describe('shipProfiles', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success if the profile ship already exists', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: false,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: { ship_id : "mockShipId" },
error: null
};
(tryCatch as jest.Mock).mockResolvedValue(mockExisting);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
const result: any = await shipProfiles(mockProps, mockAuth, mockReq);
expect(result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select ship_id from profile_ships'),
[mockAuth.uid, mockProps.targetUserId1, mockProps.targetUserId2]
);
});
it('should return success if trying to remove a profile ship that already exists', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: true,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: { ship_id : "mockShipId" },
error: null
};
(tryCatch as jest.Mock)
.mockResolvedValueOnce(mockExisting)
.mockResolvedValueOnce({error: null});
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(mockPg.none as jest.Mock).mockResolvedValue(null);
const result: any = await shipProfiles(mockProps, mockAuth, mockReq);
expect(result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(2);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select ship_id from profile_ships'),
[mockAuth.uid, mockProps.targetUserId1, mockProps.targetUserId2]
);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('delete from profile_ships where ship_id = $1'),
[mockExisting.data.ship_id]
);
});
it('should return success when creating a new profile ship', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: false,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: null,
error: null
};
const mockData = {
created_time: "mockCreatedTime",
creator_id: "mockCreatorId",
ship_id: "mockShipId",
target1_id: "mockTarget1Id",
target2_id: "mockTarget2Id",
};
(tryCatch as jest.Mock)
.mockResolvedValueOnce(mockExisting)
.mockResolvedValueOnce({data: mockData, error: null});
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
const result: any = await shipProfiles(mockProps, mockAuth, mockReq);
expect(result.result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(2);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select ship_id from profile_ships'),
[mockAuth.uid, mockProps.targetUserId1, mockProps.targetUserId2]
);
expect(supabaseUtils.insert).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledWith(
expect.any(Object),
'profile_ships',
{
creator_id: mockAuth.uid,
target1_id: mockProps.targetUserId1,
target2_id: mockProps.targetUserId2,
}
);
(profileNotificationModules.createProfileShipNotification as jest.Mock).mockReturnValue(null);
await result.continue();
expect(profileNotificationModules.createProfileShipNotification).toBeCalledTimes(2);
expect(profileNotificationModules.createProfileShipNotification).toHaveBeenNthCalledWith(
1,
mockData,
mockData.target1_id
);
expect(profileNotificationModules.createProfileShipNotification).toHaveBeenNthCalledWith(
2,
mockData,
mockData.target2_id
);
});
});
describe('when an error occurs', () => {
it('should throw if unable to check ship', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: false,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: null,
error: Error
};
(tryCatch as jest.Mock).mockResolvedValue(mockExisting);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
expect(shipProfiles(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Error when checking ship: ');
});
it('should throw if unable to remove a profile ship that already exists', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: true,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: { ship_id : "mockShipId" },
error: null
};
(tryCatch as jest.Mock)
.mockResolvedValueOnce(mockExisting)
.mockResolvedValueOnce({error: Error});
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(mockPg.none as jest.Mock).mockResolvedValue(null);
expect(shipProfiles(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Failed to remove ship: ');
});
it('should return success when creating a new profile ship', async () => {
const mockProps = {
targetUserId1: "mockTargetUserId1",
targetUserId2: "mockTargetUserId2",
remove: false,
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
data: null,
error: null
};
(tryCatch as jest.Mock)
.mockResolvedValueOnce(mockExisting)
.mockResolvedValueOnce({data: null, error: Error});
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
expect(shipProfiles(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Failed to create ship: ');
});
});
});

View File

@@ -0,0 +1,146 @@
jest.mock('common/util/try-catch');
jest.mock('shared/supabase/init');
jest.mock('shared/supabase/utils');
import { AuthedUser } from "api/helpers/endpoint";
import { starProfile } from "api/star-profile";
import { tryCatch } from "common/util/try-catch";
import * as supabaseInit from "shared/supabase/init";
import * as supabaseUtils from "shared/supabase/utils";
describe('startProfile', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
none: jest.fn(),
oneOrNone: jest.fn(),
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success when trying to star a profile for the first time', async () => {
const mockProps = {
targetUserId: "mockTargetUserId",
remove: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: null})
.mockResolvedValueOnce({error: null});
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
const result: any = await starProfile(mockProps, mockAuth, mockReq);
expect(result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(2);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select * from profile_stars where creator_id = $1 and target_id = $2'),
[mockAuth.uid, mockProps.targetUserId]
);
expect(supabaseUtils.insert).toBeCalledTimes(1);
expect(supabaseUtils.insert).toBeCalledWith(
expect.any(Object),
'profile_stars',
{
creator_id: mockAuth.uid,
target_id: mockProps.targetUserId
}
);
});
it('should return success if the profile already has a star', async () => {
const mockProps = {
targetUserId: "mockTargetUserId",
remove: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockExisting = {
created_time: "mockCreatedTime",
creator_id: "mockCreatorId",
star_id: "mockStarId",
target_id: "mockTarget",
};
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({data: mockExisting});
const result: any = await starProfile(mockProps, mockAuth, mockReq);
expect(result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(supabaseUtils.insert).not.toBeCalledTimes(1);
});
it('should return success when trying to remove a star', async () => {
const mockProps = {
targetUserId: "mockTargetUserId",
remove: true
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValue({error: null});
const result: any = await starProfile(mockProps, mockAuth, mockReq);
expect(result.status).toBe('success');
expect(tryCatch).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('delete from profile_stars where creator_id = $1 and target_id = $2'),
[mockAuth.uid, mockProps.targetUserId]
);
});
});
describe('when an error occurs', () => {
it('should throw if unable to remove star', async () => {
const mockProps = {
targetUserId: "mockTargetUserId",
remove: true
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock).mockResolvedValueOnce({error: Error});
expect(starProfile(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Failed to remove star');
});
it('should throw if unable to add a star', async () => {
const mockProps = {
targetUserId: "mockTargetUserId",
remove: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(null);
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: null})
.mockResolvedValueOnce({error: Error});
(supabaseUtils.insert as jest.Mock).mockReturnValue(null);
expect(starProfile(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Failed to add star');
});
});
});

View File

@@ -0,0 +1,255 @@
jest.mock('common/api/user-types');
jest.mock('common/util/clean-username');
jest.mock('shared/supabase/init');
jest.mock('common/util/object');
jest.mock('lodash');
jest.mock('shared/utils');
jest.mock('shared/supabase/users');
jest.mock('shared/websockets/helpers');
jest.mock('common/envs/constants');
import { updateMe } from "api/update-me";
import { toUserAPIResponse } from "common/api/user-types";
import * as cleanUsernameModules from "common/util/clean-username";
import * as supabaseInit from "shared/supabase/init";
import * as objectUtils from "common/util/object";
import * as lodashModules from "lodash";
import * as sharedUtils from "shared/utils";
import * as supabaseUsers from "shared/supabase/users";
import * as websocketHelperModules from "shared/websockets/helpers";
import { AuthedUser } from "api/helpers/endpoint";
describe('updateMe', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should update user information', async () => {
const mockProps = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUpdate = {
name: "mockName",
username: "mockUsername",
avatarUrl: "mockAvatarUrl",
bio: "mockBio",
link: {"mockLink" : "mockLinkValue"},
optOutBetWarnings:true,
website: "mockWebsite",
twitterHandle: "mockTwitterHandle",
discordHandle: "mockDiscordHandle",
};
const mockStripped = {
bio: "mockBio"
};
const mockData = {link: "mockNewLinks"};
const arrySpy = jest.spyOn(Array.prototype, 'includes');
(lodashModules.cloneDeep as jest.Mock).mockReturnValue(mockUpdate);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(cleanUsernameModules.cleanDisplayName as jest.Mock).mockReturnValue(mockUpdate.name);
(cleanUsernameModules.cleanUsername as jest.Mock).mockReturnValue(mockUpdate.username);
arrySpy.mockReturnValue(false);
(sharedUtils.getUserByUsername as jest.Mock).mockReturnValue(false);
(supabaseUsers.updateUser as jest.Mock)
.mockResolvedValueOnce(null)
.mockResolvedValueOnce(null);
(lodashModules.mapValues as jest.Mock).mockReturnValue(mockStripped);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockData);
(mockPg.none as jest.Mock)
.mockResolvedValueOnce(null)
.mockResolvedValueOnce(null);
(objectUtils.removeUndefinedProps as jest.Mock).mockReturnValue("mockRemoveUndefinedProps");
(websocketHelperModules.broadcastUpdatedUser as jest.Mock).mockReturnValue(null);
(toUserAPIResponse as jest.Mock).mockReturnValue(null);
await updateMe(mockProps, mockAuth, mockReq);
expect(lodashModules.cloneDeep).toBeCalledTimes(1);
expect(lodashModules.cloneDeep).toBeCalledWith(mockProps);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(cleanUsernameModules.cleanDisplayName).toBeCalledTimes(1);
expect(cleanUsernameModules.cleanDisplayName).toBeCalledWith(mockUpdate.name);
expect(cleanUsernameModules.cleanUsername).toBeCalledTimes(1);
expect(cleanUsernameModules.cleanUsername).toBeCalledWith(mockUpdate.username);
expect(arrySpy).toBeCalledTimes(1);
expect(arrySpy).toBeCalledWith(mockUpdate.username);
expect(sharedUtils.getUserByUsername).toBeCalledTimes(1);
expect(sharedUtils.getUserByUsername).toBeCalledWith(mockUpdate.username);
expect(supabaseUsers.updateUser).toBeCalledTimes(2);
expect(supabaseUsers.updateUser).toHaveBeenNthCalledWith(
1,
expect.any(Object),
mockAuth.uid,
'mockRemoveUndefinedProps'
);
expect(supabaseUsers.updateUser).toHaveBeenNthCalledWith(
2,
expect.any(Object),
mockAuth.uid,
{avatarUrl: mockUpdate.avatarUrl}
);
expect(lodashModules.mapValues).toBeCalledTimes(1);
expect(lodashModules.mapValues).toBeCalledWith(
expect.any(Object),
expect.any(Function)
);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('update users'),
{
adds: expect.any(Object),
removes: expect.any(Array),
id: mockAuth.uid
}
);
expect(mockPg.none).toBeCalledTimes(2);
expect(mockPg.none).toHaveBeenNthCalledWith(
1,
expect.stringContaining(`update users set name = $1 where id = $2`),
[mockUpdate.name, mockAuth.uid]
);
expect(mockPg.none).toHaveBeenNthCalledWith(
2,
expect.stringContaining(`update users set username = $1 where id = $2`),
[mockUpdate.username, mockAuth.uid]
);
expect(objectUtils.removeUndefinedProps).toBeCalledTimes(2);
expect(objectUtils.removeUndefinedProps).toHaveBeenNthCalledWith(
2,
{
id: mockAuth.uid,
name: mockUpdate.name,
username: mockUpdate.username,
avatarUrl: mockUpdate.avatarUrl,
link: mockData.link
}
);
expect(websocketHelperModules.broadcastUpdatedUser).toBeCalledTimes(1);
expect(websocketHelperModules.broadcastUpdatedUser).toBeCalledWith('mockRemoveUndefinedProps');
expect(toUserAPIResponse).toBeCalledTimes(1);
});
});
describe('when an error occurs', () => {
it('should throw if no account was found', async () => {
const mockProps = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUpdate = {
name: "mockName",
username: "mockUsername",
avatarUrl: "mockAvatarUrl",
bio: "mockBio",
link: {"mockLink" : "mockLinkValue"},
optOutBetWarnings:true,
website: "mockWebsite",
twitterHandle: "mockTwitterHandle",
discordHandle: "mockDiscordHandle",
};
(lodashModules.cloneDeep as jest.Mock).mockReturnValue(mockUpdate);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(updateMe(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Your account was not found');
});
it('should throw if the username is invalid', async () => {
const mockProps = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUpdate = {
name: "mockName",
username: "mockUsername",
avatarUrl: "mockAvatarUrl",
bio: "mockBio",
link: {"mockLink" : "mockLinkValue"},
optOutBetWarnings:true,
website: "mockWebsite",
twitterHandle: "mockTwitterHandle",
discordHandle: "mockDiscordHandle",
};
(lodashModules.cloneDeep as jest.Mock).mockReturnValue(mockUpdate);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(cleanUsernameModules.cleanDisplayName as jest.Mock).mockReturnValue(mockUpdate.name);
(cleanUsernameModules.cleanUsername as jest.Mock).mockReturnValue(false);
expect(updateMe(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Invalid username');
});
it('should throw if the username is reserved', async () => {
const mockProps = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUpdate = {
name: "mockName",
username: "mockUsername",
avatarUrl: "mockAvatarUrl",
bio: "mockBio",
link: {"mockLink" : "mockLinkValue"},
optOutBetWarnings:true,
website: "mockWebsite",
twitterHandle: "mockTwitterHandle",
discordHandle: "mockDiscordHandle",
};
const arrySpy = jest.spyOn(Array.prototype, 'includes');
(lodashModules.cloneDeep as jest.Mock).mockReturnValue(mockUpdate);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(cleanUsernameModules.cleanDisplayName as jest.Mock).mockReturnValue(mockUpdate.name);
(cleanUsernameModules.cleanUsername as jest.Mock).mockReturnValue(mockUpdate.username);
arrySpy.mockReturnValue(true);
expect(updateMe(mockProps, mockAuth, mockReq))
.rejects
.toThrow('This username is reserved');
});
it('should throw if the username is taken', async () => {
const mockProps = {} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUpdate = {
name: "mockName",
username: "mockUsername",
avatarUrl: "mockAvatarUrl",
bio: "mockBio",
link: {"mockLink" : "mockLinkValue"},
optOutBetWarnings:true,
website: "mockWebsite",
twitterHandle: "mockTwitterHandle",
discordHandle: "mockDiscordHandle",
};
const arrySpy = jest.spyOn(Array.prototype, 'includes');
(lodashModules.cloneDeep as jest.Mock).mockReturnValue(mockUpdate);
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(cleanUsernameModules.cleanDisplayName as jest.Mock).mockReturnValue(mockUpdate.name);
(cleanUsernameModules.cleanUsername as jest.Mock).mockReturnValue(mockUpdate.username);
arrySpy.mockReturnValue(false);
(sharedUtils.getUserByUsername as jest.Mock).mockReturnValue(true);
expect(updateMe(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Username already taken');
});
});
});

View File

@@ -0,0 +1,71 @@
jest.mock('shared/supabase/init');
jest.mock('shared/supabase/users');
jest.mock('shared/websockets/helpers');
import { AuthedUser } from "api/helpers/endpoint";
import { updateNotifSettings } from "api/update-notif-setting";
import * as supabaseInit from "shared/supabase/init";
import * as supabaseUsers from "shared/supabase/users";
import * as websocketHelpers from "shared/websockets/helpers";
describe('updateNotifSettings', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should update notification settings', async () => {
const mockProps = {
type: "new_match" as const,
medium: "email" as const,
enabled: false
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(mockPg.none as jest.Mock).mockResolvedValue(null);
(websocketHelpers.broadcastUpdatedPrivateUser as jest.Mock).mockReturnValue(null);
await updateNotifSettings(mockProps, mockAuth, mockReq);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('update private_users'),
[mockProps.type, mockProps.medium, mockAuth.uid]
);
expect(websocketHelpers.broadcastUpdatedPrivateUser).toBeCalledTimes(1);
expect(websocketHelpers.broadcastUpdatedPrivateUser).toBeCalledWith(mockAuth.uid);
});
it('should turn off notifications', async () => {
const mockProps = {
type: "opt_out_all" as const,
medium: "mobile" as const,
enabled: true
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(supabaseUsers.updatePrivateUser as jest.Mock).mockResolvedValue(null);
await updateNotifSettings(mockProps, mockAuth, mockReq);
expect(supabaseUsers.updatePrivateUser).toBeCalledTimes(1);
expect(supabaseUsers.updatePrivateUser).toBeCalledWith(
expect.any(Object),
mockAuth.uid,
{interestedInPushNotifications: !mockProps.enabled}
);
});
});
});

View File

@@ -0,0 +1,170 @@
jest.mock('common/util/try-catch');
jest.mock('shared/supabase/init');
import { AuthedUser } from "api/helpers/endpoint";
import { updateOptions } from "api/update-options";
import { tryCatch } from "common/util/try-catch";
import * as supabaseInit from "shared/supabase/init";
describe('updateOptions', () => {
let mockPg = {} as any;
let mockTx = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockTx = {
one: jest.fn(),
none: jest.fn()
};
mockPg = {
oneOrNone: jest.fn(),
tx: jest.fn(async (cb) => await cb(mockTx))
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should update user', async () => {
const mockProps = {
table: 'causes' as const,
names: ["mockNamesOne", "mockNamesTwo"]
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockProfileIdResult = {id: 123};
const mockRow1 = {
id: 1234,
};
const mockRow2 = {
id: 12345,
};
jest.spyOn(Array.prototype, 'includes').mockReturnValue(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockProfileIdResult);
(tryCatch as jest.Mock).mockImplementation(async (fn: any) => {
try {
const data = await fn;
return {data, error: null};
} catch (error) {
return {data:null, error};
}
});
(mockTx.one as jest.Mock)
.mockResolvedValueOnce(mockRow1)
.mockResolvedValueOnce(mockRow2);
const result: any = await updateOptions(mockProps, mockAuth, mockReq);
expect(result.updatedIds).toStrictEqual([mockRow1.id, mockRow2.id]);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('SELECT id FROM profiles WHERE user_id = $1'),
[mockAuth.uid]
);
expect(tryCatch).toBeCalledTimes(1);
expect(mockTx.one).toBeCalledTimes(2);
expect(mockTx.one).toHaveBeenNthCalledWith(
1,
expect.stringContaining(`INSERT INTO ${mockProps.table} (name, creator_id)`),
[mockProps.names[0], mockAuth.uid]
);
expect(mockTx.one).toHaveBeenNthCalledWith(
2,
expect.stringContaining(`INSERT INTO ${mockProps.table} (name, creator_id)`),
[mockProps.names[1], mockAuth.uid]
);
expect(mockTx.none).toBeCalledTimes(2);
expect(mockTx.none).toHaveBeenNthCalledWith(
1,
expect.stringContaining(`DELETE FROM profile_${mockProps.table} WHERE profile_id = $1`),
[mockProfileIdResult.id]
);
expect(mockTx.none).toHaveBeenNthCalledWith(
2,
expect.stringContaining(`INSERT INTO profile_${mockProps.table} (profile_id, option_id) VALUES`),
[mockProfileIdResult.id, mockRow1.id, mockRow2.id]
);
});
});
describe('when an error occurs', () => {
it('should throw if the table param is invalid', async () => {
const mockProps = {
table: 'causes' as const,
names: ["mockNamesOne", "mockNamesTwo"]
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(Array.prototype, 'includes').mockReturnValue(false);
expect(updateOptions(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Invalid table');
});
it('should throw if the names param is not provided', async () => {
const mockProps = {
table: 'causes' as const,
names: []
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(Array.prototype, 'includes').mockReturnValue(true);
expect(updateOptions(mockProps, mockAuth, mockReq))
.rejects
.toThrow('No names provided');
});
it('should throw if unable to find profile', async () => {
const mockProps = {
table: 'causes' as const,
names: ["mockNamesOne", "mockNamesTwo"]
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
jest.spyOn(Array.prototype, 'includes').mockReturnValue(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(updateOptions(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Profile not found');
});
it('should update user', async () => {
const mockProps = {
table: 'causes' as const,
names: ["mockNamesOne", "mockNamesTwo"]
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockProfileIdResult = {id: 123};
const mockRow1 = {
id: 1234,
};
const mockRow2 = {
id: 12345,
};
jest.spyOn(Array.prototype, 'includes').mockReturnValue(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(mockProfileIdResult);
(tryCatch as jest.Mock).mockResolvedValue({data: null, error: Error});
(mockPg.tx as jest.Mock).mockResolvedValue(null);
(mockTx.one as jest.Mock)
.mockResolvedValueOnce(mockRow1)
.mockResolvedValueOnce(mockRow2);
(mockTx.none as jest.Mock)
.mockResolvedValueOnce(null)
.mockResolvedValueOnce(null);
expect(updateOptions(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Error updating profile options');
});
});
});

View File

@@ -0,0 +1,91 @@
jest.mock('shared/supabase/init');
jest.mock('shared/utils');
jest.mock('common/supabase/utils');
import {updatePrivateUserMessageChannel} from "api/update-private-user-message-channel";
import * as supabaseInit from "shared/supabase/init";
import * as sharedUtils from "shared/utils";
import * as supabaseUtils from "common/supabase/utils";
import { AuthedUser } from "api/helpers/endpoint";
describe('updatePrivateUserMessageChannel', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
none: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should return success after updating the users private message channel', async () => {
const mockBody = {
channelId: 123,
notifyAfterTime: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(true);
(supabaseUtils.millisToTs as jest.Mock).mockReturnValue('mockMillisToTs');
const results = await updatePrivateUserMessageChannel(mockBody, mockAuth, mockReq);
expect(results.status).toBe('success');
expect(results.channelId).toBe(mockBody.channelId);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select status from private_user_message_channel_members'),
[mockBody.channelId, mockAuth.uid]
);
expect(mockPg.none).toBeCalledTimes(1);
expect(mockPg.none).toBeCalledWith(
expect.stringContaining('update private_user_message_channel_members'),
[mockBody.channelId, mockAuth.uid, 'mockMillisToTs']
);
});
});
describe('when an error occurs', () => {
it('should throw if the user account does not exist', async () => {
const mockBody = {
channelId: 123,
notifyAfterTime: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(updatePrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrow('Your account was not found');
});
it('should throw if the user is not authorized in the channel', async () => {
const mockBody = {
channelId: 123,
notifyAfterTime: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(true);
(mockPg.oneOrNone as jest.Mock).mockResolvedValue(false);
expect(updatePrivateUserMessageChannel(mockBody, mockAuth, mockReq))
.rejects
.toThrow('You are not authorized to this channel');
});
});
});

View File

@@ -1,86 +1,100 @@
jest.mock("shared/supabase/init");
jest.mock("shared/supabase/utils");
jest.mock("common/util/try-catch");
jest.mock("shared/profiles/parse-photos");
jest.mock("shared/supabase/users");
import { AuthedUser } from "api/helpers/endpoint";
import { updateProfile } from "api/update-profile";
import { AuthedUser } from "api/helpers/endpoint";
import * as supabaseInit from "shared/supabase/init";
import * as supabaseUtils from "shared/supabase/utils";
import * as supabaseUsers from "shared/supabase/users";
import { tryCatch } from "common/util/try-catch";
import { removePinnedUrlFromPhotoUrls } from "shared/profiles/parse-photos";
describe('updateProfiles', () => {
let mockPg: any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
oneOrNone: jest.fn(),
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
jest.clearAllMocks();
});
describe('should', () => {
it('update an existing profile when provided the user id', async () => {
const mockUserProfile = {
user_id: '234',
diet: 'Nothing',
gender: 'female',
is_smoker: true,
}
const mockUpdateMade = {
gender: 'male'
}
const mockUpdatedProfile = {
user_id: '234',
diet: 'Nothing',
gender: 'male',
is_smoker: true,
}
const mockParams = {} as any;
const mockAuth = {
uid: '234'
}
afterEach(() => {
jest.restoreAllMocks();
});
mockPg.oneOrNone.mockResolvedValue(mockUserProfile);
(supabaseUtils.update as jest.Mock).mockResolvedValue(mockUpdatedProfile);
describe('when given valid input', () => {
it('should update an existing profile when provided the user id', async () => {
const mockProps = {
avatar_url: "mockAvatarUrl"
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockData = "success";
const result = await updateProfile(
mockUpdateMade,
mockAuth as AuthedUser,
mockParams
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: true})
.mockResolvedValueOnce({data: mockData, error: null});
const result = await updateProfile(mockProps, mockAuth, mockReq);
expect(result).toBe(mockData);
expect(mockPg.oneOrNone).toBeCalledTimes(1);
expect(mockPg.oneOrNone).toBeCalledWith(
expect.stringContaining('select * from profiles where user_id = $1'),
[mockAuth.uid]
);
expect(removePinnedUrlFromPhotoUrls).toBeCalledTimes(1);
expect(removePinnedUrlFromPhotoUrls).toBeCalledWith(mockProps);
expect(supabaseUsers.updateUser).toBeCalledTimes(1);
expect(supabaseUsers.updateUser).toBeCalledWith(
expect.any(Object),
mockAuth.uid,
{avatarUrl: mockProps.avatar_url}
);
expect(supabaseUtils.update).toBeCalledTimes(1);
expect(supabaseUtils.update).toBeCalledWith(
expect.any(Object),
'profiles',
'user_id',
expect.any(Object)
);
});
});
expect(mockPg.oneOrNone.mock.calls.length).toBe(1);
expect(mockPg.oneOrNone.mock.calls[0][1]).toEqual([mockAuth.uid]);
expect(result).toEqual(mockUpdatedProfile);
describe('when an error occurs', () => {
it('should throw if the profile does not exist', async () => {
const mockProps = {
avatar_url: "mockAvatarUrl"
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(tryCatch as jest.Mock).mockResolvedValue({data: false});
expect(updateProfile(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Profile not found');
});
it('throw an error if a profile is not found', async () => {
mockPg.oneOrNone.mockResolvedValue(null);
expect(updateProfile({} as any, {} as any, {} as any,))
.rejects
.toThrowError('Profile not found');
});
it('should throw if unable to update the profile', async () => {
const mockProps = {
avatar_url: "mockAvatarUrl"
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
it('throw an error if unable to update the profile', async () => {
const mockUserProfile = {
user_id: '234',
diet: 'Nothing',
gender: 'female',
is_smoker: true,
}
const data = null;
const error = true;
const mockError = {
data,
error
}
mockPg.oneOrNone.mockResolvedValue(mockUserProfile);
(supabaseUtils.update as jest.Mock).mockRejectedValue(mockError);
expect(updateProfile({} as any, {} as any, {} as any,))
(tryCatch as jest.Mock)
.mockResolvedValueOnce({data: true})
.mockResolvedValueOnce({data: null, error: Error});
expect(updateProfile(mockProps, mockAuth, mockReq))
.rejects
.toThrowError('Error updating profile');
.toThrow('Error updating profile');
});
});
});

View File

@@ -0,0 +1,101 @@
jest.mock('shared/supabase/init');
jest.mock('shared/utils');
import { AuthedUser } from "api/helpers/endpoint";
import { vote } from "api/vote";
import * as supabaseInit from "shared/supabase/init";
import * as sharedUtils from "shared/utils";
describe('vote', () => {
let mockPg = {} as any;
beforeEach(() => {
jest.resetAllMocks();
mockPg = {
one: jest.fn()
};
(supabaseInit.createSupabaseDirectClient as jest.Mock)
.mockReturnValue(mockPg);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('when given valid input', () => {
it('should vote successfully', async () => {
const mockProps = {
voteId: 1,
choice: 'for' as const,
priority: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUser = {id: "mockUserId"};
const mockResult = "success";
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(mockPg.one as jest.Mock).mockResolvedValue(mockResult);
const result = await vote(mockProps, mockAuth, mockReq);
expect(result.data).toBe(mockResult);
expect(sharedUtils.getUser).toBeCalledTimes(1);
expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid);
expect(mockPg.one).toBeCalledTimes(1);
expect(mockPg.one).toBeCalledWith(
expect.stringContaining('insert into vote_results (user_id, vote_id, choice, priority)'),
[mockUser.id, mockProps.voteId, 1, mockProps.priority]
);
});
});
describe('when an error occurs', () => {
it('should throw if unable to find the account', async () => {
const mockProps = {
voteId: 1,
choice: 'for' as const,
priority: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
(sharedUtils.getUser as jest.Mock).mockResolvedValue(false);
expect(vote(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Your account was not found');
});
it('should throw if the choice is invalid', async () => {
const mockProps = {
voteId: 1,
priority: 10
} as any;
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUser = {id: "mockUserId"};
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
expect(vote(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Invalid choice');
});
it('should throw if unable to record vote', async () => {
const mockProps = {
voteId: 1,
choice: 'for' as const,
priority: 10
};
const mockAuth = { uid: '321' } as AuthedUser;
const mockReq = {} as any;
const mockUser = {id: "mockUserId"};
(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser);
(mockPg.one as jest.Mock).mockRejectedValue(new Error('Result error'));
expect(vote(mockProps, mockAuth, mockReq))
.rejects
.toThrow('Error recording vote');
});
});
});