1 | "use strict";
|
2 |
|
3 | var fs = require('fs');
|
4 | var HTTP = require('http');
|
5 |
|
6 | var Parser = require('../index.js');
|
7 |
|
8 | var Expect = require('chai').expect;
|
9 |
|
10 | var IN_DIR = __dirname + '/input';
|
11 | var OUT_DIR = __dirname + '/output';
|
12 |
|
13 | describe('Parser', function() {
|
14 | var testParseForFile = function(name, ext, options, done) {
|
15 | if (typeof done === 'undefined') {
|
16 | done = options;
|
17 | options = {};
|
18 | }
|
19 | let parser = new Parser(options);
|
20 | let xml = fs.readFileSync(IN_DIR + '/' + name + '.' + ext, 'utf8');
|
21 | parser.parseString(xml, function(err, parsed) {
|
22 | if (err) console.log(err);
|
23 | Expect(err).to.equal(null);
|
24 | if (process.env.WRITE_GOLDEN) {
|
25 | fs.writeFileSync(OUT_DIR + '/' + name + '.json', JSON.stringify({feed: parsed}, null, 2));
|
26 | } else {
|
27 | var expected = fs.readFileSync(OUT_DIR + '/' + name + '.json', 'utf8')
|
28 | expected = JSON.parse(expected);
|
29 | Expect({feed: parsed}).to.deep.equal(expected);
|
30 | }
|
31 | done();
|
32 | })
|
33 | }
|
34 |
|
35 | it('should parse Reddit', function(done) {
|
36 | testParseForFile('reddit', 'rss', done);
|
37 | })
|
38 |
|
39 | it('should parse sciencemag.org (RSS 1.0)', function(done) {
|
40 | testParseForFile('rss-1', 'rss', done);
|
41 | })
|
42 |
|
43 | it('should parse craigslist (RSS 1.0)', function(done) {
|
44 | testParseForFile('craigslist', 'rss', done);
|
45 | })
|
46 |
|
47 | it('should parse atom', function(done) {
|
48 | testParseForFile('reddit-atom', 'rss', done);
|
49 | })
|
50 |
|
51 | it('should parse atom feed', function(done) {
|
52 | testParseForFile('gulp-atom', 'atom', done);
|
53 | })
|
54 |
|
55 | it('should parse reddits new feed', function(done) {
|
56 | testParseForFile('reddit-home', 'rss', done);
|
57 | })
|
58 |
|
59 | it('should parse with missing fields', function(done) {
|
60 | testParseForFile('missing-fields', 'atom', done)
|
61 | })
|
62 |
|
63 | it('should parse heise', function(done) {
|
64 | testParseForFile('heise', 'atom', done);
|
65 | })
|
66 |
|
67 | it('should parse heraldsun', function(done) {
|
68 | testParseForFile('heraldsun', 'rss', done);
|
69 | });
|
70 |
|
71 | it('should parse UOL Noticias', function(done) {
|
72 | testParseForFile('uolNoticias', 'rss', { defaultRSS: 2.0 }, done);
|
73 | });
|
74 |
|
75 | it('should NOT parse UOL Noticias, if no default RSS is provided', function(done) {
|
76 | function willFail() {
|
77 | testParseForFile('uolNoticias', 'rss', done);
|
78 | }
|
79 | Expect(willFail).to.throw;
|
80 | done();
|
81 | });
|
82 |
|
83 | it('should parse Instant Article', function(done) {
|
84 | testParseForFile('instant-article', 'rss', done);
|
85 | });
|
86 |
|
87 | it('should parse Feedburner', function(done) {
|
88 | testParseForFile('feedburner', 'atom', done);
|
89 | });
|
90 |
|
91 | it('should parse podcasts', function(done) {
|
92 | testParseForFile('narro', 'rss', done);
|
93 | });
|
94 |
|
95 | it('should parse multiple links', function(done) {
|
96 | testParseForFile('many-links', 'rss', done);
|
97 | });
|
98 |
|
99 | it('should pass xml2js options', function(done) {
|
100 | testParseForFile('xml2js-options', 'rss', {xml2js: {emptyTag: 'EMPTY'}}, done);
|
101 | });
|
102 |
|
103 | it('should throw error for unrecognized', function(done) {
|
104 | let parser = new Parser();
|
105 | let xml = fs.readFileSync(__dirname + '/input/unrecognized.rss', 'utf8');
|
106 | parser.parseString(xml, function(err, parsed) {
|
107 | Expect(err.message).to.contain('Feed not recognized as RSS');
|
108 | done();
|
109 | });
|
110 | });
|
111 |
|
112 | it('should omit iTunes image if none available during decoration', function(done) {
|
113 | const rssFeedWithMissingImage = __dirname + '/input/itunes-missing-image.rss';
|
114 | const xml = fs.readFileSync(rssFeedWithMissingImage, 'utf8');
|
115 | let parser = new Parser();
|
116 | parser.parseString(xml, function(err, parsed) {
|
117 | Expect(err).to.be.null;
|
118 | Expect(parsed).to.not.have.deep.property('feed.itunes.image');
|
119 | done();
|
120 | });
|
121 | });
|
122 |
|
123 | it('should parse custom fields', function(done) {
|
124 | var options = {
|
125 | customFields: {
|
126 | feed: ['language', 'copyright', 'nested-field'],
|
127 | item: ['subtitle']
|
128 | }
|
129 | };
|
130 | testParseForFile('customfields', 'rss', options, done);
|
131 | });
|
132 |
|
133 | it('should parse Atom feed custom fields', function(done) {
|
134 | var options = {
|
135 | customFields: {
|
136 | feed: ['totalViews'],
|
137 | item: ['media:group']
|
138 | }
|
139 | };
|
140 | testParseForFile('atom-customfields', 'atom', options, done);
|
141 | });
|
142 |
|
143 | it('should parse sibling custom fields', function(done) {
|
144 | var options = {
|
145 | customFields: {
|
146 | item: [['media:content', 'media:content', {keepArray: true}]]
|
147 | }
|
148 | };
|
149 | testParseForFile('guardian', 'rss', options, done);
|
150 | });
|
151 |
|
152 | it('should parse URL', function(done) {
|
153 | var INPUT_FILE = __dirname + '/input/reddit.rss';
|
154 | var OUTPUT_FILE = __dirname + '/output/reddit.json';
|
155 | var server = HTTP.createServer(function(req, res) {
|
156 | var file = fs.createReadStream(INPUT_FILE, 'utf8');
|
157 | file.pipe(res);
|
158 | });
|
159 | server.listen(function() {
|
160 | var port = server.address().port;
|
161 | var url = 'http://localhost:' + port;
|
162 | let parser = new Parser();
|
163 | parser.parseURL(url, function(err, parsed) {
|
164 | Expect(err).to.equal(null);
|
165 | if (process.env.WRITE_GOLDEN) {
|
166 | fs.writeFileSync(OUTPUT_FILE, JSON.stringify({feed: parsed}, null, 2));
|
167 | } else {
|
168 | var expected = JSON.parse(fs.readFileSync(OUTPUT_FILE, 'utf8'));
|
169 | Expect({feed: parsed}).to.deep.equal(expected);
|
170 | }
|
171 | server.close();
|
172 | done();
|
173 | });
|
174 | });
|
175 | });
|
176 |
|
177 | it('should use proper encoding', function(done) {
|
178 | var INPUT_FILE = __dirname + '/input/encoding.rss';
|
179 | var OUTPUT_FILE = __dirname + '/output/encoding.json';
|
180 | var ENCODING = 'latin1';
|
181 | var server = HTTP.createServer(function(req, res) {
|
182 | res.setHeader('Content-Type', 'text/xml; charset=' + ENCODING)
|
183 | var file = fs.readFileSync(INPUT_FILE, ENCODING);
|
184 | res.end(file, ENCODING);
|
185 | });
|
186 | server.listen(function() {
|
187 | var port = server.address().port;
|
188 | var url = 'http://localhost:' + port;
|
189 | var parser = new Parser();
|
190 | parser.parseURL(url, function(err, parsed) {
|
191 | Expect(err).to.equal(null);
|
192 | if (process.env.WRITE_GOLDEN) {
|
193 | fs.writeFileSync(OUTPUT_FILE, JSON.stringify({feed: parsed}, null, 2), {encoding: ENCODING});
|
194 | } else {
|
195 | var expected = JSON.parse(fs.readFileSync(OUTPUT_FILE, ENCODING));
|
196 | Expect({feed: parsed}).to.deep.equal(expected);
|
197 | }
|
198 | server.close();
|
199 | done();
|
200 | })
|
201 | })
|
202 | });
|
203 |
|
204 | it('should respect timeout option', function(done) {
|
205 | var INPUT_FILE = __dirname + '/input/encoding.rss';
|
206 | var OUTPUT_FILE = __dirname + '/output/encoding.json';
|
207 | var ENCODING = 'latin1';
|
208 | var server = HTTP.createServer(function(req, res) {});
|
209 | server.listen(function() {
|
210 | var port = server.address().port;
|
211 | var url = 'http://localhost:' + port;
|
212 | var parser = new Parser({timeout: 1});
|
213 | parser.parseURL(url, function(err, parsed) {
|
214 | Expect(err).to.not.equal(null);
|
215 | Expect(err.message).to.equal("Request timed out after 1ms");
|
216 | done();
|
217 | });
|
218 | });
|
219 | });
|
220 | })
|