Files
protocol/sites/dev0x-portal/app/auth.server.test.ts
2023-03-07 20:36:14 +01:00

179 lines
5.2 KiB
TypeScript

import type { User } from './auth.server';
import { withSignedInUser, auth, sessionStorage } from './auth.server';
import { faker } from '@faker-js/faker';
import { addMinutes, startOfMinute } from 'date-fns';
import type { Mock } from 'vitest';
import { vi } from 'vitest';
import { doesSessionExist } from './data/zippo.server';
// mock the zippo.server module
vi.mock('./data/zippo.server', () => ({
doesSessionExist: vi.fn(),
}));
function createUser(overwrites: Partial<User> = {}): User {
return {
id: faker.datatype.uuid(),
email: faker.internet.email(),
team: faker.company.name(),
sessionToken: faker.datatype.uuid(),
expiresAt: addMinutes(new Date(), 15).toISOString(),
...overwrites,
};
}
const createUserSessionCookie = async (user: User) => {
const session = await sessionStorage.getSession();
session.set(auth.sessionKey, user);
return sessionStorage.commitSession(session);
};
const createRequestWithSession = async (user: User) => {
const request = new Request('/', {
headers: {
cookie: await createUserSessionCookie(user),
},
});
return request;
};
describe('withSignedInUser', () => {
const doesSessionExistMock = doesSessionExist as Mock;
afterEach(() => {
doesSessionExistMock.mockReset();
});
it('should return the user if the session is valid', async () => {
const user = createUser();
doesSessionExistMock.mockReturnValue(true);
const request = await createRequestWithSession(user);
let result: User | undefined;
await withSignedInUser(request, async (user) => {
result = user;
return new Response();
});
expect(result).toEqual(user);
});
it('should redirect to the landing page if the session is invalid', async () => {
await expect(withSignedInUser(new Request('/'), async () => new Response())).rejects
.toThrowErrorMatchingInlineSnapshot(`
NodeResponse {
"size": 0,
Symbol(Body internals): {
"body": null,
"boundary": null,
"disturbed": false,
"error": null,
"size": 0,
"type": null,
},
Symbol(Response internals): {
"counter": 0,
"headers": Headers {
Symbol(query): [
"location",
"/",
],
Symbol(context): null,
},
"highWaterMark": undefined,
"status": 302,
"statusText": "",
"url": undefined,
},
}
`);
});
it('should return the user if the session is expired but still valid', async () => {
const user = createUser({
expiresAt: addMinutes(new Date(), -15).toISOString(),
});
doesSessionExistMock.mockReturnValue(true);
const request = await createRequestWithSession(user);
let result: User | undefined;
await withSignedInUser(request, async (user) => {
result = user;
return new Response();
});
expect(result?.id).toEqual(user.id);
});
it('should update the session expiry by 15 minutes if the session is expired but still valid', async () => {
const user = createUser({
expiresAt: startOfMinute(addMinutes(new Date(), -15)).toISOString(),
});
doesSessionExistMock.mockReturnValue(true);
const request = await createRequestWithSession(user);
let result: User | undefined;
await withSignedInUser(request, async (user) => {
result = user;
return new Response();
});
expect(startOfMinute(new Date(result?.expiresAt || 0)).toISOString()).toEqual(
startOfMinute(addMinutes(new Date(), 15)).toISOString(),
);
});
it('should redirect to the login page if the session is expired and invalid', async () => {
const user = createUser({
expiresAt: addMinutes(new Date(), -15).toISOString(),
});
doesSessionExistMock.mockReturnValue(false);
const request = await createRequestWithSession(user);
let result: Response | undefined;
// the redirect gets thrown as an exception, so we need to assert the exception
await expect(
withSignedInUser(request, async (user) => {
result = new Response();
return result;
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
NodeResponse {
"size": 0,
Symbol(Body internals): {
"body": null,
"boundary": null,
"disturbed": false,
"error": null,
"size": 0,
"type": null,
},
Symbol(Response internals): {
"counter": 0,
"headers": Headers {
Symbol(query): [
"location",
"/login",
"set-cookie",
"__session=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=Lax",
],
Symbol(context): null,
},
"highWaterMark": undefined,
"status": 302,
"statusText": "",
"url": undefined,
},
}
`); // redirect to login page
});
});