UNPKG

35.6 kBJavaScriptView Raw
1const NodeID3 = require('../index.js')
2const jsmediatags = require("jsmediatags")
3const assert = require('assert')
4const chai = require('chai')
5const expect = chai.expect
6const iconv = require('iconv-lite')
7const fs = require('fs')
8const ID3Util = require('../src/ID3Util')
9
10describe('NodeID3', function () {
11 describe('#create()', function () {
12 it('empty tags', function () {
13 assert.strictEqual(NodeID3.create({}).compare(Buffer.from([0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])), 0)
14 })
15 it('text frames', function () {
16 let tags = {
17 TIT2: "abcdeÜ看板かんばん",
18 album: "nasÖÄkdnasd",
19 notfound: "notfound",
20 year: 1990
21 }
22 let buffer = NodeID3.create(tags)
23 let titleSize = 10 + 1 + iconv.encode(tags.TIT2, 'utf16').length
24 let albumSize = 10 + 1 + iconv.encode(tags.album, 'utf16').length
25 let yearSize = 10 + 1 + iconv.encode(tags.year, 'utf16').length
26 assert.strictEqual(buffer.length,
27 10 + // ID3 frame header
28 titleSize + // TIT2 header + encoding byte + utf16 bytes + utf16 string
29 albumSize +// same as above for album,
30 yearSize
31 )
32 // Check ID3 header
33 assert.ok(buffer.includes(
34 Buffer.concat([
35 Buffer.from([0x49, 0x44, 0x33, 0x03, 0x00, 0x00]),
36 Buffer.from(ID3Util.encodeSize(titleSize + albumSize + yearSize))
37 ])
38 ))
39
40 // Check TIT2 frame
41 assert.ok(buffer.includes(
42 Buffer.concat([
43 Buffer.from([0x54, 0x49, 0x54, 0x32]),
44 sizeToBuffer(titleSize - 10),
45 Buffer.from([0x00, 0x00]),
46 Buffer.from([0x01]),
47 iconv.encode(tags.TIT2, 'utf16')
48 ])
49 ))
50 // Check album frame
51 assert.ok(buffer.includes(
52 Buffer.concat([
53 Buffer.from([0x54, 0x41, 0x4C, 0x42]),
54 sizeToBuffer(albumSize - 10),
55 Buffer.from([0x00, 0x00]),
56 Buffer.from([0x01]),
57 iconv.encode(tags.album, 'utf16')
58 ])
59 ))
60 assert.ok(buffer.includes(
61 Buffer.concat([
62 Buffer.from([0x54, 0x59, 0x45, 0x52]),
63 sizeToBuffer(yearSize - 10),
64 Buffer.from([0x00, 0x00]),
65 Buffer.from([0x01]),
66 iconv.encode(tags.year, 'utf16')
67 ])
68 ))
69 })
70
71 it('user defined text frames', function() {
72 let tags = {
73 userDefinedText: {
74 description: "abc",
75 value: "defg"
76 }
77 }
78 let buffer = NodeID3.create(tags).slice(10)
79 let descEncoded = iconv.encode(tags.userDefinedText.description + "\0", "UTF-16")
80 let valueEncoded = iconv.encode(tags.userDefinedText.value, "UTF-16")
81
82 assert.strictEqual(Buffer.compare(
83 buffer,
84 Buffer.concat([
85 Buffer.from([0x54, 0x58, 0x58, 0x58]),
86 sizeToBuffer(1 + descEncoded.length + valueEncoded.length),
87 Buffer.from([0x00, 0x00]),
88 Buffer.from([0x01]),
89 descEncoded,
90 valueEncoded
91 ])
92 ), 0)
93
94 tags = {
95 userDefinedText: [{
96 description: "abc",
97 value: "defg"
98 }, {
99 description: "hij",
100 value: "klmn"
101 }]
102 }
103 buffer = NodeID3.create(tags).slice(10)
104 let desc1Encoded = iconv.encode(tags.userDefinedText[0].description + "\0", "UTF-16")
105 let value1Encoded = iconv.encode(tags.userDefinedText[0].value, "UTF-16")
106 let desc2Encoded = iconv.encode(tags.userDefinedText[1].description + "\0", "UTF-16")
107 let value2Encoded = iconv.encode(tags.userDefinedText[1].value, "UTF-16")
108
109 assert.strictEqual(Buffer.compare(
110 buffer,
111 Buffer.concat([
112 Buffer.from([0x54, 0x58, 0x58, 0x58]),
113 sizeToBuffer(1 + desc1Encoded.length + value1Encoded.length),
114 Buffer.from([0x00, 0x00]),
115 Buffer.from([0x01]),
116 desc1Encoded,
117 value1Encoded,
118 Buffer.from([0x54, 0x58, 0x58, 0x58]),
119 sizeToBuffer(1 + desc2Encoded.length + value2Encoded.length),
120 Buffer.from([0x00, 0x00]),
121 Buffer.from([0x01]),
122 desc2Encoded,
123 value2Encoded
124 ])
125 ), 0)
126 })
127
128 it('create APIC frame', function() {
129 let tags = {
130 image: {
131 description: "asdf",
132 imageBuffer: Buffer.from('5B307836312C20307836322C20307836332C20307836345D', 'hex'),
133 mime: "image/jpeg",
134 type: {id: 3, name: "front cover"}
135 }
136 }
137
138 assert.strictEqual(Buffer.compare(
139 NodeID3.create(tags),
140 Buffer.from('4944330300000000003B4150494300000031000001696D6167652F6A7065670003FFFE610073006400660000005B307836312C20307836322C20307836332C20307836345D', 'hex')
141 ), 0)
142
143 assert.strictEqual(Buffer.compare(
144 NodeID3.create({
145 image: __dirname + '/smallimg'
146 }),
147 NodeID3.create({
148 image: {
149 imageBuffer: fs.readFileSync(__dirname + '/smallimg')
150 }
151 })
152 ), 0)
153
154 assert.strictEqual(Buffer.compare(
155 NodeID3.create({
156 image: fs.readFileSync(__dirname + '/smallimg')
157 }),
158 NodeID3.create({
159 image: {
160 imageBuffer: fs.readFileSync(__dirname + '/smallimg')
161 }
162 })
163 ), 0)
164 })
165
166 it('create USLT frame', function() {
167 let tags = {
168 unsynchronisedLyrics: {
169 language: "deu",
170 shortText: "Haiwsää#",
171 text: "askdh ashd olahs elowz dlouaish dkajh"
172 }
173 }
174
175 assert.strictEqual(Buffer.compare(
176 NodeID3.create(tags),
177 Buffer.from('4944330300000000006E55534C5400000064000001646575FFFE48006100690077007300E400E40023000000FFFE610073006B00640068002000610073006800640020006F006C00610068007300200065006C006F0077007A00200064006C006F0075006100690073006800200064006B0061006A006800', 'hex')
178 ), 0)
179 })
180
181 it('create COMM frame', function() {
182 const tags = {
183 comment: {
184 language: "deu",
185 shortText: "Haiwsää#",
186 text: "askdh ashd olahs elowz dlouaish dkajh"
187 }
188 }
189 let frameBuf = Buffer.from('4944330300000000006E434F4D4D00000064000001646575FFFE48006100690077007300E400E40023000000FFFE610073006B00640068002000610073006800640020006F006C00610068007300200065006C006F0077007A00200064006C006F0075006100690073006800200064006B0061006A006800', 'hex')
190
191 assert.strictEqual(Buffer.compare(
192 NodeID3.create(tags),
193 frameBuf
194 ), 0)
195 })
196
197 it('create POPM frame', function() {
198 let frameBuf = Buffer.from('49443303000000000020504F504D0000001600006D61696C406578616D706C652E636F6D00C00000000C', 'hex')
199 const tags = {
200 popularimeter: {
201 email: "mail@example.com",
202 rating: 192, // 1-255
203 counter: 12
204 }
205 }
206
207 assert.strictEqual(Buffer.compare(
208 NodeID3.create(tags),
209 frameBuf
210 ), 0)
211 })
212
213 it('create PRIV frame', function() {
214 let frameBuf = Buffer.from('4944330300000000003250524956000000140000416243006173646F61687764696F686177646177505249560000000A000041624353535300010205', 'hex')
215 const tags = { PRIV: [{
216 ownerIdentifier: "AbC",
217 data: Buffer.from("asdoahwdiohawdaw")
218 }, {
219 ownerIdentifier: "AbCSSS",
220 data: Buffer.from([0x01, 0x02, 0x05])
221 }]
222 }
223
224 assert.deepStrictEqual(
225 NodeID3.create(tags),
226 frameBuf
227 )
228 })
229
230 it('create CHAP frame', function() {
231 let frameBuf = Buffer.from('494433030000000000534348415000000049000048657921000000138800001F400000007B000001C8544954320000000F000001FFFE6100620063006400650066005450453100000011000001FFFE61006B0073006800640061007300', 'hex')
232 const tags = { CHAP: [{
233 elementID: "Hey!", //THIS MUST BE UNIQUE!
234 startTimeMs: 5000,
235 endTimeMs: 8000,
236 startOffsetBytes: 123, // OPTIONAL!
237 endOffsetBytes: 456, // OPTIONAL!
238 tags: { // OPTIONAL
239 title: "abcdef",
240 artist: "akshdas"
241 }
242 }]}
243
244 assert.deepStrictEqual(
245 NodeID3.create(tags),
246 frameBuf
247 )
248 })
249
250 it('create WXXX frame', function() {
251 const frameBuf = Buffer.from('4944330300000000002c5758585800000022000001fffe61006200630064002300000068747470733a2f2f6578616d706c652e636f6d', 'hex')
252 const tags = {
253 userDefinedUrl: [{
254 description: 'abcd#',
255 url: 'https://example.com'
256 }]
257 }
258
259 assert.deepStrictEqual(
260 NodeID3.create(tags),
261 frameBuf
262 )
263 })
264
265 it('create URL frame', function() {
266 const frameBuf = Buffer.from('4944330300000000003b57434f4d00000013000068747470733a2f2f6578616d706c652e636f6d574f414600000014000068747470733a2f2f6578616d706c65322e636f6d', 'hex')
267 const tags = {
268 commercialUrl: ['https://example.com'],
269 fileUrl: 'https://example2.com'
270 }
271
272 assert.deepStrictEqual(
273 NodeID3.create(tags),
274 frameBuf
275 )
276 })
277 })
278
279 describe('#write()', function() {
280 it('sync not existing filepath', function() {
281 assert.throws(NodeID3.write.bind({}, './hopefullydoesnotexist.mp3'), Error)
282 })
283 it('async not existing filepath', function() {
284 NodeID3.write({}, './hopefullydoesnotexist.mp3', function(err) {
285 if(!(err instanceof Error)) {
286 assert.fail("No error thrown on non-existing filepath")
287 }
288 })
289 })
290
291 let buffer = Buffer.from([0x02, 0x06, 0x12, 0x22])
292 let tags = {title: "abc"}
293 let filepath = './testfile.mp3'
294
295 it('sync write file without id3 tag', function() {
296 fs.writeFileSync(filepath, buffer, 'binary')
297 NodeID3.write(tags, filepath)
298 let newFileBuffer = fs.readFileSync(filepath)
299 fs.unlinkSync(filepath)
300 assert.strictEqual(Buffer.compare(
301 newFileBuffer,
302 Buffer.concat([NodeID3.create(tags), buffer])
303 ), 0)
304 })
305 it('async write file without id3 tag', function(done) {
306 fs.writeFileSync(filepath, buffer, 'binary')
307 NodeID3.write(tags, filepath, function() {
308 let newFileBuffer = fs.readFileSync(filepath)
309 fs.unlinkSync(filepath)
310 if(Buffer.compare(
311 newFileBuffer,
312 Buffer.concat([NodeID3.create(tags), buffer])
313 ) === 0) {
314 done()
315 } else {
316 done(new Error("buffer not the same"))
317 }
318 })
319 })
320
321 let bufferWithTag = Buffer.concat([NodeID3.create(tags), buffer])
322 tags = {album: "ix123"}
323
324 it('sync write file with id3 tag', function() {
325 fs.writeFileSync(filepath, bufferWithTag, 'binary')
326 NodeID3.write(tags, filepath)
327 let newFileBuffer = fs.readFileSync(filepath)
328 fs.unlinkSync(filepath)
329 assert.strictEqual(Buffer.compare(
330 newFileBuffer,
331 Buffer.concat([NodeID3.create(tags), buffer])
332 ), 0)
333 })
334 it('async write file with id3 tag', function(done) {
335 fs.writeFileSync(filepath, bufferWithTag, 'binary')
336 NodeID3.write(tags, filepath, function() {
337 let newFileBuffer = fs.readFileSync(filepath)
338 fs.unlinkSync(filepath)
339 if(Buffer.compare(
340 newFileBuffer,
341 Buffer.concat([NodeID3.create(tags), buffer])
342 ) === 0) {
343 done()
344 } else {
345 done(new Error("file written incorrectly"))
346 }
347 })
348 })
349 })
350
351 describe('#read()', function() {
352 it('read empty id3 tag', function() {
353 let frame = NodeID3.create({})
354 assert.deepStrictEqual(
355 NodeID3.read(frame),
356 {raw: {}}
357 )
358 })
359
360 it('read text frames id3 tag', function() {
361 let frame = NodeID3.create({ title: "asdfghjÄÖP", album: "naBGZwssg" })
362 assert.deepStrictEqual(
363 NodeID3.read(frame),
364 { title: "asdfghjÄÖP", album: "naBGZwssg", raw: { TIT2: "asdfghjÄÖP", TALB: "naBGZwssg" }}
365 )
366 })
367
368 it('read tag with broken frame', function() {
369 let frame = NodeID3.create({ title: "asdfghjÄÖP", album: "naBGZwssg" })
370 frame[10] = 0x99
371 assert.deepStrictEqual(
372 NodeID3.read(frame),
373 { album: "naBGZwssg", raw: { TALB: "naBGZwssg" }}
374 )
375 })
376
377 /*it('read tag with broken tag', function() {
378 let frame = NodeID3.create({ title: "asdfghjÄÖP", album: "naBGZwssg" })
379 frame[3] = 0x99
380 assert.deepStrictEqual(
381 NodeID3.read(frame),
382 { raw: { }}
383 )
384 })*/
385
386 it('read tag with bigger size', function() {
387 let frame = NodeID3.create({ title: "asdfghjÄÖP", album: "naBGZwssg" })
388 frame[9] += 100
389 assert.deepStrictEqual(
390 NodeID3.read(frame),
391 { title: "asdfghjÄÖP", album: "naBGZwssg", raw: { TIT2: "asdfghjÄÖP", TALB: "naBGZwssg" }}
392 )
393 })
394
395 it('read tag with smaller size', function() {
396 let frame = NodeID3.create({ title: "asdfghjÄÖP", album: "naBGZwssg" })
397 frame[9] -= 25
398 assert.deepStrictEqual(
399 NodeID3.read(frame),
400 { title: "asdfghjÄÖP", raw: { TIT2: "asdfghjÄÖP" }}
401 )
402 })
403
404 it('read TXXX frame', function() {
405 let tags = { userDefinedText: {description: "abc", value: "deg"} }
406 let frame = NodeID3.create(tags)
407 assert.deepStrictEqual(
408 NodeID3.read(frame),
409 {
410 userDefinedText: [tags.userDefinedText],
411 raw: {
412 TXXX: [tags.userDefinedText]
413 }
414 }
415 )
416 })
417
418 it('read TXXX array frame', function() {
419 let tags = { userDefinedText: [{description: "abc", value: "deg"}, {description: "abcd", value: "efgh"}] }
420 let frame = NodeID3.create(tags)
421 assert.deepStrictEqual(
422 NodeID3.read(frame),
423 {
424 userDefinedText: tags.userDefinedText,
425 raw: {
426 TXXX: tags.userDefinedText
427 }
428 }
429 )
430 })
431
432 it('read APIC frame', function() {
433 let withAll = Buffer.from("4944330300000000101C4150494300000016000000696D6167652F6A7065670003617364660061626364", "hex")
434 let noDesc = Buffer.from("494433030000000000264150494300000012000000696D6167652F6A70656700030061626364", "hex")
435 let obj = {
436 description: "asdf",
437 imageBuffer: Buffer.from([0x61, 0x62, 0x63, 0x64]),
438 mime: "jpeg",
439 type: { id: 3, name: "front cover" }
440 }
441
442 assert.deepStrictEqual(
443 NodeID3.read(withAll).image,
444 obj
445 )
446
447 obj.description = undefined
448 assert.deepStrictEqual(
449 NodeID3.read(noDesc).image,
450 obj
451 )
452 })
453
454 it('read USLT frame', function() {
455 let frameBuf = Buffer.from('4944330300000000006E55534C5400000064000001646575FFFE48006100690077007300E400E40023000000FFFE610073006B00640068002000610073006800640020006F006C00610068007300200065006C006F0077007A00200064006C006F0075006100690073006800200064006B0061006A006800', 'hex')
456 const unsynchronisedLyrics = {
457 language: "deu",
458 shortText: "Haiwsää#",
459 text: "askdh ashd olahs elowz dlouaish dkajh"
460 }
461
462 assert.deepStrictEqual(
463 NodeID3.read(frameBuf).unsynchronisedLyrics,
464 unsynchronisedLyrics
465 )
466 })
467
468 it('read COMM frame', function() {
469 let frameBuf = Buffer.from('4944330300000000006E434F4D4D00000064000001646575FFFE48006100690077007300E400E40023000000FFFE610073006B00640068002000610073006800640020006F006C00610068007300200065006C006F0077007A00200064006C006F0075006100690073006800200064006B0061006A006800', 'hex')
470 const comment = {
471 language: "deu",
472 shortText: "Haiwsää#",
473 text: "askdh ashd olahs elowz dlouaish dkajh"
474 }
475
476 assert.deepStrictEqual(
477 NodeID3.read(frameBuf).comment,
478 comment
479 )
480 })
481
482 it('read POPM frame', function() {
483 let frameBuf = Buffer.from('49443303000000000020504F504D0000001600006D61696C406578616D706C652E636F6D00C00000000C', 'hex')
484 const popularimeter = {
485 email: "mail@example.com",
486 rating: 192, // 1-255
487 counter: 12
488 }
489
490 assert.deepStrictEqual(
491 NodeID3.read(frameBuf).popularimeter,
492 popularimeter
493 )
494 })
495
496 it('read PRIV frame', function() {
497 let frameBuf = Buffer.from('4944330300000000003250524956000000140000416243006173646F61687764696F686177646177505249560000000A000041624353535300010205', 'hex')
498 const priv = [{
499 ownerIdentifier: "AbC",
500 data: Buffer.from("asdoahwdiohawdaw")
501 }, {
502 ownerIdentifier: "AbCSSS",
503 data: Buffer.from([0x01, 0x02, 0x05])
504 }]
505
506 assert.deepStrictEqual(
507 NodeID3.read(frameBuf).private,
508 priv
509 )
510 })
511
512 it('read CHAP frame', function() {
513 let frameBuf = Buffer.from('494433030000000000534348415000000049000048657921000000138800001F400000007B000001C8544954320000000F000001FFFE6100620063006400650066005450453100000011000001FFFE61006B0073006800640061007300', 'hex')
514 const chap = [{
515 elementID: "Hey!", //THIS MUST BE UNIQUE!
516 startTimeMs: 5000,
517 endTimeMs: 8000,
518 startOffsetBytes: 123, // OPTIONAL!
519 endOffsetBytes: 456, // OPTIONAL!
520 tags: { // OPTIONAL
521 title: "abcdef",
522 artist: "akshdas",
523 raw: {
524 TIT2: "abcdef",
525 TPE1: "akshdas"
526 }
527 }
528 }]
529
530 assert.deepStrictEqual(
531 NodeID3.read(frameBuf).chapter,
532 chap
533 )
534 })
535
536 it('read WXXX frame', function() {
537 const frameBuf = Buffer.from('4944330300000000002c5758585800000022000001fffe61006200630064002300000068747470733a2f2f6578616d706c652e636f6d', 'hex')
538 const userDefinedUrl = [{
539 description: 'abcd#',
540 url: 'https://example.com'
541 }]
542
543 assert.deepStrictEqual(
544 NodeID3.read(frameBuf).userDefinedUrl,
545 userDefinedUrl
546 )
547 })
548
549 it('read URL frame', function() {
550 const frameBuf = Buffer.from('4944330300000000003d57434f4d0000001400000068747470733a2f2f6578616d706c652e636f6d574f41460000001500000068747470733a2f2f6578616d706c65322e636f6d', 'hex')
551 const commercialUrl = ['https://example.com']
552 const fileUrl = 'https://example2.com'
553
554 assert.deepStrictEqual(
555 NodeID3.read(frameBuf).commercialUrl,
556 commercialUrl
557 )
558 assert.deepStrictEqual(
559 NodeID3.read(frameBuf).fileUrl,
560 fileUrl
561 )
562 })
563
564 it('read exclude', function() {
565 let tags = {
566 TIT2: "abcdeÜ看板かんばん",
567 album: "nasÖÄkdnasd",
568 year: "1990"
569 }
570
571 const buffer = NodeID3.create(tags)
572 let read = NodeID3.read(buffer, { exclude: ['TIT2'] })
573 delete read.raw
574 delete tags.TIT2
575 assert.deepStrictEqual(
576 read,
577 tags
578 )
579 })
580
581 it('read include', function() {
582 let tags = {
583 title: "abcdeÜ看板かんばん",
584 album: "nasÖÄkdnasd",
585 year: "1990"
586 }
587
588 const buffer = NodeID3.create(tags)
589 let read = NodeID3.read(buffer, { include: ['TALB', 'TIT2'] })
590 delete read.raw
591 delete tags.year
592 assert.deepStrictEqual(
593 read,
594 tags
595 )
596 })
597
598 it('onlyRaw', function() {
599 let tags = {
600 TIT2: "abcdeÜ看板かんばん",
601 TALB: "nasÖÄkdnasd"
602 }
603
604 const buffer = NodeID3.create(tags)
605 let read = NodeID3.read(buffer, { onlyRaw: true })
606 assert.deepStrictEqual(
607 read,
608 tags
609 )
610 })
611
612 it('noRaw', function() {
613 let tags = {
614 title: "abcdeÜ看板かんばん",
615 album: "nasÖÄkdnasd"
616 }
617
618 const buffer = NodeID3.create(tags)
619 let read = NodeID3.read(buffer, { noRaw: true })
620 assert.deepStrictEqual(
621 read,
622 tags
623 )
624 })
625 })
626})
627
628describe('ID3 helper functions', function () {
629 describe('#removeTagsFromBuffer()', function () {
630 it('no tags in buffer', function () {
631 let emptyBuffer = Buffer.from([0x12, 0x04, 0x05, 0x01, 0x76, 0x27, 0x76, 0x27, 0x76, 0x27, 0x76, 0x27])
632 assert.strictEqual(Buffer.compare(
633 emptyBuffer,
634 NodeID3.removeTagsFromBuffer(emptyBuffer)
635 ), 0)
636 })
637
638 it('tags at start', function () {
639 let buffer = Buffer.from([0x22, 0x73, 0x72])
640 let bufferWithID3 = Buffer.concat([
641 NodeID3.create({title: "abc"}),
642 buffer
643 ])
644 assert.strictEqual(Buffer.compare(
645 NodeID3.removeTagsFromBuffer(bufferWithID3),
646 buffer
647 ), 0)
648 })
649
650 it('tags in middle/end', function () {
651 let buffer = Buffer.from([0x22, 0x73, 0x72])
652 let bufferWithID3 = Buffer.concat([
653 buffer,
654 NodeID3.create({title: "abc"}),
655 buffer
656 ])
657 assert.strictEqual(Buffer.compare(
658 NodeID3.removeTagsFromBuffer(bufferWithID3),
659 Buffer.concat([buffer, buffer])
660 ), 0)
661 })
662 })
663})
664
665const nodeTagsFull = {
666 title: 'abc',
667 album: '人物asfjas as das \\',
668 comment: {
669 language: 'en3',
670 shortText: 'asd物f',
671 text: 1337
672 },
673 unsynchronisedLyrics: {
674 language: 'e33',
675 text: 'asd物f asd物f asd物f'
676 },
677 userDefinedText: [
678 {
679 description: "txxx name物",
680 value: "TXXX value text"
681 }, {
682 description: "txxx name 2",
683 value: "TXXX value text 2"
684 }
685 ],
686 image: {
687 mime: "jpeg",
688 description: 'asd物f asd物f asd物f',
689 imageBuffer: Buffer.from([0x02, 0x27, 0x17, 0x99])
690 },
691 popularimeter: {
692 email: 'test@example.com',
693 rating: 192,
694 counter: 12
695 },
696 private: [{
697 ownerIdentifier: "AbC",
698 data: "asdoahwdiohawdaw"
699 }, {
700 ownerIdentifier: "AbCSSS",
701 data: Buffer.from([0x01, 0x02, 0x05])
702 }],
703 chapter: [{
704 elementID: "Hey!", // THIS MUST BE UNIQUE!
705 startTimeMs: 5000,
706 endTimeMs: 8000,
707 startOffsetBytes: 123, // OPTIONAL!
708 endOffsetBytes: 456, // OPTIONAL!
709 tags: { // OPTIONAL
710 title: "abcdef",
711 artist: "akshdas"
712 }
713 }],
714 tableOfContents: [{
715 elementID: "toc1", // THIS MUST BE UNIQUE!
716 isOrdered: false, // OPTIONAL, tells a player etc. if elements are in a specific order
717 elements: ['chap1'], // OPTIONAL but most likely needed, contains the chapter/tableOfContents elementIDs
718 tags: { // OPTIONAL
719 title: "abcdef"
720 }
721 }],
722 commercialUrl: ["commercialurl.com"],
723 userDefinedUrl: [{
724 description: "URL description物",
725 url: "https://example.com/"
726 }]
727}
728
729const nodeTagsMissingValues = {
730 comment: {
731 language: 'en3',
732 text: 1337
733 },
734 userDefinedText: [
735 {
736 value: "TXXX value text"
737 }, {
738 value: "TXXX value text 2"
739 }
740 ],
741 image: {
742 mime: "jpeg",
743 imageBuffer: Buffer.from([0x02, 0x27, 0x17, 0x99])
744 },
745 popularimeter: {
746 email: 'test@example.com',
747 counter: 12
748 },
749 private: [{
750 data: "asdoahwdiohawdaw"
751 }, {
752 data: Buffer.from([0x01, 0x02, 0x05])
753 }],
754 chapter: [{
755 elementID: "Hey!", // THIS MUST BE UNIQUE!
756 startTimeMs: 5000,
757 endTimeMs: 8000
758 }],
759 tableOfContents: [{
760 elementID: "toc1", // THIS MUST BE UNIQUE!
761 elements: ['chap1']
762 }],
763}
764
765describe('Cross tests jsmediatags', function() {
766 it('write full', function() {
767 jsmediatags.read(NodeID3.create(nodeTagsFull), {
768 onSuccess: (tag) => {
769 const tags = tag.tags
770 assert.strictEqual(tags.TIT2.data, nodeTagsFull.title)
771 assert.strictEqual(tags.TALB.data, nodeTagsFull.album)
772 assert.deepStrictEqual({ language: tags.COMM.data.language, shortText: tags.COMM.data.short_description, text: parseInt(tags.COMM.data.text) }, nodeTagsFull.comment)
773 assert.deepStrictEqual({ language: tags.USLT.data.language, text: tags.USLT.data.lyrics }, nodeTagsFull.unsynchronisedLyrics)
774 expect(tags.TXXX.map((t) => {
775 return {
776 description: t.data.user_description,
777 value: t.data.data
778 }
779 })).to.have.deep.members(nodeTagsFull.userDefinedText)
780 assert.deepStrictEqual({
781 mime: tags.APIC.data.format,
782 description: tags.APIC.data.description,
783 imageBuffer: Buffer.from(tags.APIC.data.data)
784 }, nodeTagsFull.image)
785 /* POPM seems broken in jsmediatags, data is null but tag looks correct */
786 /* PRIV seems broken in jsmediatags, data is null but tag looks correct */
787 assert.deepStrictEqual({
788 elementID: nodeTagsFull.chapter[0].elementID,
789 startTimeMs: tags.CHAP.data.startTime,
790 endTimeMs: tags.CHAP.data.endTime,
791 startOffsetBytes: tags.CHAP.data.startOffset,
792 endOffsetBytes: tags.CHAP.data.endOffset,
793 tags: {
794 title: tags.CHAP.data.subFrames.TIT2.data,
795 artist: tags.CHAP.data.subFrames.TPE1.data
796 }
797 }, nodeTagsFull.chapter[0])
798 assert.deepStrictEqual({
799 elementID:nodeTagsFull.tableOfContents[0].elementID,
800 isOrdered: false,
801 elements: tags.CTOC.data.childElementIds,
802 tags: {
803 title: tags.CTOC.data.subFrames.TIT2.data
804 }
805 }, nodeTagsFull.tableOfContents[0])
806 assert.strictEqual(tags.WCOM.data, nodeTagsFull.commercialUrl[0])
807 assert.deepStrictEqual({
808 description: tags.WXXX.data.user_description,
809 url: nodeTagsFull.userDefinedUrl[0].url /* The URL is always encoded with ISO-8859-1 => jsmediatags reads as UTF-16, can't use here*/
810 }, nodeTagsFull.userDefinedUrl[0])
811 },
812 onError: function(error) {
813 throw error
814 }
815 })
816 })
817
818 it('write with missing values', function() {
819 jsmediatags.read(NodeID3.create(nodeTagsMissingValues), {
820 onSuccess: (tag) => {
821 const tags = tag.tags
822 assert.deepStrictEqual({ language: tags.COMM.data.language, text: parseInt(tags.COMM.data.text) }, nodeTagsMissingValues.comment)
823 assert.strictEqual(tags.COMM.data.short_description, '')
824 expect(tags.TXXX.map((t) => {
825 return {
826 value: t.data.data
827 }
828 })).to.have.deep.members(nodeTagsMissingValues.userDefinedText)
829 tags.TXXX.forEach((t) => {
830 assert.strictEqual(t.data.user_description, '')
831 })
832 assert.deepStrictEqual({
833 mime: tags.APIC.data.format,
834 imageBuffer: Buffer.from(tags.APIC.data.data)
835 }, nodeTagsMissingValues.image)
836 assert.strictEqual(tags.APIC.data.description, '')
837 /* POPM seems broken in jsmediatags, data is null but tag looks correct */
838 /* PRIV seems broken in jsmediatags, data is null but tag looks correct */
839 assert.deepStrictEqual({
840 elementID: nodeTagsMissingValues.chapter[0].elementID,
841 startTimeMs: tags.CHAP.data.startTime,
842 endTimeMs: tags.CHAP.data.endTime
843 }, nodeTagsMissingValues.chapter[0])
844 assert.deepStrictEqual(tags.CHAP.data.subFrames, {})
845 assert.strictEqual(tags.CHAP.data.startOffset, 0xFFFFFFFF)
846 assert.strictEqual(tags.CHAP.data.endOffset, 0xFFFFFFFF)
847 assert.deepStrictEqual({
848 elementID: nodeTagsMissingValues.tableOfContents[0].elementID,
849 elements: tags.CTOC.data.childElementIds,
850 }, nodeTagsMissingValues.tableOfContents[0])
851 assert.deepStrictEqual(tags.CTOC.data.subFrames, {})
852 assert.strictEqual(tags.CTOC.data.ordered, false)
853 },
854 onError: function(error) {
855 throw error
856 }
857 })
858 })
859
860 it('read from full self-created tags', function() {
861 const tagsBuffer = NodeID3.create(nodeTagsFull)
862 let read = NodeID3.read(tagsBuffer)
863
864 delete read.raw
865 delete read.chapter[0].tags.raw
866 delete read.tableOfContents[0].tags.raw
867 read.comment.text = parseInt(read.comment.text)
868 delete read.image.type
869 read.private[0].data = read.private[0].data.toString()
870 if(read.unsynchronisedLyrics.shortText === undefined) delete read.unsynchronisedLyrics.shortText
871 assert.deepStrictEqual(nodeTagsFull, read)
872 })
873
874 it('read from missing values self-created tags', function() {
875 const tagsBuffer = NodeID3.create(nodeTagsMissingValues)
876 let read = NodeID3.read(tagsBuffer)
877
878 delete read.raw
879 assert.deepStrictEqual(read.chapter[0].tags.raw, {})
880 delete read.chapter[0].tags
881 read.comment.text = parseInt(read.comment.text)
882 if(read.comment.shortText === undefined) delete read.comment.shortText
883 if(read.image.description === undefined) delete read.image.description
884 delete read.image.type
885 assert.strictEqual(read.popularimeter.rating, 0)
886 delete read.popularimeter.rating
887 read.private[0].data = read.private[0].data.toString()
888 if(read.private[0].ownerIdentifier === undefined) delete read.private[0].ownerIdentifier
889 if(read.private[1].ownerIdentifier === undefined) delete read.private[1].ownerIdentifier
890 assert.strictEqual(read.tableOfContents[0].isOrdered, false)
891 assert.deepStrictEqual(read.tableOfContents[0].tags.raw, {})
892 delete read.tableOfContents[0].tags
893 delete read.tableOfContents[0].isOrdered
894 if(read.userDefinedText[0].description === undefined) delete read.userDefinedText[0].description
895 if(read.userDefinedText[1].description === undefined) delete read.userDefinedText[1].description
896 assert.deepStrictEqual(nodeTagsMissingValues, read)
897 })
898})
899
900function sizeToBuffer(totalSize) {
901 let buffer = Buffer.alloc(4)
902 buffer.writeUInt32BE(totalSize)
903 return buffer
904}