1 | const { toXML } = require('./dist/jstoxml');
|
2 | const assert = require('assert');
|
3 |
|
4 | describe('toXML', () => {
|
5 | describe('primitives', () => {
|
6 | const vals = [
|
7 | 'foo',
|
8 | false,
|
9 | true,
|
10 | 4,
|
11 | 4.56
|
12 | ];
|
13 |
|
14 | vals.forEach(val => {
|
15 | it(`outputs ${val}`, () => {
|
16 | const result = toXML(val);
|
17 | const expectedResult = `${val}`;
|
18 | assert.equal(result, expectedResult);
|
19 | });
|
20 | });
|
21 | });
|
22 |
|
23 | describe('functions', () => {
|
24 | describe('primitive outputs', () => {
|
25 | const vals = [
|
26 | 999,
|
27 | 'foo',
|
28 | false,
|
29 | true
|
30 | ];
|
31 |
|
32 | vals.forEach((val) => {
|
33 | it(`${val}`, () => {
|
34 | const result = toXML(() => val);
|
35 | const expectedResult = `${val}`;
|
36 | assert.equal(result, expectedResult);
|
37 | });
|
38 | });
|
39 | });
|
40 |
|
41 | it('fat arrow', () => {
|
42 | const val = 888;
|
43 | const result = toXML(() => val);
|
44 | const expectedResult = val;
|
45 | assert.equal(result, expectedResult);
|
46 | });
|
47 |
|
48 | it('accessing config within function', () => {
|
49 | const val = {
|
50 | foo: {
|
51 | depth: config => config.depth
|
52 | }
|
53 | };
|
54 | const result = toXML(val);
|
55 | const expectedResult = '<foo><depth>2</depth></foo>';
|
56 | assert.equal(result, expectedResult);
|
57 | });
|
58 |
|
59 | it('converts nonprimitive output', () => {
|
60 | const val = { foo: 'bar' };
|
61 | const result = toXML(() => val);
|
62 | const expectedResult = '<foo>bar</foo>';
|
63 | assert.equal(result, expectedResult);
|
64 | });
|
65 |
|
66 | it('converts nested nonprimitive output', () => {
|
67 | const val = { foo: { bar: { baz: 2 } } };
|
68 | const result = toXML(() => val);
|
69 | const expectedResult = '<foo><bar><baz>2</baz></bar></foo>';
|
70 | assert.equal(result, expectedResult);
|
71 | });
|
72 |
|
73 | it('converts nested nonprimitive output with indent', () => {
|
74 | const val = { foo: { bar: { baz: 2 } } };
|
75 | const config = { indent: ' ' };
|
76 | const result = toXML(() => val, config);
|
77 | const expectedResult = '<foo>\n <bar>\n <baz>2</baz>\n </bar>\n</foo>';
|
78 | assert.equal(result, expectedResult);
|
79 | });
|
80 | });
|
81 |
|
82 | describe('github issues', () => {
|
83 | it('issue 3', () => {
|
84 | const val = {
|
85 | foo: true,
|
86 | bar: '',
|
87 | foo2: false,
|
88 | ok: 'This is ok',
|
89 | ok2: 'false',
|
90 | ok3: 'true'
|
91 | };
|
92 | const result = toXML(val);
|
93 | const expectedResult = '<foo>true</foo><bar/><foo2>false</foo2><ok>This is ok</ok><ok2>false</ok2><ok3>true</ok3>';
|
94 | assert.equal(result, expectedResult);
|
95 | });
|
96 |
|
97 | it('issue 4a', () => {
|
98 | const val = {
|
99 | foo: 4,
|
100 | bar: '&'
|
101 | };
|
102 | const result = toXML(val);
|
103 | const expectedResult = '<foo>4</foo><bar>&</bar>';
|
104 | assert.equal(result, expectedResult);
|
105 | });
|
106 |
|
107 | it('issue 4b', () => {
|
108 | const val = {
|
109 | foo: '&'
|
110 | };
|
111 | const config = {
|
112 | filter: {
|
113 | '&': '&'
|
114 | }
|
115 | };
|
116 | const result = toXML(val, config);
|
117 | const expectedResult = '<foo>&</foo>';
|
118 | assert.equal(result, expectedResult);
|
119 | });
|
120 | });
|
121 |
|
122 | describe('arrays', () => {
|
123 | it('1', () => {
|
124 | const val = [
|
125 | { foo: 'bar' },
|
126 | { foo: 'baz' },
|
127 | { foo2: 'bar2' }
|
128 | ];
|
129 | const result = toXML(val);
|
130 | const expectedResult = '<foo>bar</foo><foo>baz</foo><foo2>bar2</foo2>';
|
131 | assert.equal(result, expectedResult);
|
132 | });
|
133 |
|
134 | it('attributes in subobject', () => {
|
135 | const val = [
|
136 | { foo: 'bar' },
|
137 | { foo: 'baz' },
|
138 | { foo: undefined },
|
139 | { foo: '' },
|
140 | { foo: null },
|
141 | {
|
142 | _name: 'foo',
|
143 | _content: 'bar',
|
144 | _attrs: {
|
145 | a: 'b',
|
146 | c: 'd'
|
147 | }
|
148 | }
|
149 | ];
|
150 | const result = toXML(val);
|
151 | const expectedResult = '<foo>bar</foo><foo>baz</foo><foo/><foo/>foo<foo a="b" c="d">bar</foo>';
|
152 | assert.equal(result, expectedResult);
|
153 | });
|
154 |
|
155 | it('nesting with indent', () => {
|
156 | const val = {
|
157 | foo: [
|
158 | { foo: 'bar' },
|
159 | { foo: 'baz' },
|
160 | { foo2: 'bar2' }
|
161 | ]
|
162 | };
|
163 | const config = { indent: ' ' };
|
164 | const result = toXML(val, config);
|
165 | const expectedResult = `<foo>
|
166 | <foo>bar</foo>
|
167 | <foo>baz</foo>
|
168 | <foo2>bar2</foo2>
|
169 | </foo>`;
|
170 | assert.equal(result, expectedResult);
|
171 | });
|
172 | });
|
173 |
|
174 | describe('special-objects', () => {
|
175 | it('1', () => {
|
176 | const val = {
|
177 | _name: 'foo',
|
178 | _content: 'bar',
|
179 | _attrs: {
|
180 | a: 1,
|
181 | b: 2
|
182 | }
|
183 | };
|
184 | const result = toXML(val);
|
185 | const expectedResult = '<foo a="1" b="2">bar</foo>';
|
186 | assert.equal(result, expectedResult);
|
187 | });
|
188 |
|
189 | it('2', () => {
|
190 | const val = {
|
191 | _name: 'foo',
|
192 | _content: {
|
193 | foo: 'bar'
|
194 | },
|
195 | _attrs: {
|
196 | a: 1,
|
197 | b: 2
|
198 | }
|
199 | };
|
200 | const result = toXML(val);
|
201 | const expectedResult = '<foo a="1" b="2"><foo>bar</foo></foo>';
|
202 | assert.equal(result, expectedResult);
|
203 | });
|
204 |
|
205 | it('3', () => {
|
206 | const val = {
|
207 | _name: 'foo',
|
208 | _content: () => 1 + 2,
|
209 | _attrs: {
|
210 | a: 1,
|
211 | b: 2
|
212 | }
|
213 | };
|
214 | const result = toXML(val);
|
215 | const expectedResult = '<foo a="1" b="2">3</foo>';
|
216 | assert.equal(result, expectedResult);
|
217 | });
|
218 | });
|
219 |
|
220 | describe('objects', () => {
|
221 | it('1', () => {
|
222 | const val = {
|
223 | foo: 'bar',
|
224 | foo2: 'bar2'
|
225 | };
|
226 | const result = toXML(val);
|
227 | const expectedResult = '<foo>bar</foo><foo2>bar2</foo2>';
|
228 | assert.equal(result, expectedResult);
|
229 | });
|
230 |
|
231 | it('attributes', () => {
|
232 | const val = {
|
233 | _name: 'a',
|
234 | _attrs: {
|
235 | foo: 'bar',
|
236 | foo2: 'bar2'
|
237 | }
|
238 | };
|
239 | const result = toXML(val);
|
240 | const expectedResult = '<a foo="bar" foo2="bar2"/>';
|
241 | assert.equal(result, expectedResult);
|
242 | });
|
243 |
|
244 | it('attributes 2', () => {
|
245 | const val = {
|
246 | _name: 'a',
|
247 | _attrs: {
|
248 | foo: 'bar',
|
249 | foo2: 'bar2'
|
250 | },
|
251 | _content: 'la dee da'
|
252 | };
|
253 | const result = toXML(val);
|
254 | const expectedResult = '<a foo="bar" foo2="bar2">la dee da</a>';
|
255 | assert.equal(result, expectedResult);
|
256 | });
|
257 |
|
258 | it('attributes nesting', () => {
|
259 | const val = {
|
260 | _name: 'foo',
|
261 | _attrs: {
|
262 | a: 'b'
|
263 | },
|
264 | _content: {
|
265 | _name: 'bar',
|
266 | _attrs: {
|
267 | c: 'd'
|
268 | }
|
269 | }
|
270 | };
|
271 | const result = toXML(val);
|
272 | const expectedResult = '<foo a="b"><bar c="d"/></foo>';
|
273 | assert.equal(result, expectedResult);
|
274 | });
|
275 | it('with mixed content', () => {
|
276 | const val = {
|
277 | blah: null,
|
278 | foo: 'bar',
|
279 | 'more blah': null,
|
280 | bar: 0,
|
281 | 'more more blah': null,
|
282 | baz: false
|
283 | };
|
284 | const result = toXML(val);
|
285 | const expectedResult =
|
286 | 'blah<foo>bar</foo>more blah<bar>0</bar>more more blah<baz>false</baz>';
|
287 | assert.equal(result, expectedResult);
|
288 | });
|
289 |
|
290 | it('nesting with indent', () => {
|
291 | const val = {
|
292 | foo: {
|
293 | foo: 'bar',
|
294 | foo2: 'bar2'
|
295 | }
|
296 | };
|
297 | const config = { indent: ' ' };
|
298 | const result = toXML(val, config);
|
299 | const expectedResult = `<foo>
|
300 | <foo>bar</foo>
|
301 | <foo2>bar2</foo2>
|
302 | </foo>`;
|
303 | assert.equal(result, expectedResult);
|
304 | });
|
305 |
|
306 | it('deep nesting', () => {
|
307 | const val = {
|
308 | a: {
|
309 | b: {
|
310 | c: {
|
311 | d: {
|
312 | e: {
|
313 | f: {
|
314 | g: {
|
315 | h: {
|
316 | i: {
|
317 | j: {
|
318 | k: {
|
319 | l: {
|
320 | m: {
|
321 | foo: 'bar'
|
322 | }
|
323 | }
|
324 | }
|
325 | }
|
326 | }
|
327 | }
|
328 | }
|
329 | }
|
330 | }
|
331 | }
|
332 | }
|
333 | }
|
334 | }
|
335 | };
|
336 | const result = toXML(val);
|
337 | const expectedResult = '<a><b><c><d><e><f><g><h><i><j><k><l><m><foo>bar</foo></m></l></k></j></i></h></g></f></e></d></c></b></a>';
|
338 | assert.equal(result, expectedResult);
|
339 | });
|
340 | });
|
341 |
|
342 | describe('header', () => {
|
343 | it('default header', () => {
|
344 | const val = {
|
345 | foo: 'bar'
|
346 | };
|
347 | const config = {
|
348 | header: true
|
349 | };
|
350 | const result = toXML(val, config);
|
351 | const expectedResult = '<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>';
|
352 | assert.equal(result, expectedResult);
|
353 | });
|
354 |
|
355 | it('no header', () => {
|
356 | const val = {
|
357 | foo: 'bar'
|
358 | };
|
359 | const config = {
|
360 | header: false
|
361 | };
|
362 | const result = toXML(val, config);
|
363 | const expectedResult = '<foo>bar</foo>';
|
364 | assert.equal(result, expectedResult);
|
365 | });
|
366 |
|
367 | it('no header by default', () => {
|
368 | const val = {
|
369 | foo: 'bar'
|
370 | };
|
371 | const result = toXML(val);
|
372 | const expectedResult = '<foo>bar</foo>';
|
373 | assert.equal(result, expectedResult);
|
374 | });
|
375 |
|
376 | it('default header with indent', () => {
|
377 | const val = {
|
378 | foo: 'bar'
|
379 | };
|
380 | const config = {
|
381 | header: true,
|
382 | indent: ' '
|
383 | };
|
384 | const result = toXML(val, config);
|
385 | const expectedResult = '<?xml version="1.0" encoding="UTF-8"?>\n<foo>bar</foo>';
|
386 | assert.equal(result, expectedResult);
|
387 | });
|
388 |
|
389 | it('custom header', () => {
|
390 | const val = {
|
391 | foo: 'bar'
|
392 | };
|
393 | const config = {
|
394 | header: '<?FOO BAR="123" BAZ="XX"?>'
|
395 | };
|
396 | const result = toXML(val, config);
|
397 | const expectedResult = '<?FOO BAR="123" BAZ="XX"?><foo>bar</foo>';
|
398 | assert.equal(result, expectedResult);
|
399 | });
|
400 | });
|
401 |
|
402 | describe('filtering', () => {
|
403 | it('values', () => {
|
404 | const val = {
|
405 | foo: '<a>',
|
406 | bar: '"b"',
|
407 | baz: '\'&whee\''
|
408 | };
|
409 | const config = {
|
410 | filter: {
|
411 | '<': '<',
|
412 | '>': '>',
|
413 | '"': '"',
|
414 | '\'': ''',
|
415 | '&': '&'
|
416 | }
|
417 | };
|
418 | const result = toXML(val, config);
|
419 | const expectedResult =
|
420 | '<foo><a></foo><bar>"b"</bar><baz>'&whee'</baz>';
|
421 | assert.equal(result, expectedResult);
|
422 | });
|
423 |
|
424 | it('attributes', () => {
|
425 | const val = {
|
426 | _name: 'foo',
|
427 | _attrs: { a: '<"\'&"foo>' }
|
428 | };
|
429 | const config = {
|
430 | attributesFilter: {
|
431 | '<': '<',
|
432 | '>': '>',
|
433 | '"': '"',
|
434 | '\'': ''',
|
435 | '&': '&'
|
436 | }
|
437 | };
|
438 | const result = toXML(val, config);
|
439 | const expectedResult = '<foo a="<"'&"foo>"/>';
|
440 | assert.equal(result, expectedResult);
|
441 | });
|
442 | });
|
443 |
|
444 | describe('misc', () => {
|
445 | it('outputs <_content> if it has no tag name', () => {
|
446 | const val = {
|
447 | _content: 'foo'
|
448 | };
|
449 | const result = toXML(val);
|
450 | const expectedResult = '<_content>foo</_content>';
|
451 | assert.equal(result, expectedResult);
|
452 | });
|
453 |
|
454 | it('outputs emoji attributes', () => {
|
455 | const val = {
|
456 | html: {
|
457 | _attrs: [
|
458 | { '⚡': true },
|
459 | { lang: 'en' },
|
460 | { lang: 'klingon' }
|
461 | ]
|
462 | }
|
463 | };
|
464 | const result = toXML(val);
|
465 | const expectedResult = '<html ⚡ lang="en" lang="klingon"/>';
|
466 | assert.equal(result, expectedResult);
|
467 | });
|
468 |
|
469 | it('does not force self close if tag has content', () => {
|
470 | const val = {
|
471 | _name: 'foo',
|
472 | _selfCloseTag: true,
|
473 | _content: 'bar'
|
474 | };
|
475 | const result = toXML(val);
|
476 | const expectedResult = '<foo>bar</foo>';
|
477 | assert.equal(result, expectedResult);
|
478 | });
|
479 |
|
480 | it('nested elements with self-closing sibling', () => {
|
481 | const val = {
|
482 | people: {
|
483 | students: [
|
484 | {
|
485 | student: { name: 'Joe' }
|
486 | },
|
487 | {
|
488 | student: { name: 'Jane' }
|
489 | }
|
490 | ],
|
491 | teacher: {
|
492 | _selfCloseTag: true,
|
493 | _attrs: {
|
494 | name: 'Yoda'
|
495 | }
|
496 | }
|
497 | }
|
498 | };
|
499 | const result = toXML(val);
|
500 | const expectedResult = '<people><students><student><name>Joe</name></student><student><name>Jane</name></student></students><teacher name="Yoda"/></people>';
|
501 | assert.equal(result, expectedResult);
|
502 | });
|
503 |
|
504 | it('sibling _content tag', () => {
|
505 | const val = {
|
506 | foo: {
|
507 | bar: 'baz',
|
508 | _content: {
|
509 | bar2: 'baz2'
|
510 | }
|
511 | }
|
512 | };
|
513 | const result = toXML(val);
|
514 | const expectedResult = '<foo><bar>baz</bar><bar2>baz2</bar2></foo>';
|
515 | assert.equal(result, expectedResult);
|
516 | });
|
517 | });
|
518 |
|
519 | describe('examples', () => {
|
520 | it('1 simple object', () => {
|
521 | const val = {
|
522 | foo: 'bar',
|
523 | foo2: 'bar2'
|
524 | };
|
525 | const result = toXML(val);
|
526 | const expectedResult = '<foo>bar</foo><foo2>bar2</foo2>';
|
527 | assert.equal(result, expectedResult);
|
528 | });
|
529 |
|
530 | it('2 simple array', () => {
|
531 | const val = [
|
532 | { foo: 'bar' },
|
533 | { foo: 'bar2' }
|
534 | ];
|
535 | const result = toXML(val);
|
536 | const expectedResult = '<foo>bar</foo><foo>bar2</foo>';
|
537 | assert.equal(result, expectedResult);
|
538 | });
|
539 |
|
540 | it('3 simple function', () => {
|
541 | const date = new Date();
|
542 | const val = {
|
543 | currentTime: () => date
|
544 | };
|
545 | const result = toXML(val);
|
546 | const expectedResult = `<currentTime>${date}</currentTime>`;
|
547 | assert.equal(result, expectedResult);
|
548 | });
|
549 |
|
550 | it('4 attributes', () => {
|
551 | const val = {
|
552 | _name: 'foo',
|
553 | _content: 'bar',
|
554 | _attrs: {
|
555 | a: 'b',
|
556 | c: 'd'
|
557 | }
|
558 | };
|
559 | const result = toXML(val);
|
560 | const expectedResult = '<foo a="b" c="d">bar</foo>';
|
561 | assert.equal(result, expectedResult);
|
562 | });
|
563 |
|
564 | it('5 tags with mixed content', () => {
|
565 | const val = {
|
566 | text1: null,
|
567 | foo: 'bar',
|
568 | text2: null
|
569 | };
|
570 | const result = toXML(val);
|
571 | const expectedResult = 'text1<foo>bar</foo>text2';
|
572 | assert.equal(result, expectedResult);
|
573 | });
|
574 |
|
575 | it('6 nested tags with indent', () => {
|
576 | const val = {
|
577 | a: {
|
578 | foo: 'bar',
|
579 | foo2: 'bar2'
|
580 | }
|
581 | };
|
582 | const config = {
|
583 | header: false,
|
584 | indent: ' '
|
585 | };
|
586 | const result = toXML(val, config);
|
587 | const expectedResult = `<a>
|
588 | <foo>bar</foo>
|
589 | <foo2>bar2</foo2>
|
590 | </a>`;
|
591 | assert.equal(result, expectedResult);
|
592 | });
|
593 |
|
594 | it('7 nested tags attributes', () => {
|
595 | const val = {
|
596 | ooo: {
|
597 | _name: 'foo',
|
598 | _attrs: {
|
599 | a: 'b'
|
600 | },
|
601 | _content: {
|
602 | _name: 'bar',
|
603 | _attrs: {
|
604 | c: 'd'
|
605 | }
|
606 | }
|
607 | }
|
608 | };
|
609 | const config = {
|
610 | header: false,
|
611 | indent: ' '
|
612 | };
|
613 | const result = toXML(val, config);
|
614 | const expectedResult = `<ooo>
|
615 | <foo a="b">
|
616 | <bar c="d"/>
|
617 | </foo>
|
618 | </ooo>`;
|
619 | assert.equal(result, expectedResult);
|
620 | });
|
621 |
|
622 | it('8 complex functions', () => {
|
623 | const val = {
|
624 | someNestedXML: () => ({ foo: 'bar' })
|
625 | };
|
626 | const result = toXML(val);
|
627 | const expectedResult = '<someNestedXML><foo>bar</foo></someNestedXML>';
|
628 | assert.equal(result, expectedResult);
|
629 | });
|
630 |
|
631 | it('9 RSS feed', () => {
|
632 | const date = new Date();
|
633 |
|
634 | const val = {
|
635 | _name: 'rss',
|
636 | _attrs: {
|
637 | version: '2.0'
|
638 | },
|
639 | _content: {
|
640 | channel: [
|
641 | { title: 'RSS Example' },
|
642 | { description: 'Description' },
|
643 | { link: 'google.com' },
|
644 | { lastBuildDate: () => date },
|
645 | { pubDate: () => date },
|
646 | { language: 'en' },
|
647 | { item: {
|
648 | title: 'Item title',
|
649 | link: 'Item link',
|
650 | description: 'Item Description',
|
651 | pubDate: () => date
|
652 | } },
|
653 | { item: {
|
654 | title: 'Item2 title',
|
655 | link: 'Item2 link',
|
656 | description: 'Item2 Description',
|
657 | pubDate: () => date
|
658 | } }
|
659 | ]
|
660 | }
|
661 | };
|
662 | const config = {
|
663 | header: true,
|
664 | indent: ' '
|
665 | };
|
666 | const result = toXML(val, config);
|
667 | const expectedResult = `<?xml version="1.0" encoding="UTF-8"?>
|
668 | <rss version="2.0">
|
669 | <channel>
|
670 | <title>RSS Example</title>
|
671 | <description>Description</description>
|
672 | <link>google.com</link>
|
673 | <lastBuildDate>${date}</lastBuildDate>
|
674 | <pubDate>${date}</pubDate>
|
675 | <language>en</language>
|
676 | <item>
|
677 | <title>Item title</title>
|
678 | <link>Item link</link>
|
679 | <description>Item Description</description>
|
680 | <pubDate>${date}</pubDate>
|
681 | </item>
|
682 | <item>
|
683 | <title>Item2 title</title>
|
684 | <link>Item2 link</link>
|
685 | <description>Item2 Description</description>
|
686 | <pubDate>${date}</pubDate>
|
687 | </item>
|
688 | </channel>
|
689 | </rss>`;
|
690 | assert.equal(result, expectedResult);
|
691 | });
|
692 |
|
693 | it('10 podcast RSS', () => {
|
694 | const val = {
|
695 | _name: 'rss',
|
696 | _attrs: {
|
697 | 'xmlns:itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
698 | version: '2.0'
|
699 | },
|
700 | _content: {
|
701 | channel: [
|
702 | { title: 'Title' },
|
703 | { link: 'google.com' },
|
704 | { language: 'en-us' },
|
705 | { copyright: 'Copyright 2011' },
|
706 | { 'itunes:subtitle': 'Subtitle' },
|
707 | { 'itunes:author': 'Author' },
|
708 | { 'itunes:summary': 'Summary' },
|
709 | { description: 'Description' },
|
710 | { 'itunes:owner': {
|
711 | 'itunes:name': 'Name',
|
712 | 'itunes:email': 'Email'
|
713 | } },
|
714 | {
|
715 | _name: 'itunes:image',
|
716 | _attrs: {
|
717 | href: 'image.jpg'
|
718 | }
|
719 | },
|
720 | {
|
721 | _name: 'itunes:category',
|
722 | _attrs: {
|
723 | text: 'Technology'
|
724 | },
|
725 | _content: {
|
726 | _name: 'itunes:category',
|
727 | _attrs: {
|
728 | text: 'Gadgets'
|
729 | }
|
730 | }
|
731 | },
|
732 | {
|
733 | _name: 'itunes:category',
|
734 | _attrs: {
|
735 | text: 'TV & Film'
|
736 | }
|
737 | },
|
738 | {
|
739 | item: [
|
740 | { title: 'Podcast Title' },
|
741 | { 'itunes:author': 'Author' },
|
742 | { 'itunes:subtitle': 'Subtitle' },
|
743 | { 'itunes:summary': 'Summary' },
|
744 | { 'itunes:image': 'image.jpg' },
|
745 | {
|
746 | _name: 'enclosure',
|
747 | _attrs: {
|
748 | url: 'http://example.com/podcast.m4a',
|
749 | length: '8727310',
|
750 | type: 'audio/x-m4a'
|
751 | }
|
752 | },
|
753 | { guid: 'http://example.com/archive/aae20050615.m4a' },
|
754 | { pubDate: 'Wed, 15 Jun 2011 19:00:00 GMT' },
|
755 | { 'itunes:duration': '7:04' },
|
756 | { 'itunes:keywords': 'salt, pepper, shaker, exciting' }
|
757 | ]
|
758 | },
|
759 | {
|
760 | item: [
|
761 | { title: 'Podcast2 Title' },
|
762 | { 'itunes:author': 'Author2' },
|
763 | { 'itunes:subtitle': 'Subtitle2' },
|
764 | { 'itunes:summary': 'Summary2' },
|
765 | { 'itunes:image': 'image2.jpg' },
|
766 | {
|
767 | _name: 'enclosure',
|
768 | _attrs: {
|
769 | url: 'http://example.com/podcast2.m4a',
|
770 | length: '655555',
|
771 | type: 'audio/x-m4a'
|
772 | }
|
773 | },
|
774 | { guid: 'http://example.com/archive/aae2.m4a' },
|
775 | { pubDate: 'Wed, 15 Jul 2011 19:00:00 GMT' },
|
776 | { 'itunes:duration': '11:20' },
|
777 | { 'itunes:keywords': 'foo, bar' }
|
778 | ]
|
779 | }
|
780 | ]
|
781 | }
|
782 | };
|
783 | const config = {
|
784 | header: true,
|
785 | indent: ' '
|
786 | };
|
787 |
|
788 | const result = toXML(val, config);
|
789 | const expectedResult = `<?xml version="1.0" encoding="UTF-8"?>
|
790 | <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
|
791 | <channel>
|
792 | <title>Title</title>
|
793 | <link>google.com</link>
|
794 | <language>en-us</language>
|
795 | <copyright>Copyright 2011</copyright>
|
796 | <itunes:subtitle>Subtitle</itunes:subtitle>
|
797 | <itunes:author>Author</itunes:author>
|
798 | <itunes:summary>Summary</itunes:summary>
|
799 | <description>Description</description>
|
800 | <itunes:owner>
|
801 | <itunes:name>Name</itunes:name>
|
802 | <itunes:email>Email</itunes:email>
|
803 | </itunes:owner>
|
804 | <itunes:image href="image.jpg"/>
|
805 | <itunes:category text="Technology">
|
806 | <itunes:category text="Gadgets"/>
|
807 | </itunes:category>
|
808 | <itunes:category text="TV & Film"/>
|
809 | <item>
|
810 | <title>Podcast Title</title>
|
811 | <itunes:author>Author</itunes:author>
|
812 | <itunes:subtitle>Subtitle</itunes:subtitle>
|
813 | <itunes:summary>Summary</itunes:summary>
|
814 | <itunes:image>image.jpg</itunes:image>
|
815 | <enclosure url="http://example.com/podcast.m4a" length="8727310" type="audio/x-m4a"/>
|
816 | <guid>http://example.com/archive/aae20050615.m4a</guid>
|
817 | <pubDate>Wed, 15 Jun 2011 19:00:00 GMT</pubDate>
|
818 | <itunes:duration>7:04</itunes:duration>
|
819 | <itunes:keywords>salt, pepper, shaker, exciting</itunes:keywords>
|
820 | </item>
|
821 | <item>
|
822 | <title>Podcast2 Title</title>
|
823 | <itunes:author>Author2</itunes:author>
|
824 | <itunes:subtitle>Subtitle2</itunes:subtitle>
|
825 | <itunes:summary>Summary2</itunes:summary>
|
826 | <itunes:image>image2.jpg</itunes:image>
|
827 | <enclosure url="http://example.com/podcast2.m4a" length="655555" type="audio/x-m4a"/>
|
828 | <guid>http://example.com/archive/aae2.m4a</guid>
|
829 | <pubDate>Wed, 15 Jul 2011 19:00:00 GMT</pubDate>
|
830 | <itunes:duration>11:20</itunes:duration>
|
831 | <itunes:keywords>foo, bar</itunes:keywords>
|
832 | </item>
|
833 | </channel>
|
834 | </rss>`;
|
835 | assert.equal(result, expectedResult);
|
836 | });
|
837 |
|
838 | it('11 filter', () => {
|
839 | const val = {
|
840 | foo: '<a>',
|
841 | bar: '"b"',
|
842 | baz: '\'&whee\''
|
843 | };
|
844 | const config = {
|
845 | filter: {
|
846 | '<': '<',
|
847 | '>': '>',
|
848 | '"': '"',
|
849 | '\'': ''',
|
850 | '&': '&'
|
851 | }
|
852 | };
|
853 | const result = toXML(val, config);
|
854 | const expectedResult =
|
855 | '<foo><a></foo><bar>"b"</bar><baz>'&whee'</baz>';
|
856 | assert.equal(result, expectedResult);
|
857 | });
|
858 |
|
859 | it('11b attributes filter', () => {
|
860 | const val = {
|
861 | _name: 'foo',
|
862 | _content: 'bar',
|
863 | _attrs: {
|
864 | a: 'http://example.com/?test=\'1\'&foo=<bar>&whee="sha"',
|
865 | b: 'http://example2.com/?test=\'2\'&md=<5>&sum="sha"'
|
866 | }
|
867 | };
|
868 | const config = {
|
869 | attributesFilter: {
|
870 | '<': '<',
|
871 | '>': '>',
|
872 | '"': '"',
|
873 | '\'': ''',
|
874 | '&': '&'
|
875 | }
|
876 | };
|
877 | const result = toXML(val, config);
|
878 | const expectedResult =
|
879 | '<foo a="http://example.com/?test='1'&foo=<bar>&whee="sha"" b="http://example2.com/?test='2'&md=<5>&sum="sha"">bar</foo>';
|
880 | assert.equal(result, expectedResult);
|
881 | });
|
882 |
|
883 | it('12 avoiding self closing tags', () => {
|
884 | const val = [
|
885 | {
|
886 | _name: 'foo',
|
887 | _content: '',
|
888 | _selfCloseTag: false
|
889 | },
|
890 | {
|
891 | _name: 'bar',
|
892 | _content: undefined,
|
893 | _selfCloseTag: false
|
894 | }
|
895 | ];
|
896 | const result = toXML(val);
|
897 | const expectedResult = '<foo></foo><bar></bar>';
|
898 | assert.equal(result, expectedResult);
|
899 | });
|
900 |
|
901 | it('13 custom xml header', () => {
|
902 | const val = {
|
903 | foo: 'bar'
|
904 | };
|
905 | const config = {
|
906 | header: '<?xml version="1.0" encoding="UTF-16" standalone="yes"?>'
|
907 | };
|
908 | const result = toXML(val, config);
|
909 | const expectedResult =
|
910 | '<?xml version="1.0" encoding="UTF-16" standalone="yes"?><foo>bar</foo>';
|
911 | assert.equal(result, expectedResult);
|
912 | });
|
913 |
|
914 |
|
915 | it('14 emoji attributes', () => {
|
916 | const val = {
|
917 | html: {
|
918 | _attrs: {
|
919 | '⚡': true
|
920 | }
|
921 | }
|
922 | };
|
923 | const result = toXML(val);
|
924 | const expectedResult = '<html ⚡/>';
|
925 | assert.equal(result, expectedResult);
|
926 | });
|
927 |
|
928 | it('15 duplicate attribute keys', () => {
|
929 | const val = {
|
930 | html: {
|
931 | _attrs: [
|
932 | { lang: 'en' },
|
933 | { lang: 'klingon' }
|
934 | ]
|
935 | }
|
936 | };
|
937 | const result = toXML(val);
|
938 | const expectedResult = '<html lang="en" lang="klingon"/>';
|
939 | assert.equal(result, expectedResult);
|
940 | });
|
941 |
|
942 | it('issue #33: array of primitives', () => {
|
943 | const val = {
|
944 | x: [1, 2, 3]
|
945 | };
|
946 | const result = toXML(val);
|
947 | const expectedResult = '<x>1</x><x>2</x><x>3</x>';
|
948 | assert.equal(result, expectedResult);
|
949 | });
|
950 |
|
951 | it('issue #33: array of primitives 2', () => {
|
952 | const val = {
|
953 | a: {
|
954 | x: [1, 2, 3]
|
955 | }
|
956 | };
|
957 | const result = toXML(val);
|
958 | const expectedResult = '<a><x>1</x><x>2</x><x>3</x></a>';
|
959 | assert.equal(result, expectedResult);
|
960 | });
|
961 |
|
962 | it('issue #33: array of primitives 2 with indent', () => {
|
963 | const val = {
|
964 | a: {
|
965 | x: [1, 2, 3]
|
966 | }
|
967 | };
|
968 | const config = { indent: ' ' };
|
969 | const result = toXML(val, config);
|
970 | const expectedResult = '<a>\n <x>1</x>\n <x>2</x>\n <x>3</x>\n</a>';
|
971 | assert.equal(result, expectedResult);
|
972 | });
|
973 | it('issue #33: array of objects', ()=>{
|
974 | const val = {
|
975 | a: {
|
976 | x: [{b:1,c:2},{d:3,e:4},{f:5,g:6}]
|
977 | }
|
978 | }
|
979 | const result = toXML(val);
|
980 | const expectedResult = '<a><x><b>1</b><c>2</c></x><x><d>3</d><e>4</e></x><x><f>5</f><g>6</g></x></a>'
|
981 | });
|
982 | it('issue #33: array of objects jstoxml format', () => {
|
983 | const val = {
|
984 | a: [
|
985 | {
|
986 | _name: 'foo',
|
987 | _content: '1',
|
988 | },
|
989 | {
|
990 | _name: 'foo',
|
991 | _content: '2',
|
992 | }
|
993 | ]
|
994 | };
|
995 | const result = toXML(val);
|
996 | const expectedResult = '<a><foo>1</foo><foo>2</foo></a>';
|
997 | assert.equal(result, expectedResult);
|
998 | });
|
999 | it('issue #34: array of array', () => {
|
1000 | const val = {
|
1001 | Response: [
|
1002 | [
|
1003 | {
|
1004 | _name: 'Play',
|
1005 | _content: 'first sound'
|
1006 | },
|
1007 | {
|
1008 | _name: 'Play',
|
1009 | _content: 'second sound'
|
1010 | }
|
1011 | ]
|
1012 | ]
|
1013 | };
|
1014 | const result = toXML(val);
|
1015 | const expectedResult = '<Response><Play>first sound</Play><Play>second sound</Play></Response>';
|
1016 | assert.equal(result, expectedResult);
|
1017 | });
|
1018 | it('issue #34', () => {
|
1019 | const val = {t:[{foo: 'bar'},{foo: 'bar2'}]};
|
1020 | const result = toXML(val);
|
1021 | const expectedResult = '<t><foo>bar</foo><foo>bar2</foo></t>';
|
1022 | assert.equal(result, expectedResult);
|
1023 | });
|
1024 | it('issue #34', () => {
|
1025 | const val = {t:[{_name: "foo", _content: 'bar'},{_name: "foo", _content: 'bar2'}]};
|
1026 | const result = toXML(val);
|
1027 | const expectedResult = '<t><foo>bar</foo><foo>bar2</foo></t>';
|
1028 | assert.equal(result, expectedResult);
|
1029 | });
|
1030 | });
|
1031 | });
|