import React, { useEffect } from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act } from "react-dom/test-utils";
import { Auth0 } from "../providers/Auth0";
import { useAuth } from "../useAuth";
import { authService } from "../authReducer";
const auth0 = new Auth0({
dispatch: authService.send,
customPropertyNamespace: "localhost:8000",
domain: "localhost",
clientID: "12345",
redirectUri: `localhost/auth0_callback`,
audience: `https://localhost/api/v2/`,
responseType: "token id_token",
scope: "openid profile email"
});
auth0.authorize = jest.fn();
auth0.logout = jest.fn();
auth0.checkSession = jest.fn();
describe("useAuth", () => {
let container: any = null,
navigate = jest.fn();
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
authService.send("SET_CONFIG", {
authProvider: auth0,
navigate,
callbackDomain: "localhost:8000"
});
});
afterEach(() => {
unmountComponentAtNode(container);
container.remove();
container = null;
});
describe("login", () => {
it("calls auth0.authorize()", () => {
const Mock = () => {
const { login } = useAuth();
login();
return null;
};
act(() => {
render(, container);
});
expect(auth0.authorize).toBeCalled();
});
});
describe("logout", () => {
const Mock = () => {
const { logout } = useAuth();
useEffect(() => {
logout();
}, []);
return null;
};
it("calls auth0.logout()", () => {
act(() => {
render(, container);
});
expect(auth0.logout).toBeCalled();
});
it("puts user in unauthenticated state", () => {
act(() => {
render(, container);
});
expect(authService.state.value).toBe("unauthenticated");
});
});
describe("handleAuthentication", () => {
const Mock = () => {
const { handleAuthentication } = useAuth();
useEffect(() => {
handleAuthentication({ postLoginRoute: "/route" });
}, []);
return null;
};
it("puts user in authenticating state", () => {
act(() => {
render(, container);
});
expect(authService.state.value).toBe("authenticating");
});
// TODO: test fails because auth0 doesn't return true
it.skip("navigates to postLoginRoute", () => {
act(() => {
render(, container);
});
expect(navigate).toBeCalledWith("/route");
});
});
describe("isAuthenticated", () => {
afterEach(() => {
act(() => {
authService.send("LOGOUT");
});
});
it("is false when expiresAt not set", () => {
const Mock = () => {
const { isAuthenticated } = useAuth();
expect(isAuthenticated()).toBe(false);
return null;
};
act(() => {
render(, container);
});
});
it("is false when expiresAt in the past", () => {
const Mock = () => {
const { isAuthenticated } = useAuth();
expect(isAuthenticated()).toBe(false);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: -10 * 1000 * 60 * 24
},
user: { sub: "1234" }
});
act(() => {
render(, container);
});
});
it("is true when expiresAt in the future", () => {
const Mock = () => {
const { isAuthenticated } = useAuth();
useEffect(() => {
expect(isAuthenticated()).toBe(true);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: 10 * 1000 * 60 * 24
},
user: { sub: "1234" }
});
act(() => {
render(, container);
});
});
});
describe("isAuthorized", () => {
afterEach(() => {
act(() => {
authService.send("LOGOUT");
});
});
it("returns true if role exists", () => {
const Mock = () => {
const { isAuthorized } = useAuth();
useEffect(() => {
expect(isAuthorized("testRole")).toBe(true);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: 10 * 1000 * 60 * 24
},
user: {
"localhost:8000/user_metadata": {
roles: ["testRole"]
},
sub: "1234"
}
});
act(() => {
render(, container);
});
});
it("returns false if role does not exist", () => {
const Mock = () => {
const { isAuthorized } = useAuth();
useEffect(() => {
expect(isAuthorized("testRole")).toBe(false);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: 10 * 1000 * 60 * 24
},
user: {
"localhost:8000/user_metadata": {
roles: []
},
sub: "1234"
}
});
act(() => {
render(, container);
});
});
it("returns false if role exists but user not authenticated", () => {
const Mock = () => {
const { isAuthorized } = useAuth();
useEffect(() => {
expect(isAuthorized("testRole")).toBe(false);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: -10 * 1000 * 60 * 24
},
user: {
"localhost:8000/user_metadata": {
roles: ["testRole"]
},
sub: "1234"
}
});
act(() => {
render(, container);
});
});
describe("array argument", () => {
afterEach(() => {
act(() => {
authService.send("LOGOUT");
});
});
it("true if at least 1 present", () => {
const Mock = () => {
const { isAuthorized } = useAuth();
useEffect(() => {
expect(isAuthorized(["testRole1", "testRole2"])).toBe(
true
);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: 10 * 1000 * 60 * 24
},
user: {
"localhost:8000/user_metadata": {
roles: ["testRole1"]
},
sub: "1234"
}
});
act(() => {
render(, container);
});
});
it("false if none present", () => {
const Mock = () => {
const { isAuthorized } = useAuth();
useEffect(() => {
expect(isAuthorized(["testRole1", "testRole2"])).toBe(
false
);
}, []);
return null;
};
authService.send("LOGIN");
authService.send("AUTHENTICATED", {
authResult: {
expiresIn: 10 * 1000 * 60 * 24
},
user: {
"localhost:8000/user_metadata": {
roles: ["testRole"]
},
sub: "1234"
}
});
act(() => {
render(, container);
});
});
});
});
});