X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Flib%2Fcommunication.js;fp=test%2Flib%2Fcommunication.js;h=f544d80f67304ce8e47468623368b635e487e1a7;hb=cf9590ecbcd4b0a7c01f153cacade619518f84f0;hp=5c41469db57a763c3fc202cb769c77b5566e1e3b;hpb=cbc34a48ad25784a42673faa7c48067c4bfa10a2;p=squeep-indieauth-helper diff --git a/test/lib/communication.js b/test/lib/communication.js index 5c41469..f544d80 100644 --- a/test/lib/communication.js +++ b/test/lib/communication.js @@ -7,6 +7,8 @@ const assert = require('assert'); const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require const Communication = require('../../lib/communication'); +const { ValidationError } = require('../../lib/errors'); +const dns = require('dns'); const stubLogger = require('../stub-logger'); const testData = require('../test-data/communication'); @@ -516,6 +518,165 @@ describe('Communication', function () { }); }); // fetchJSON + describe('validateProfile', function () { + let url, validationOptions; + beforeEach(function () { + url = 'https://example.com/'; + options = {}; + sinon.stub(dns, 'lookupAsync').resolves([{ family: 4, address: '10.11.12.14' }]); + }); + it('rejects invalid url', async function () { + url = 'bad url'; + await assert.rejects(() => communication.validateProfile(url, validationOptions), ValidationError); + }); + it('covers success', async function () { + const result = await communication.validateProfile(url, validationOptions); + assert.strictEqual(result.isLoopback, false); + }); + it('rejects invalid', async function () { + url = 'ftp://example.com/'; + await assert.rejects(() => communication.validateProfile(url, validationOptions), ValidationError); + }); + + }); // validateProfile + + describe('validateClientIdentifier', function () { + let url, validationOptions; + beforeEach(function () { + url = 'https://example.com/'; + options = {}; + 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); + } + }); + 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); + } + }); + 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); + } + }); + 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); + } + }); + 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); + } + }); + 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); + } + }); + 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); + } + }); + 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); + } + }); + it('accepts ipv4 loopback', async function () { + url = 'https://127.0.0.1/'; + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, true); + }); + it('accepts ipv6 loopback', async function () { + url = 'https://[::1]/'; + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, true); + }); + it('accepts resolved ipv4 loopback', async function () { + dns.lookupAsync.resolves([{ family: 4, address: '127.0.0.1' }]); + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, true); + }); + it('accepts resolved ipv6 loopback', async function () { + dns.lookupAsync.resolves([{ family: 6, address: '::1' }]); + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, true); + }); + it('covers success', async function () { + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, false); + }); + 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); + } + }); + 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); + } + }); + it('ignores unknown dns family', async function () { + dns.lookupAsync.resolves([{ family: 5, address: '10.9.8.7' }]); + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, false); + }); + it('covers rooted hostname', async function() { + url = 'https://example.com./'; + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, false); + }); + it('covers unresolved', async function () { + dns.lookupAsync.resolves(); + const result = await communication.validateClientIdentifier(url, validationOptions); + assert.strictEqual(result.isLoopback, false); + }); + }); // validateClientIdentifier + describe('fetchClientIdentifier', function () { let expected, response, result, urlObj; beforeEach(function () { @@ -592,6 +753,17 @@ describe('Communication', function () { result = await communication.fetchClientIdentifier(urlObj); assert.deepStrictEqual(result, expected); }); + it('covers loopback', async function () { + sinon.spy(communication, 'fetchMicroformat'); + urlObj.isLoopback = true; + expected = { + rels: {}, + items: [], + }; + result = await communication.fetchClientIdentifier(urlObj); + assert.deepStrictEqual(result, expected); + assert(communication.fetchMicroformat.notCalled); + }); }); // fetchClientIdentifier describe('fetchProfile', function () {