From 9b1c436373f69284795f951eb9dffa9cf09e3acb Mon Sep 17 00:00:00 2001 From: Jasir Zaeem <20666236+JasirZaeem@users.noreply.github.com> Date: Sat, 14 Aug 2021 21:01:34 +0530 Subject: [PATCH 1/3] Redirect unauthenticated user to /login --- pages/review/[lesson].tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pages/review/[lesson].tsx b/pages/review/[lesson].tsx index cf73808cf..907cdfab2 100644 --- a/pages/review/[lesson].tsx +++ b/pages/review/[lesson].tsx @@ -44,8 +44,11 @@ const Review: React.FC> = ({ queryData }) => { if (loading) { return } - if (!session) { - router.push('/login') + if (!session?.user) { + router.push({ + pathname: '/login', + query: { next: router.asPath } + }) return } const currentLesson = lessons.find(lesson => lesson.id === currentlessonId) From 0cb9463ddb1d6c8b056934c5b470ad86eef18c66 Mon Sep 17 00:00:00 2001 From: Jasir Zaeem <20666236+JasirZaeem@users.noreply.github.com> Date: Sat, 14 Aug 2021 21:02:36 +0530 Subject: [PATCH 2/3] Add a next query param with path to redirect to on successful login --- pages/login.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pages/login.tsx b/pages/login.tsx index 8f78e8489..d4f58f5ef 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -95,7 +95,8 @@ const LoginPage: React.FC & WithLayout = () => { const { success } = _.get(data, 'login', false) if (success) { window.localStorage.setItem('loggedIn', 'true') - router.push('/curriculum') + const { next } = router.query + router.push(next ? (next as string) : '/curriculum') } if (error) { const graphQLErrors: any = _.get(error, 'graphQLErrors', []) From cc5893cae74140598d6a37ac7bde7dfc921853c6 Mon Sep 17 00:00:00 2001 From: Jasir Zaeem <20666236+JasirZaeem@users.noreply.github.com> Date: Sat, 14 Aug 2021 21:02:45 +0530 Subject: [PATCH 3/3] Update tests --- __tests__/pages/login.test.js | 98 +++++++++++++++---------- __tests__/pages/review/[lesson].test.js | 13 +++- 2 files changed, 70 insertions(+), 41 deletions(-) diff --git a/__tests__/pages/login.test.js b/__tests__/pages/login.test.js index 2e1ff830d..baa656d87 100644 --- a/__tests__/pages/login.test.js +++ b/__tests__/pages/login.test.js @@ -8,6 +8,7 @@ import LOGIN_USER from '../../graphql/queries/loginUser' import LoginPage from '../../pages/login' import { useRouter } from 'next/router' import { getLayout } from '../../components/Layout' +import { cloneDeep } from 'lodash' describe('Login Page', () => { const fakeUsername = 'fake username' @@ -21,7 +22,7 @@ describe('Login Page', () => { await userEvent.type(usernameField, fakeUsername, { delay: 1 }) await userEvent.type(passwordField, fakePassword, { delay: 1 }) } - const { push } = useRouter() + const { push, query } = useRouter() beforeEach(() => { jest.clearAllMocks() }) @@ -29,51 +30,54 @@ describe('Login Page', () => { expect(LoginPage.getLayout === getLayout).toBe(true) }) - test('Should redirect to /curriculum on success', async () => { - const mocks = [ - { - request: { query: GET_APP }, - result: { - data: { - session: null, - lessons: [], - alerts: [] - } + const successfulLoginMocks = [ + { + request: { query: GET_APP }, + result: { + data: { + session: null, + lessons: [], + alerts: [] } - }, - { - request: { query: GET_APP }, - result: { - data: { - session: null, - lessons: [], - alerts: [] - } + } + }, + { + request: { query: GET_APP }, + result: { + data: { + session: null, + lessons: [], + alerts: [] + } + } + }, + { + request: { + query: LOGIN_USER, + variables: { + username: fakeUsername, + password: fakePassword } }, - { - request: { - query: LOGIN_USER, - variables: { + result: { + data: { + login: { + success: true, username: fakeUsername, - password: fakePassword - } - }, - result: { - data: { - login: { - success: true, - username: fakeUsername, - cliToken: 'fake token', - error: null - } + cliToken: 'fake token', + error: null } } } - ] + } + ] + test('Should redirect to /curriculum on success', async () => { const { getByTestId } = render( - + ) @@ -86,6 +90,26 @@ describe('Login Page', () => { await waitFor(() => expect(push).toBeCalledWith('/curriculum')) }) + test('Should redirect to the path in `next` on success', async () => { + query.next = 'url-to-go-to-post-login' + + const { getByTestId } = render( + + + + ) + + const submitButton = getByTestId('submit') + + await fillOutLoginForm(getByTestId) + fireEvent.click(submitButton) + + await waitFor(() => expect(push).toBeCalledWith(query.next)) + }) + test('Should set alert visible on invalid credentials', async () => { const mocks = [ { diff --git a/__tests__/pages/review/[lesson].test.js b/__tests__/pages/review/[lesson].test.js index 1995f7c88..214e01863 100644 --- a/__tests__/pages/review/[lesson].test.js +++ b/__tests__/pages/review/[lesson].test.js @@ -69,7 +69,6 @@ const getSubmissionsMock = { } } } - const getPreviousSubmissionsMock = { request: { query: GET_PREVIOUS_SUBMISSIONS, @@ -79,9 +78,10 @@ const getPreviousSubmissionsMock = { data: getPreviousSubmissions } } + const mocks = [getAppMock, getSubmissionsMock, getPreviousSubmissionsMock] describe('Lesson Page', () => { - const { query, push } = useRouter() + const { query, push, asPath } = useRouter() query['lesson'] = '2' test('Should render new submissions', async () => { const { container } = render( @@ -100,7 +100,7 @@ describe('Lesson Page', () => { test('Should return loading spinner when loading', () => { expectLoading() }) - test('Should redirect to login if no session', async () => { + test('Should redirect to login if no user is logged in', async () => { const noSessionMock = { request: { query: GET_APP }, result: { @@ -120,7 +120,12 @@ describe('Lesson Page', () => { ) - await waitFor(() => expect(push).toBeCalledWith('/login')) + await waitFor(() => + expect(push).toBeCalledWith({ + pathname: '/login', + query: { next: asPath } + }) + ) }) test("Should redirect to curriculum if user hasn't completed lesson yet", async () => { const noSessionMock = {