+ 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),
+ body: testData.hCardHtml,
+ };
+ });
+ it('covers', async function () {
+ communication.got.resolves(response);
+ expected = { foo: 'bar', baz: 123 };
+ response.body = expected;
+
+ result = await communication.fetchJSON(urlObj);
+ assert.deepStrictEqual(result, expected);
+ });
+ it('covers got error', async function () {
+ communication.got.rejects(new Error('blah'));
+ expected = undefined;
+
+ result = await communication.fetchJSON(urlObj);
+
+ assert.deepStrictEqual(result, expected);
+ });
+ it('covers non-parsable content', async function () {
+ response.body = 'some bare text';
+ response.headers = {};
+ const error = new Error('oh no');
+ response.request = { options: { url: new URL('https://example.com/') } };
+ communication.got.rejects(new communication.Got.ParseError(error, response));
+ expected = undefined;
+
+ result = await communication.fetchJSON(urlObj);
+
+ assert.deepStrictEqual(result, expected);
+ });
+ }); // fetchJSON
+
+ describe('validateProfile', function () {
+ let url, validationOptions;
+ beforeEach(function () {
+ url = 'https://example.com/';
+ validationOptions = {};
+ sinon.stub(dns.promises, 'lookup').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/';
+ validationOptions = {};
+ sinon.stub(dns.promises, 'lookup').resolves([{ family: 4, address: '10.11.12.13' }]);
+ });
+ it('rejects invalid url', async function () {
+ await assert.rejects(() => communication.validateClientIdentifier('bad url'), ValidationError);
+ });
+ it('rejects invalid scheme', async function () {
+ url = 'ftp://example.com/';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects fragment', async function () {
+ url = 'https://example.com/#foo';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects username', async function () {
+ url = 'https://user@example.com/';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects password', async function () {
+ url = 'https://:foo@example.com/';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects relative path', async function () {
+ url = 'https://example.com/client/../sneaky';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects ipv4', async function () {
+ url = 'https://10.11.12.13/';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects ipv6', async function () {
+ url = 'https://[fd64:defa:00e5:caf4:0dff::ad39]/';
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), 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.promises.lookup.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.promises.lookup.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.promises.lookup.rejects(new Error('oh no'));
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('rejects mismatched resolutions', async function () {
+ dns.promises.lookup.onCall(1).resolves([{ family: 4, address: '10.9.8.7' }]);
+ await assert.rejects(() => communication.validateClientIdentifier(url, validationOptions), ValidationError);
+ });
+ it('ignores unknown dns family', async function () {
+ dns.promises.lookup.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.promises.lookup.resolves();
+ const result = await communication.validateClientIdentifier(url, validationOptions);
+ assert.strictEqual(result.isLoopback, false);
+ });
+ }); // validateClientIdentifier
+