From 129d3c0ef13d437878d0c0b0f545cfd0156605d6 Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Mon, 6 Dec 2021 13:49:39 +0100 Subject: [PATCH] test: Update IDP integration tests for new API --- test/integration/Identity.test.ts | 74 ++++++++++----------- test/integration/IdentityTestState.ts | 25 +++---- test/integration/RestrictedIdentity.test.ts | 5 +- 3 files changed, 51 insertions(+), 53 deletions(-) diff --git a/test/integration/Identity.test.ts b/test/integration/Identity.test.ts index 0561562e8..df242aae0 100644 --- a/test/integration/Identity.test.ts +++ b/test/integration/Identity.test.ts @@ -30,19 +30,6 @@ async function postForm(url: string, formBody: string): Promise { }); } -/** - * Extracts the registration triple from the registration form body. - */ -function extractRegistrationTriple(body: string, webId: string): string { - const error = load(body)('p.error').first().text(); - const regex = new RegExp( - `<${webId}>\\s+\\s+"[^"]+"\\s*\\.`, 'u', - ); - const match = regex.exec(error); - expect(match).toHaveLength(1); - return match![0]; -} - // No way around the cookies https://github.com/panva/node-oidc-provider/issues/552 . // They will be simulated by storing the values and passing them along. // This is why the redirects are handled manually. @@ -98,7 +85,8 @@ describe('A Solid server with IDP', (): void => { it('sends the form once to receive the registration triple.', async(): Promise => { const res = await postForm(`${baseUrl}idp/register/`, formBody); expect(res.status).toBe(400); - registrationTriple = extractRegistrationTriple(await res.text(), webId); + const json = await res.json(); + registrationTriple = json.details.quad; }); it('updates the webId with the registration token.', async(): Promise => { @@ -114,10 +102,11 @@ describe('A Solid server with IDP', (): void => { it('sends the form again to successfully register.', async(): Promise => { const res = await postForm(`${baseUrl}idp/register/`, formBody); expect(res.status).toBe(200); - const text = await res.text(); - expect(text).toMatch(new RegExp(`your.WebID.*${webId}`, 'u')); - expect(text).toMatch(new RegExp(`your.email.address.*${email}`, 'u')); - expect(text).toMatch(new RegExp(`<${webId}> <http://www.w3.org/ns/solid/terms#oidcIssuer> <${baseUrl}>\\.`, 'mu')); + await expect(res.json()).resolves.toEqual(expect.objectContaining({ + webId, + email, + oidcIssuer: baseUrl, + })); }); }); @@ -146,7 +135,8 @@ describe('A Solid server with IDP', (): void => { it('initializes the session and logs in.', async(): Promise => { const url = await state.startSession(); - await state.parseLoginPage(url); + const res = await state.fetchIdp(url); + expect(res.status).toBe(200); await state.login(url, email, password); expect(state.session.info?.webId).toBe(webId); }); @@ -171,11 +161,13 @@ describe('A Solid server with IDP', (): void => { let res = await state.fetchIdp(url); expect(res.status).toBe(200); + // Will receive confirm screen here instead of login screen res = await state.fetchIdp(url, 'POST', '', APPLICATION_X_WWW_FORM_URLENCODED); - const nextUrl = res.headers.get('location'); + const json = await res.json(); + const nextUrl = json.location; expect(typeof nextUrl).toBe('string'); - await state.handleLoginRedirect(nextUrl!); + await state.handleLoginRedirect(nextUrl); expect(state.session.info?.webId).toBe(webId); }); }); @@ -186,8 +178,8 @@ describe('A Solid server with IDP', (): void => { it('sends the corresponding email address through the form to get a mail.', async(): Promise => { const res = await postForm(`${baseUrl}idp/forgotpassword/`, stringify({ email })); expect(res.status).toBe(200); - expect(load(await res.text())('form p').first().text().trim()) - .toBe('If your account exists, an email has been sent with a link to reset your password.'); + const json = await res.json(); + expect(json.email).toBe(email); const mail = sendMail.mock.calls[0][0]; expect(mail.to).toBe(email); @@ -218,7 +210,6 @@ describe('A Solid server with IDP', (): void => { body: formData, }); expect(res.status).toBe(200); - expect(await res.text()).toContain('Your password was successfully reset.'); }); }); @@ -233,9 +224,10 @@ describe('A Solid server with IDP', (): void => { it('can not log in with the old password anymore.', async(): Promise => { const url = await state.startSession(); nextUrl = url; - await state.parseLoginPage(url); + let res = await state.fetchIdp(url); + expect(res.status).toBe(200); const formData = stringify({ email, password }); - const res = await state.fetchIdp(url, 'POST', formData, APPLICATION_X_WWW_FORM_URLENCODED); + res = await state.fetchIdp(url, 'POST', formData, APPLICATION_X_WWW_FORM_URLENCODED); expect(res.status).toBe(500); expect(await res.text()).toContain('Incorrect password'); }); @@ -266,7 +258,8 @@ describe('A Solid server with IDP', (): void => { it('sends the form once to receive the registration triple.', async(): Promise => { const res = await postForm(`${baseUrl}idp/register/`, formBody); expect(res.status).toBe(400); - registrationTriple = extractRegistrationTriple(await res.text(), webId2); + const json = await res.json(); + registrationTriple = json.details.quad; }); it('updates the webId with the registration token.', async(): Promise => { @@ -282,8 +275,11 @@ describe('A Solid server with IDP', (): void => { it('sends the form again to successfully register.', async(): Promise => { const res = await postForm(`${baseUrl}idp/register/`, formBody); expect(res.status).toBe(200); - const text = await res.text(); - expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u')); + await expect(res.json()).resolves.toEqual(expect.objectContaining({ + email: 'bob@test.email', + webId: webId2, + podBaseUrl: `${baseUrl}${podName}/`, + })); }); }); @@ -300,21 +296,21 @@ describe('A Solid server with IDP', (): void => { it('sends the form to create the WebID and register.', async(): Promise => { const res = await postForm(`${baseUrl}idp/register/`, formBody); expect(res.status).toBe(200); - const text = await res.text(); - - const matchWebId = /Your new WebID is [^>]+>([^<]+)/u.exec(text); - expect(matchWebId).toBeDefined(); - expect(matchWebId).toHaveLength(2); - newWebId = matchWebId![1]; - expect(text).toMatch(new RegExp(`new WebID is.*${newWebId}`, 'u')); - expect(text).toMatch(new RegExp(`your email address.*${newMail}`, 'u')); - expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u')); + const json = await res.json(); + expect(json).toEqual(expect.objectContaining({ + webId: expect.any(String), + email: newMail, + oidcIssuer: baseUrl, + podBaseUrl: `${baseUrl}${podName}/`, + })); + newWebId = json.webId; }); it('initializes the session and logs in.', async(): Promise => { state = new IdentityTestState(baseUrl, redirectUrl, oidcIssuer); const url = await state.startSession(); - await state.parseLoginPage(url); + const res = await state.fetchIdp(url); + expect(res.status).toBe(200); await state.login(url, newMail, password); expect(state.session.info?.webId).toBe(newWebId); }); diff --git a/test/integration/IdentityTestState.ts b/test/integration/IdentityTestState.ts index 28597d006..59816a44a 100644 --- a/test/integration/IdentityTestState.ts +++ b/test/integration/IdentityTestState.ts @@ -87,21 +87,21 @@ export class IdentityTestState { expect(nextUrl.startsWith(this.oidcIssuer)).toBeTruthy(); // Need to catch the redirect so we can copy the cookies - const res = await this.fetchIdp(nextUrl); + let res = await this.fetchIdp(nextUrl); expect(res.status).toBe(302); nextUrl = res.headers.get('location')!; - return nextUrl; - } - - public async parseLoginPage(url: string): Promise<{ register: string; forgotPassword: string }> { - const res = await this.fetchIdp(url); + // Handle redirect + res = await this.fetchIdp(nextUrl); expect(res.status).toBe(200); - const text = await res.text(); - const register = this.extractUrl(text, 'a:contains("Sign up")', 'href'); - const forgotPassword = this.extractUrl(text, 'a:contains("Forgot password")', 'href'); - return { register, forgotPassword }; + // Need to send request to prompt API to get actual location + let json = await res.json(); + res = await this.fetchIdp(json.controls.prompt); + json = await res.json(); + nextUrl = json.location; + + return nextUrl; } /** @@ -111,8 +111,9 @@ export class IdentityTestState { public async login(url: string, email: string, password: string): Promise { const formData = stringify({ email, password }); const res = await this.fetchIdp(url, 'POST', formData, APPLICATION_X_WWW_FORM_URLENCODED); - expect(res.status).toBe(302); - const nextUrl = res.headers.get('location')!; + expect(res.status).toBe(200); + const json = await res.json(); + const nextUrl = json.location; return this.handleLoginRedirect(nextUrl); } diff --git a/test/integration/RestrictedIdentity.test.ts b/test/integration/RestrictedIdentity.test.ts index 9a0db6593..a9fee024f 100644 --- a/test/integration/RestrictedIdentity.test.ts +++ b/test/integration/RestrictedIdentity.test.ts @@ -95,12 +95,13 @@ describe('A server with restricted IDP access', (): void => { // Logging into session const state = new IdentityTestState(baseUrl, 'http://mockedredirect/', baseUrl); const url = await state.startSession(); - await state.parseLoginPage(url); + let res = await state.fetchIdp(url); + expect(res.status).toBe(200); await state.login(url, settings.email, settings.password); expect(state.session.info?.webId).toBe(webId); // Registration still works for this WebID - let res = await state.session.fetch(`${baseUrl}idp/register/`); + res = await state.session.fetch(`${baseUrl}idp/register/`); expect(res.status).toBe(200); res = await state.session.fetch(`${baseUrl}idp/register/`, {