X-Git-Url: http://git.squeep.com/?p=squeep-indieauth-helper;a=blobdiff_plain;f=test%2Flib%2Fcommunication.js;fp=test%2Flib%2Fcommunication.js;h=42b5116f7d7043c594d8b12ac6e3335e8a4fb172;hp=332aa64921cd383d37cf73b155f2d6e754272949;hb=45d151c0587750c9a8ed3e3180ca79139a6ccb5e;hpb=1d9686ba6995243a939f9438045f92e7573e9b85 diff --git a/test/lib/communication.js b/test/lib/communication.js index 332aa64..42b5116 100644 --- a/test/lib/communication.js +++ b/test/lib/communication.js @@ -785,6 +785,52 @@ describe('Communication', function () { }); }); // fetchProfile + describe('fetchMetadata', function () { + let metadataUrl; + beforeEach(function () { + metadataUrl = new URL('https://thuza.ratfeathers.com/'); + sinon.stub(communication, 'fetchJSON'); + }); + it('covers success', async function () { + communication.fetchJSON.resolves({ + 'issuer': 'https://ia.squeep.com/', + 'authorization_endpoint': 'https://ia.squeep.com/auth', + 'token_endpoint': 'https://ia.squeep.com/token', + 'introspection_endpoint': 'https://ia.squeep.com/introspect', + 'introspection_endpoint_auth_methods_supported': [ '' ], + 'revocation_endpoint': 'https://ia.squeep.com/revoke', + 'revocation_endpoint_auth_methods_supported': [ 'none' ], + 'scopes_supported': [ 'profile', 'email' ], + 'service_documentation': 'https://indieauth.spec.indieweb.org/', + 'code_challenge_methods_supported': [ 'S256', 'SHA256' ], + 'authorization_response_iss_parameter_supported': true, + 'userinfo_endpoint': 'https://ia.squeep.com/userinfo', + }); + const expected = { + authorizationEndpoint: 'https://ia.squeep.com/auth', + tokenEndpoint: 'https://ia.squeep.com/token', + issuer: 'https://ia.squeep.com/', + introspectionEndpoint: 'https://ia.squeep.com/introspect', + introspectionEndpointAuthMethodsSupported: [ '' ], + revocationEndpoint: 'https://ia.squeep.com/revoke', + revocationEndpointAuthMethodsSupported: [ 'none' ], + scopesSupported: [ 'profile', 'email' ], + serviceDocumentation: 'https://indieauth.spec.indieweb.org/', + codeChallengeMethodsSupported: [ 'S256', 'SHA256' ], + authorizationResponseIssParameterSupported: true, + userinfoEndpoint: 'https://ia.squeep.com/userinfo', + }; + const result = await communication.fetchMetadata(metadataUrl); + assert.deepStrictEqual(result, expected); + }); + it('covers failure', async function () { + communication.fetchJSON.resolves(undefined); + const expected = {}; + const result = await communication.fetchMetadata(metadataUrl); + assert.deepStrictEqual(result, expected); + }); + }); // fetchMetadata + describe('redeemCode', function () { let expected, urlObj, code, codeVerifier, clientId, redirectURI; beforeEach(function () { @@ -878,14 +924,21 @@ describe('Communication', function () { }); // introspectToken describe('deliverTicket', function () { - let ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket; + let ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket, issuerUrlObj; beforeEach(function () { ticketEndpointUrlObj = new URL('https://ticket.example.com/'); resourceUrlObj = new URL('https://resource.example.com/'); subjectUrlObj = new URL('https://subject.example.com/'); + issuerUrlObj = new URL('https://idp.example.com/'); ticket = 'XXXThisIsATicketXXX'; }); it('covers success', async function () { + const expected = { body: 'blah', statusCode: 200 }; + communication.got.resolves(expected); + const result = await communication.deliverTicket(ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket, issuerUrlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers success, no issuer', async function () { const expected = { body: 'blah', statusCode: 200 }; communication.got.resolves(expected); const result = await communication.deliverTicket(ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket); @@ -898,4 +951,118 @@ describe('Communication', function () { }); }); // deliverTicket + describe('_fetchMetadataOrTokenEndpoint', function () { + let urlObj, metadataUrl, tokenUrl; + beforeEach(function () { + urlObj = new URL('https://idp.example.com/'); + metadataUrl = new URL('https://idp.example.com/meta'); + tokenUrl = new URL('https://idp.example.com/token'); + sinon.stub(communication, 'fetchMicroformat').resolves({ + rels: { + 'indieauth-metadata': [ metadataUrl.href ], + 'token_endpoint': [ tokenUrl.href ], + }, + }); + }); + it('covers success', async function () { + const expected = { + metadataUrl, + tokenUrl: undefined, + }; + const result = await communication._fetchMetadataOrTokenEndpoint(urlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers bad metadata url', async function () { + communication.fetchMicroformat.resolves({ + rels: { + 'indieauth-metadata': [ 'not a url' ], + 'token_endpoint': [ tokenUrl.href ], + }, + }); + const expected = { + metadataUrl: undefined, + tokenUrl, + }; + const result = await communication._fetchMetadataOrTokenEndpoint(urlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers bad token url', async function () { + communication.fetchMicroformat.resolves({ + rels: { + 'indieauth-metadata': [], + 'token_endpoint': [ 'not a url' ], + }, + }); + const expected = { + metadataUrl: undefined, + tokenUrl: undefined, + }; + const result = await communication._fetchMetadataOrTokenEndpoint(urlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers no rels', async function () { + communication.fetchMicroformat.resolves({ + rels: { + 'indieauth-metadata': [], + 'token_endpoint': [], + }, + }); + const expected = { + metadataUrl: undefined, + tokenUrl: undefined, + }; + const result = await communication._fetchMetadataOrTokenEndpoint(urlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers no url', async function () { + const expected = { + metadataUrl: undefined, + tokenUrl: undefined, + }; + const result = await communication._fetchMetadataOrTokenEndpoint(); + assert.deepStrictEqual(result, expected); + }); + }); // _fetchMetadataOrTokenEndpoint + + describe('redeemTicket', function () { + let ticket, resourceUrlObj, issuerUrlObj; + beforeEach(function () { + resourceUrlObj = new URL('https://resource.example.com/'); + issuerUrlObj = new URL('https://idp.example.com/'); + ticket = 'XXXThisIsATicketXXX'; + sinon.stub(communication, '_fetchMetadataOrTokenEndpoint').resolves({ + metadataUrl: new URL('https://example.com'), + tokenUrl: undefined, + }); + sinon.stub(communication, 'fetchMetadata').resolves({ tokenEndpoint: 'https://idp.example.com/' }); + }); + it('covers success', async function () { + const expected = { 'access_token': 'XXXThisIsAnAccessTokenXXX' }; + const response = { body: expected, headers: {}, statusCode: 200 }; + communication.got.resolves(response); + const result = await communication.redeemTicket(ticket, resourceUrlObj, issuerUrlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers success without issuer', async function () { + const expected = { 'access_token': 'XXXThisIsAnAccessTokenXXX' }; + const response = { body: expected, headers: {}, statusCode: 200 }; + communication.got.resolves(response); + const result = await communication.redeemTicket(ticket, resourceUrlObj); + assert.deepStrictEqual(result, expected); + }); + it('covers got failure', async function () { + const expectedException = new Error('oh no'); + communication.got.rejects(expectedException); + await assert.rejects(() => communication.redeemTicket(ticket, resourceUrlObj, issuerUrlObj), expectedException); + }); + it('covers no metadata url', async function () { + communication._fetchMetadataOrTokenEndpoint.resolves({ metadataUrl: undefined, tokenUrl: undefined }); + await assert.rejects(() => communication.redeemTicket(ticket, resourceUrlObj, issuerUrlObj), ValidationError); + }); + it('covers bad token url', async function () { + communication.fetchMetadata.resolves({ tokenEndpoint: 'not a url' }); + await assert.rejects(() => communication.redeemTicket(ticket, resourceUrlObj, issuerUrlObj), ValidationError); + }); + }); // redeemTicket + }); // Communication