Bring in hapi-nextauth and dev support libs
This commit is contained in:
parent
feab3f90d7
commit
7aa1ec74eb
45 changed files with 14633 additions and 1141 deletions
363
packages/hapi-nextauth/src/index.spec.ts
Normal file
363
packages/hapi-nextauth/src/index.spec.ts
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
import * as Hapi from "@hapi/hapi";
|
||||
import HapiBasic from "@hapi/basic";
|
||||
import NextAuthPlugin from ".";
|
||||
|
||||
describe("plugin option validation", () => {
|
||||
let server;
|
||||
beforeEach(async () => {
|
||||
server = new Hapi.Server();
|
||||
});
|
||||
|
||||
it("should throw when options contain no next auth adapter", async () => {
|
||||
expect(server.register(NextAuthPlugin)).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("plugin runtime", () => {
|
||||
let server;
|
||||
const user = { id: "abc", email: "abc@abc.abc" };
|
||||
const session = {
|
||||
id: "zyx",
|
||||
userId: "abc",
|
||||
expires: Date.now(),
|
||||
sessionToken: "foo",
|
||||
accessToken: "bar",
|
||||
};
|
||||
|
||||
const start = async (mock) => {
|
||||
await server.register(HapiBasic);
|
||||
await server.register({
|
||||
plugin: NextAuthPlugin,
|
||||
options: {
|
||||
nextAuthAdapterFactory: () => mock,
|
||||
},
|
||||
});
|
||||
|
||||
await server.start();
|
||||
return server;
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
server = new Hapi.Server({ port: 0 });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it("createUser", async () => {
|
||||
const createUser = jest.fn(() => user);
|
||||
const profile = { email: "abc@abc.abc" };
|
||||
|
||||
await start({ createUser });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "post",
|
||||
url: "/api/nextauth/createUser",
|
||||
payload: profile,
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(createUser).toHaveBeenCalledWith(profile);
|
||||
expect(result).toStrictEqual(user);
|
||||
});
|
||||
|
||||
it("createUser fails with invalid payload", async () => {
|
||||
const createUser = jest.fn(() => user);
|
||||
const profile = { name: "name" };
|
||||
|
||||
await start({ createUser });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "post",
|
||||
url: "/api/nextauth/createUser",
|
||||
payload: profile,
|
||||
});
|
||||
expect(statusCode).toBe(400);
|
||||
});
|
||||
|
||||
it("getUser", async () => {
|
||||
const getUser = jest.fn(() => user);
|
||||
|
||||
await start({ getUser });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUser/abc",
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(getUser).toHaveBeenCalledWith("abc");
|
||||
expect(result).toBe(user);
|
||||
});
|
||||
|
||||
it("getUserByEmail", async () => {
|
||||
const getUserByEmail = jest.fn(() => user);
|
||||
|
||||
await start({ getUserByEmail });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUserByEmail/abc@abc.abc",
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(getUserByEmail).toHaveBeenCalledWith("abc@abc.abc");
|
||||
expect(result).toBe(user);
|
||||
});
|
||||
|
||||
it("getUserByEmail fails with invalid email", async () => {
|
||||
const getUserByEmail = jest.fn(() => user);
|
||||
|
||||
await start({ getUserByEmail });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUserByEmail/notanemail@foo",
|
||||
});
|
||||
expect(statusCode).toBe(400);
|
||||
});
|
||||
|
||||
it("getUserByProviderAccountId", async () => {
|
||||
const getUserByProviderAccountId = jest.fn(() => user);
|
||||
|
||||
await start({ getUserByProviderAccountId });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUserByProviderAccountId/foo/bar",
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(getUserByProviderAccountId).toHaveBeenCalledWith("foo", "bar");
|
||||
expect(result).toBe(user);
|
||||
});
|
||||
|
||||
it("updateUser", async () => {
|
||||
const updateUser = jest.fn(() => user);
|
||||
|
||||
await start({ updateUser });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "put",
|
||||
url: "/api/nextauth/updateUser",
|
||||
payload: user,
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(updateUser).toHaveBeenCalledWith(user);
|
||||
expect(result).toStrictEqual(user);
|
||||
});
|
||||
|
||||
it("updateUser fails with invalid payload", async () => {
|
||||
const updateUser = jest.fn(() => user);
|
||||
|
||||
await start({ updateUser });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "put",
|
||||
url: "/api/nextauth/updateUser",
|
||||
payload: {
|
||||
// id not specified
|
||||
email: "abc@abc.abc",
|
||||
},
|
||||
});
|
||||
expect(statusCode).toBe(400);
|
||||
});
|
||||
|
||||
it("linkUser", async () => {
|
||||
const linkAccount = jest.fn(() => undefined);
|
||||
const args = {
|
||||
userId: "abc",
|
||||
providerId: "foo",
|
||||
providerType: "something",
|
||||
providerAccountId: "bar",
|
||||
refreshToken: "refreshToken",
|
||||
accessToken: "accessToken",
|
||||
accessTokenExpires: 10,
|
||||
};
|
||||
|
||||
await start({ linkAccount });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "put",
|
||||
url: "/api/nextauth/linkAccount",
|
||||
payload: args,
|
||||
});
|
||||
expect(statusCode).toBe(204);
|
||||
expect(linkAccount.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it("createSession", async () => {
|
||||
const createSession = jest.fn(() => session);
|
||||
|
||||
await start({ createSession });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "post",
|
||||
url: "/api/nextauth/createSession",
|
||||
payload: user,
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(createSession).toHaveBeenCalledWith(user);
|
||||
expect(result).toStrictEqual(session);
|
||||
});
|
||||
|
||||
it("getSession", async () => {
|
||||
const getSession = jest.fn(() => session);
|
||||
|
||||
await start({ getSession });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getSession/xyz",
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(getSession).toHaveBeenCalledWith("xyz");
|
||||
expect(result).toBe(session);
|
||||
});
|
||||
|
||||
it("updateSession", async () => {
|
||||
const updateSession = jest.fn(() => session);
|
||||
|
||||
await start({ updateSession });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "put",
|
||||
url: "/api/nextauth/updateSession",
|
||||
payload: session,
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(updateSession).toHaveBeenCalledWith(
|
||||
{
|
||||
...session,
|
||||
expires: new Date(session.expires),
|
||||
},
|
||||
false
|
||||
);
|
||||
expect(result).toStrictEqual(session);
|
||||
});
|
||||
|
||||
it("updateSession - force", async () => {
|
||||
const updateSession = jest.fn(() => session);
|
||||
|
||||
await start({ updateSession });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "put",
|
||||
url: "/api/nextauth/updateSession?force=true",
|
||||
payload: session,
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(updateSession).toHaveBeenCalledWith(
|
||||
{
|
||||
...session,
|
||||
expires: new Date(session.expires),
|
||||
},
|
||||
true
|
||||
);
|
||||
expect(result).toStrictEqual(session);
|
||||
});
|
||||
|
||||
it("deleteSession", async () => {
|
||||
const deleteSession = jest.fn(() => undefined);
|
||||
|
||||
await start({ deleteSession });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "delete",
|
||||
url: "/api/nextauth/deleteSession/xyz",
|
||||
});
|
||||
expect(statusCode).toBe(204);
|
||||
expect(deleteSession).toHaveBeenCalledWith("xyz");
|
||||
});
|
||||
});
|
||||
|
||||
describe("plugin authentication", () => {
|
||||
const user = { id: "abc", email: "abc@abc.abc" };
|
||||
const sharedSecret = "secret";
|
||||
let server;
|
||||
|
||||
const start = async (mock) => {
|
||||
await server.register(HapiBasic);
|
||||
await server.register({
|
||||
plugin: NextAuthPlugin,
|
||||
options: {
|
||||
nextAuthAdapterFactory: () => mock,
|
||||
sharedSecret,
|
||||
},
|
||||
});
|
||||
|
||||
await server.start();
|
||||
return server;
|
||||
};
|
||||
|
||||
const basicHeader = (username, password) =>
|
||||
"Basic " +
|
||||
Buffer.from(username + ":" + password, "utf8").toString("base64");
|
||||
|
||||
beforeEach(async () => {
|
||||
server = new Hapi.Server({ port: 0 });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it("getUser - no auth header fails", async () => {
|
||||
const getUser = jest.fn(() => user);
|
||||
|
||||
await start({ getUser });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUser/abc",
|
||||
});
|
||||
expect(statusCode).toBe(401);
|
||||
expect(getUser).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("getUser - with auth header suceeds", async () => {
|
||||
const getUser = jest.fn(() => user);
|
||||
|
||||
await start({ getUser });
|
||||
|
||||
const { statusCode, result } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUser/abc",
|
||||
headers: {
|
||||
authorization: basicHeader(sharedSecret, ""),
|
||||
},
|
||||
});
|
||||
expect(statusCode).toBe(200);
|
||||
expect(getUser).toHaveBeenCalledWith("abc");
|
||||
expect(result).toBe(user);
|
||||
});
|
||||
|
||||
it("getUser - with invalid credentials fails", async () => {
|
||||
const getUser = jest.fn(() => user);
|
||||
|
||||
await start({ getUser });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUser/abc",
|
||||
headers: {
|
||||
authorization: basicHeader("wrong secret", ""),
|
||||
},
|
||||
});
|
||||
expect(statusCode).toBe(401);
|
||||
expect(getUser).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("getUser - with secret in password field fails", async () => {
|
||||
const getUser = jest.fn(() => user);
|
||||
|
||||
await start({ getUser });
|
||||
|
||||
const { statusCode } = await server.inject({
|
||||
method: "get",
|
||||
url: "/api/nextauth/getUser/abc",
|
||||
headers: {
|
||||
authorization: basicHeader("", "sharedSecret"),
|
||||
},
|
||||
});
|
||||
expect(statusCode).toBe(401);
|
||||
expect(getUser).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue