add some support for tickets, introspection method, minor fixes
[squeep-indieauth-helper] / test / lib / communication.js
index 9781cd65b05088664a1d1dee04282d12ff31bf05..c79d2613f5388485862a3eb83ef7d84304b8582c 100644 (file)
@@ -13,8 +13,6 @@ const dns = require('dns');
 const stubLogger = require('../stub-logger');
 const testData = require('../test-data/communication');
 
-const noExpectedException = 'did not get expected exception';
-
 describe('Communication', function () {
   let communication, options;
 
@@ -69,12 +67,7 @@ describe('Communication', function () {
       assert.strictEqual(result.codeChallengeMethod, 'S256');
     });
     it('covers error', async function () {
-      try {
-        await Communication.generatePKCE(1);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof RangeError);
-      }
+      await assert.rejects(() => Communication.generatePKCE(1));
     });
   }); // generatePKCE
 
@@ -104,12 +97,7 @@ describe('Communication', function () {
       const method = 'MD5';
       const challenge = 'xkfP7DUYDsnu07Kg6ogc8A';
       const verifier = 'VGhpcyBpcyBhIHNlY3JldC4u';
-      try {
-        Communication.verifyChallenge(challenge, verifier, method);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e.message.includes('unsupported'));
-      }
+      assert.throws(() => Communication.verifyChallenge(challenge, verifier, method));
     });
   }); // verifyChallenge
 
@@ -539,7 +527,7 @@ describe('Communication', function () {
     let url, validationOptions;
     beforeEach(function () {
       url = 'https://example.com/';
-      options = {};
+      validationOptions = {};
       sinon.stub(dns, 'lookupAsync').resolves([{ family: 4, address: '10.11.12.14' }]);
     });
     it('rejects invalid url', async function () {
@@ -561,79 +549,39 @@ describe('Communication', function () {
     let url, validationOptions;
     beforeEach(function () {
       url = 'https://example.com/';
-      options = {};
+      validationOptions = {};
       sinon.stub(dns, 'lookupAsync').resolves([{ family: 4, address: '10.11.12.13' }]);
     });
     it('rejects invalid url', async function () {
-      try {
-        await communication.validateClientIdentifier('bad url');
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier('bad url'), ValidationError);
     });
     it('rejects invalid scheme', async function () {
       url = 'ftp://example.com/';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects fragment', async function () {
       url = 'https://example.com/#foo';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects username', async function () {
       url = 'https://user@example.com/';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects password', async function () {
       url = 'https://:foo@example.com/';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects relative path', async function () {
       url = 'https://example.com/client/../sneaky';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects ipv4', async function () {
       url = 'https://10.11.12.13/';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects ipv6', async function () {
       url = 'https://[fd64:defa:00e5:caf4:0dff::ad39]/';
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('accepts ipv4 loopback', async function () {
       url = 'https://127.0.0.1/';
@@ -661,21 +609,11 @@ describe('Communication', function () {
     });
     it('rejects resolution failure', async function () {
       dns.lookupAsync.rejects(new Error('oh no'));
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('rejects mismatched resolutions', async function () {
       dns.lookupAsync.onCall(1).resolves([{ family: 4, address: '10.9.8.7' }]);
-      try {
-        await communication.validateClientIdentifier(url, validationOptions);
-        assert.fail(noExpectedException);
-      } catch (e) {
-        assert(e instanceof ValidationError);
-      }
+      await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
     });
     it('ignores unknown dns family', async function () {
       dns.lookupAsync.resolves([{ family: 5, address: '10.9.8.7' }]);
@@ -934,7 +872,7 @@ describe('Communication', function () {
 
   describe('redeemProfileCode', function () {
     let expected, urlObj, code, codeVerifier, clientId, redirectURI;
-    this.beforeEach(function () {
+    beforeEach(function () {
       urlObj = new URL('https://example.com/auth');
       code = Buffer.allocUnsafe(42).toString('base64').replace('/', '_').replace('+', '-');
       codeVerifier = Buffer.allocUnsafe(42).toString('base64').replace('/', '_').replace('+', '-');
@@ -960,5 +898,64 @@ describe('Communication', function () {
 
       assert.strictEqual(result, undefined);
     });
-  });
+  }); // redeemProfileCode
+
+  describe('introspectToken', function () {
+    let introspectionUrlObj, authenticationHeader, token;
+    beforeEach(function () {
+      introspectionUrlObj = new URL('https://ia.example.com/introspect');
+      authenticationHeader = 'Bearer XXX';
+      token = 'xxx';
+    });
+    it('covers success active', async function () {
+      const nowEpoch = Math.ceil(Date.now() / 1000);
+      communication.axios.resolves({
+        data: JSON.stringify({
+          active: true,
+          me: 'https://profile.example.com/',
+          'client_id': 'https://app.example.com/',
+          scope: 'create profile email',
+          exp: nowEpoch + 86400,
+          iat: nowEpoch,
+        }),
+      });
+      const result = await communication.introspectToken(introspectionUrlObj, authenticationHeader, token);
+      assert.strictEqual(result.active, true);
+    });
+    it('covers success inactive', async function () {
+      communication.axios.resolves({
+        data: JSON.stringify({
+          active: false,
+        }),
+      });
+      const result = await communication.introspectToken(introspectionUrlObj, authenticationHeader, token);
+      assert.strictEqual(result.active, false);
+    });
+    it('covers failure', async function () {
+      communication.axios.resolves('what kind of response is this?');
+      await assert.rejects(() => communication.introspectToken(introspectionUrlObj, authenticationHeader, token));
+    });
+  }); // introspectToken
+
+  describe('deliverTicket', function () {
+    let ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket;
+    beforeEach(function () {
+      ticketEndpointUrlObj = new URL('https://ticket.example.com/');
+      resourceUrlObj = new URL('https://resource.example.com/');
+      subjectUrlObj = new URL('https://subject.example.com/');
+      ticket = 'XXXThisIsATicketXXX';
+    });
+    it('covers success', async function () {
+      const expected = { data: 'blah', statusCode: 200 };
+      communication.axios.resolves(expected);
+      const result = await communication.deliverTicket(ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket);
+      assert.deepStrictEqual(result, expected);
+    });
+    it('covers failure', async function () {
+      const expectedException = new Error('oh no');
+      communication.axios.rejects(expectedException);
+      await assert.rejects(() => communication.deliverTicket(ticketEndpointUrlObj, resourceUrlObj, subjectUrlObj, ticket), expectedException);
+    });
+  }); // deliverTicket
+
 }); // Communication
\ No newline at end of file