Initial release
[websub-hub] / test / src / link-helper.js
1 /* eslint-env mocha */
2 'use strict';
3
4 const assert = require('assert');
5 const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
6 const LinkHelper = require('../../src/link-helper');
7 const stubLogger = require('../stub-logger');
8 const testData = require('../test-data/link-helper');
9
10 describe('LinkHelper', function () {
11 let lh, options;
12 beforeEach(function () {
13 options = {
14 dingus: {
15 selfBaseUrl: 'https://example.com/hub/',
16 },
17 };
18 lh = new LinkHelper(stubLogger, options);
19 });
20 afterEach(function () {
21 sinon.restore();
22 });
23 describe('validHub', function () {
24 let url, headers, body;
25 beforeEach(function () {
26 url = 'https://example.com/feed/';
27 headers = {};
28 body = '';
29 });
30 it('covers success', async function () {
31 headers = {
32 link: '<https://example.com/hub/>; rel="hub"',
33 };
34 const expected = true;
35 const result = await lh.validHub(url, headers, body);
36 assert.strictEqual(result, expected);
37 });
38 it('covers wrong hub', async function () {
39 headers = {
40 link: '<https://example.com/other/hub/>; rel="hub"',
41 };
42 const expected = false;
43 const result = await lh.validHub(url, headers, body);
44 assert.strictEqual(result, expected);
45 });
46 it('covers link in Atom body', async function () {
47 headers = {
48 'content-type': 'application/xml',
49 };
50 body = testData.atomFeedBody;
51 url = testData.atomFeedUrl;
52 lh.selfUrl = 'https://hub.squeep.com/';
53 const expected = true;
54 const result = await lh.validHub(url, headers, body);
55 assert.strictEqual(result, expected);
56 });
57 it('covers link in HTML body', async function () {
58 headers = {
59 'content-type': 'text/html',
60 };
61 body = '<html><head><link rel="hub" href="https://example.com/hub/"></head></html>';
62 const expected = true;
63 const result = await lh.validHub(url, headers, body);
64 assert.strictEqual(result, expected);
65 });
66 it('covers parser failure', async function () {
67 headers = {
68 link: 'Invalid Link Header',
69 };
70 const expected = false;
71 const result = await lh.validHub(url, headers, body);
72 assert.strictEqual(result, expected);
73 });
74 it('covers other failure', async function () {
75 const expected = false;
76 const result = await lh.validHub(url, headers, body);
77 assert.strictEqual(result, expected);
78 });
79 }); // validHub
80
81 describe('absoluteURI', function () {
82 it('success', function () {
83 const uri = '../rel';
84 const context = 'https://example.com/base/';
85 const expected = 'https://example.com/rel';
86 const result = lh.absoluteURI(uri, context);
87 assert.strictEqual(result, expected);
88 });
89 it('failure', function () {
90 const uri = '../rel';
91 const context = '/not/valid';
92 const expected = '../rel';
93 const result = lh.absoluteURI(uri, context);
94 assert.strictEqual(result, expected);
95 });
96 }); // absoluteURI
97
98 describe('locateHubTargets', function () {
99 it('covers', function () {
100 const links = [
101 {
102 target: 'https://example.com/hub1/',
103 attributes: [
104 {
105 name: 'rel',
106 value: 'hub',
107 },
108 ],
109 },
110 {
111 target: 'https://example.com/index',
112 attributes: [
113 {
114 name: 'rel',
115 value: 'index',
116 },
117 ],
118 },
119 {
120 target: 'https://example.com/hub2/',
121 attributes: [
122 {
123 name: 'rel',
124 value: 'hub other',
125 },
126 ],
127 },
128 ];
129 const expected = ['https://example.com/hub1/', 'https://example.com/hub2/'];
130 const result = LinkHelper.locateHubTargets(links);
131 assert.deepStrictEqual(result, expected);
132 });
133 }); // locateHubTargets
134
135 describe('linksFromFeedBody', function () {
136 it('parses rss', async function () {
137 const feedData = testData.rssFeedBody;
138 const feedUrl = testData.rssFeedUrl;
139 const expected = [
140 {
141 attributes: [
142 {
143 name: 'rel',
144 value: 'self',
145 },
146 {
147 name: 'type',
148 value: 'application/rss+xml',
149 },
150 ],
151 target: 'https://puppetcircuits.wordpress.com/feed/',
152 },
153 {
154 attributes: [
155 {
156 name: 'rel',
157 value: 'search',
158 },
159 {
160 name: 'type',
161 value: 'application/opensearchdescription+xml',
162 },
163 {
164 name: 'title',
165 value: 'Puppet Circuits',
166 },
167 ],
168 target: 'https://puppetcircuits.wordpress.com/osd.xml',
169 },
170 {
171 attributes: [
172 {
173 name: 'rel',
174 value: 'hub',
175 },
176 ],
177 target: 'https://puppetcircuits.wordpress.com/?pushpress=hub',
178 },
179 ];
180 const result = await lh.linksFromFeedBody(feedUrl, feedData);
181 assert.deepStrictEqual(result, expected);
182 });
183 it('parses atom', async function () {
184 const feedData = testData.atomFeedBody;
185 const feedUrl = testData.atomFeedUrl;
186 const expected = [
187 {
188 attributes: [
189 {
190 name: 'rel',
191 value: 'alternate',
192 },
193 {
194 name: 'type',
195 value: 'text/xhtml',
196 },
197 ],
198 target: 'https://squeep.com/eats/',
199 },
200 {
201 attributes: [
202 {
203 name: 'rel',
204 value: 'self',
205 },
206 {
207 name: 'type',
208 value: 'application/atom+xml',
209 },
210 ],
211 target: 'https://squeep.com/eats/atom/',
212 },
213 {
214 attributes: [
215 {
216 name: 'rel',
217 value: 'hub',
218 },
219 ],
220 target: 'https://hub.squeep.com/',
221 },
222 ];
223 const result = await lh.linksFromFeedBody(feedUrl, feedData);
224 assert.deepStrictEqual(result, expected);
225 });
226 it('does not parse HTML', async function () {
227 const feedData = testData.htmlBody;
228 const feedUrl = testData.htmlUrl;
229 const expected = [];
230 const result = await lh.linksFromFeedBody(feedUrl, feedData);
231 assert.deepStrictEqual(result, expected);
232 });
233 }); // hubLinksFromFeedBody
234
235 describe('linksFromHTMLBody', function () {
236 it('parses HTML', function () {
237 const htmlData = testData.htmlBody;
238 const expected = [
239 {
240 attributes: [
241 {
242 name: 'rel',
243 value: 'preload',
244 },
245 {
246 name: 'as',
247 value: 'font',
248 },
249 {
250 name: 'type',
251 value: 'font/opentype',
252 },
253 {
254 name: 'crossorigin',
255 value: 'anonymous',
256 },
257 ],
258 target: 'oldstyle.otf',
259 },
260 {
261 attributes: [
262 {
263 name: 'rel',
264 value: 'stylesheet',
265 },
266 {
267 name: 'type',
268 value: 'text/css',
269 },
270 ],
271 target: 'eats.css',
272 },
273 {
274 attributes: [
275 {
276 name: 'rel',
277 value: 'hub',
278 },
279 ],
280 target: 'https://hub.squeep.com/',
281 },
282 {
283 attributes: [
284 {
285 name: 'rel',
286 value: 'alternate',
287 },
288 {
289 name: 'type',
290 value: 'application/atom+xml',
291 },
292 {
293 name: 'title',
294 value: 'Atom 1.0',
295 },
296 ],
297 target: 'https://squeep.com/eats/atom/',
298 },
299 ];
300 const result = lh.linksFromHTMLBody(htmlData);
301 assert.deepStrictEqual(result, expected);
302 });
303 }); // linksFromHTMLBody
304
305 }); // LinkHelper