test: Update IDP integration tests for new API

This commit is contained in:
Joachim Van Herwegen 2021-12-06 13:49:39 +01:00
parent a684b2ead7
commit 129d3c0ef1
3 changed files with 51 additions and 53 deletions

View File

@ -30,19 +30,6 @@ async function postForm(url: string, formBody: string): Promise<Response> {
}); });
} }
/**
* 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+<http://www.w3.org/ns/solid/terms#oidcIssuerRegistrationToken>\\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 . // 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. // They will be simulated by storing the values and passing them along.
// This is why the redirects are handled manually. // 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<void> => { it('sends the form once to receive the registration triple.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/register/`, formBody); const res = await postForm(`${baseUrl}idp/register/`, formBody);
expect(res.status).toBe(400); 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<void> => { it('updates the webId with the registration token.', async(): Promise<void> => {
@ -114,10 +102,11 @@ describe('A Solid server with IDP', (): void => {
it('sends the form again to successfully register.', async(): Promise<void> => { it('sends the form again to successfully register.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/register/`, formBody); const res = await postForm(`${baseUrl}idp/register/`, formBody);
expect(res.status).toBe(200); expect(res.status).toBe(200);
const text = await res.text(); await expect(res.json()).resolves.toEqual(expect.objectContaining({
expect(text).toMatch(new RegExp(`your.WebID.*${webId}`, 'u')); webId,
expect(text).toMatch(new RegExp(`your.email.address.*${email}`, 'u')); email,
expect(text).toMatch(new RegExp(`<code>&lt;${webId}&gt; &lt;http://www.w3.org/ns/solid/terms#oidcIssuer&gt; &lt;${baseUrl}&gt;\\.</code>`, 'mu')); oidcIssuer: baseUrl,
}));
}); });
}); });
@ -146,7 +135,8 @@ describe('A Solid server with IDP', (): void => {
it('initializes the session and logs in.', async(): Promise<void> => { it('initializes the session and logs in.', async(): Promise<void> => {
const url = await state.startSession(); 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); await state.login(url, email, password);
expect(state.session.info?.webId).toBe(webId); expect(state.session.info?.webId).toBe(webId);
}); });
@ -171,11 +161,13 @@ describe('A Solid server with IDP', (): void => {
let res = await state.fetchIdp(url); let res = await state.fetchIdp(url);
expect(res.status).toBe(200); 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); 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'); expect(typeof nextUrl).toBe('string');
await state.handleLoginRedirect(nextUrl!); await state.handleLoginRedirect(nextUrl);
expect(state.session.info?.webId).toBe(webId); 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<void> => { it('sends the corresponding email address through the form to get a mail.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/forgotpassword/`, stringify({ email })); const res = await postForm(`${baseUrl}idp/forgotpassword/`, stringify({ email }));
expect(res.status).toBe(200); expect(res.status).toBe(200);
expect(load(await res.text())('form p').first().text().trim()) const json = await res.json();
.toBe('If your account exists, an email has been sent with a link to reset your password.'); expect(json.email).toBe(email);
const mail = sendMail.mock.calls[0][0]; const mail = sendMail.mock.calls[0][0];
expect(mail.to).toBe(email); expect(mail.to).toBe(email);
@ -218,7 +210,6 @@ describe('A Solid server with IDP', (): void => {
body: formData, body: formData,
}); });
expect(res.status).toBe(200); 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<void> => { it('can not log in with the old password anymore.', async(): Promise<void> => {
const url = await state.startSession(); const url = await state.startSession();
nextUrl = url; nextUrl = url;
await state.parseLoginPage(url); let res = await state.fetchIdp(url);
expect(res.status).toBe(200);
const formData = stringify({ email, password }); 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(res.status).toBe(500);
expect(await res.text()).toContain('Incorrect password'); 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<void> => { it('sends the form once to receive the registration triple.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/register/`, formBody); const res = await postForm(`${baseUrl}idp/register/`, formBody);
expect(res.status).toBe(400); 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<void> => { it('updates the webId with the registration token.', async(): Promise<void> => {
@ -282,8 +275,11 @@ describe('A Solid server with IDP', (): void => {
it('sends the form again to successfully register.', async(): Promise<void> => { it('sends the form again to successfully register.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/register/`, formBody); const res = await postForm(`${baseUrl}idp/register/`, formBody);
expect(res.status).toBe(200); expect(res.status).toBe(200);
const text = await res.text(); await expect(res.json()).resolves.toEqual(expect.objectContaining({
expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u')); 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<void> => { it('sends the form to create the WebID and register.', async(): Promise<void> => {
const res = await postForm(`${baseUrl}idp/register/`, formBody); const res = await postForm(`${baseUrl}idp/register/`, formBody);
expect(res.status).toBe(200); expect(res.status).toBe(200);
const text = await res.text(); const json = await res.json();
expect(json).toEqual(expect.objectContaining({
const matchWebId = /Your new WebID is [^>]+>([^<]+)/u.exec(text); webId: expect.any(String),
expect(matchWebId).toBeDefined(); email: newMail,
expect(matchWebId).toHaveLength(2); oidcIssuer: baseUrl,
newWebId = matchWebId![1]; podBaseUrl: `${baseUrl}${podName}/`,
expect(text).toMatch(new RegExp(`new WebID is.*${newWebId}`, 'u')); }));
expect(text).toMatch(new RegExp(`your email address.*${newMail}`, 'u')); newWebId = json.webId;
expect(text).toMatch(new RegExp(`Your new Pod.*${baseUrl}${podName}/`, 'u'));
}); });
it('initializes the session and logs in.', async(): Promise<void> => { it('initializes the session and logs in.', async(): Promise<void> => {
state = new IdentityTestState(baseUrl, redirectUrl, oidcIssuer); state = new IdentityTestState(baseUrl, redirectUrl, oidcIssuer);
const url = await state.startSession(); 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); await state.login(url, newMail, password);
expect(state.session.info?.webId).toBe(newWebId); expect(state.session.info?.webId).toBe(newWebId);
}); });

View File

@ -87,21 +87,21 @@ export class IdentityTestState {
expect(nextUrl.startsWith(this.oidcIssuer)).toBeTruthy(); expect(nextUrl.startsWith(this.oidcIssuer)).toBeTruthy();
// Need to catch the redirect so we can copy the cookies // 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); expect(res.status).toBe(302);
nextUrl = res.headers.get('location')!; nextUrl = res.headers.get('location')!;
return nextUrl; // Handle redirect
} res = await this.fetchIdp(nextUrl);
public async parseLoginPage(url: string): Promise<{ register: string; forgotPassword: string }> {
const res = await this.fetchIdp(url);
expect(res.status).toBe(200); 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<void> { public async login(url: string, email: string, password: string): Promise<void> {
const formData = stringify({ email, password }); const formData = stringify({ email, password });
const res = await this.fetchIdp(url, 'POST', formData, APPLICATION_X_WWW_FORM_URLENCODED); const res = await this.fetchIdp(url, 'POST', formData, APPLICATION_X_WWW_FORM_URLENCODED);
expect(res.status).toBe(302); expect(res.status).toBe(200);
const nextUrl = res.headers.get('location')!; const json = await res.json();
const nextUrl = json.location;
return this.handleLoginRedirect(nextUrl); return this.handleLoginRedirect(nextUrl);
} }

View File

@ -95,12 +95,13 @@ describe('A server with restricted IDP access', (): void => {
// Logging into session // Logging into session
const state = new IdentityTestState(baseUrl, 'http://mockedredirect/', baseUrl); const state = new IdentityTestState(baseUrl, 'http://mockedredirect/', baseUrl);
const url = await state.startSession(); 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); await state.login(url, settings.email, settings.password);
expect(state.session.info?.webId).toBe(webId); expect(state.session.info?.webId).toBe(webId);
// Registration still works for this 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); expect(res.status).toBe(200);
res = await state.session.fetch(`${baseUrl}idp/register/`, { res = await state.session.fetch(`${baseUrl}idp/register/`, {