support indieauth-metadata relation on profiles, per spec 20220212
[squeep-indieauth-helper] / test / lib / communication.js
index 9a6056db723093696e4e4cc7f72561c3c3b9b54a..5c41469db57a763c3fc202cb769c77b5566e1e3b 100644 (file)
@@ -477,6 +477,45 @@ describe('Communication', function () {
     });
   }); // fetchMicroformat
 
+  describe('fetchJSON', function () {
+    let expected, response, result, urlObj;
+    beforeEach(function () {
+      expected = undefined;
+      result = undefined;
+      urlObj = new URL('https://thuza.ratfeathers.com/');
+      response = {
+        headers: Object.assign({}, testData.linkHeaders),
+        data: testData.hCardHtml,
+      };
+    });
+    it('covers', async function () {
+      communication.axios.resolves(response);
+      expected = { foo: 'bar', baz: 123 };
+      response.data = JSON.stringify(expected);
+
+      result = await communication.fetchJSON(urlObj);
+      assert.deepStrictEqual(result, expected);
+    });
+    it('covers axios error', async function () {
+      communication.axios.rejects(new Error('blah'));
+      expected = undefined;
+
+      result = await communication.fetchJSON(urlObj);
+
+      assert.deepStrictEqual(result, expected);
+    });
+    it('covers non-parsable content', async function () {
+      response.data = 'some bare text';
+      response.headers = {};
+      communication.axios.resolves(response);
+      expected = undefined;
+
+      result = await communication.fetchJSON(urlObj);
+
+      assert.deepStrictEqual(result, expected);
+    });
+  }); // fetchJSON
+
   describe('fetchClientIdentifier', function () {
     let expected, response, result, urlObj;
     beforeEach(function () {
@@ -565,43 +604,141 @@ describe('Communication', function () {
         headers: {},
         data: testData.hCardHtml,
       };
+      sinon.stub(communication, 'fetchJSON');
+    });
+    describe('legacy without indieauth-metadata', function () {
+      it('covers', async function () {
+        communication.axios.resolves(response);
+        expected = {
+          name: 'Thuza',
+          photo: 'https://thuza.ratfeathers.com/image.png',
+          url: 'https://thuza.ratfeathers.com/',
+          email: undefined,
+          authorizationEndpoint: 'https://ia.squeep.com/auth',
+          tokenEndpoint: 'https://ia.squeep.com/token',
+          metadata: {
+            authorizationEndpoint: 'https://ia.squeep.com/auth',
+            tokenEndpoint: 'https://ia.squeep.com/token',  
+          },
+        };
+        result = await communication.fetchProfile(urlObj);
+        assert.deepStrictEqual(result, expected);
+      });
+      it('covers multiple hCards', async function () {
+        response.data = testData.multiMF2Html;
+        communication.axios.resolves(response);
+        expected = {
+          email: undefined,
+          name: 'Thuza',
+          photo: 'https://thuza.ratfeathers.com/image.png',
+          url: 'https://thuza.ratfeathers.com/',
+          authorizationEndpoint: 'https://ia.squeep.com/auth',
+          tokenEndpoint: 'https://ia.squeep.com/token',
+          metadata: {
+            authorizationEndpoint: 'https://ia.squeep.com/auth',
+            tokenEndpoint: 'https://ia.squeep.com/token',  
+          },
+        };
+        result = await communication.fetchProfile(urlObj);
+        assert.deepStrictEqual(result, expected);
+      });
+      it('covers failed fetch', async function () {
+        communication.axios.rejects();
+        expected = {
+          email: undefined,
+          name: undefined,
+          photo: undefined,
+          url: undefined,
+          metadata: {},
+        };
+        result = await communication.fetchProfile(urlObj);
+        assert.deepStrictEqual(result, expected);
+      });
     });
     it('covers', async function () {
+      response.data = testData.hCardMetadataHtml;
       communication.axios.resolves(response);
+      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',
+      });
       expected = {
         name: 'Thuza',
         photo: 'https://thuza.ratfeathers.com/image.png',
         url: 'https://thuza.ratfeathers.com/',
         email: undefined,
+        metadata: {
+          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',
+        },
         authorizationEndpoint: 'https://ia.squeep.com/auth',
         tokenEndpoint: 'https://ia.squeep.com/token',
+        indieauthMetadata: 'https://ia.squeep.com/meta',
       };
+
       result = await communication.fetchProfile(urlObj);
+
       assert.deepStrictEqual(result, expected);
     });
-    it('covers multiple hCards', async function () {
-      response.data = testData.multiMF2Html;
+    it('covers metadata missing fields', async function () {
+      response.data = testData.hCardMetadataHtml;
       communication.axios.resolves(response);
+      communication.fetchJSON.resolves({
+        'issuer': 'https://ia.squeep.com/',
+      });
       expected = {
-        email: undefined,
         name: 'Thuza',
         photo: 'https://thuza.ratfeathers.com/image.png',
         url: 'https://thuza.ratfeathers.com/',
-        authorizationEndpoint: 'https://ia.squeep.com/auth',
-        tokenEndpoint: 'https://ia.squeep.com/token',
+        email: undefined,
+        metadata: {
+          issuer: 'https://ia.squeep.com/',
+        },
+        indieauthMetadata: 'https://ia.squeep.com/meta',
       };
+
       result = await communication.fetchProfile(urlObj);
+
       assert.deepStrictEqual(result, expected);
     });
-    it('covers failed fetch', async function () {
-      communication.axios.rejects();
+    it('covers metadata response failure', async function () {
+      const jsonError = new Error('oh no');
+      response.data = testData.hCardMetadataHtml;
+      communication.axios
+        .onCall(0).resolves(response)
+        .onCall(1).rejects(jsonError);
+      communication.fetchJSON.restore();
       expected = {
+        name: 'Thuza',
+        photo: 'https://thuza.ratfeathers.com/image.png',
+        url: 'https://thuza.ratfeathers.com/',
         email: undefined,
-        name: undefined,
-        photo: undefined,
-        url: undefined,
+        metadata: {},
+        indieauthMetadata: 'https://ia.squeep.com/meta',
       };
+
       result = await communication.fetchProfile(urlObj);
+
       assert.deepStrictEqual(result, expected);
     });
   }); // fetchProfile
@@ -617,7 +754,7 @@ describe('Communication', function () {
     });
     it('covers', async function () {
       communication.axios.resolves({
-        data: '{"me":"https://profile.example.com/"}'
+        data: '{"me":"https://profile.example.com/"}',
       });
       expected = {
         me: 'https://profile.example.com/',