X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=test%2Flib%2Fcommunication.js;h=42b5116f7d7043c594d8b12ac6e3335e8a4fb172;hb=refs%2Ftags%2Fv1.4.0;hp=46ef89e2642ff206207fce8783052d1ea9fee2a5;hpb=cc52f66ba8522b6bc7002dfba79c1162a51aef0e;p=squeep-indieauth-helper diff --git a/test/lib/communication.js b/test/lib/communication.js index 46ef89e..42b5116 100644 --- a/test/lib/communication.js +++ b/test/lib/communication.js @@ -302,7 +302,7 @@ describe('Communication', function () { text: '', }, 'https://thuza.ratfeathers.com/': { - rels: ['self', 'canonical', 'author', 'me'], + rels: ['self', 'author', 'canonical', 'me'], text: 'Thuza', }, 'https://thuza.ratfeathers.com/image.png': { @@ -373,7 +373,7 @@ describe('Communication', function () { text: '', }, 'https://thuza.ratfeathers.com/': { - rels: ['self', 'canonical', 'author', 'me'], + rels: ['self', 'author', 'canonical', 'me'], text: 'Thuza', }, 'https://thuza.ratfeathers.com/image.png': { @@ -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