123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893 |
- import {LineStream, ParseStream} from '../src';
- import QUnit from 'qunit';
- import sinon from 'sinon';
- QUnit.module('ParseStream', {
- beforeEach() {
- this.lineStream = new LineStream();
- this.parseStream = new ParseStream();
- this.lineStream.pipe(this.parseStream);
- }
- });
- QUnit.test('parses custom tags', function(assert) {
- const manifest = '#VOD-STARTTIMESTAMP:1501533337573\n';
- let element;
- this.parseStream.addParser({
- expression: /^#VOD-STARTTIMESTAMP/,
- customType: 'startTimestamp'
- });
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'element');
- assert.strictEqual(element.type, 'custom', 'the type of the data is custom');
- assert.strictEqual(
- element.customType,
- 'startTimestamp',
- 'the customType is startTimestamp'
- );
- });
- QUnit.test('mapper does not conflict with parser', function(assert) {
- const manifest = '#EXAMPLE\n';
- const commentMapper = sinon.spy(line => '#NEW-COMMENT');
- const commentMapper2 = sinon.spy(line => '#SOMETHING-ELSE');
- const dataCallback = sinon.spy();
- this.parseStream.addTagMapper({
- expression: /^#EXAMPLE/,
- map: commentMapper
- });
- this.parseStream.addTagMapper({
- expression: /^#EXAMPLE/,
- map: commentMapper2
- });
- this.parseStream.addParser({
- expression: /^#EXAMPLE/,
- customType: 'test'
- });
- this.parseStream.addParser({
- expression: /^#NEW-COMMENT/,
- customType: 'test2'
- });
- this.parseStream.on('data', dataCallback);
- this.lineStream.push(manifest);
- assert.ok(commentMapper.called);
- assert.ok(commentMapper2.called);
- assert.strictEqual(dataCallback.callCount, 3);
- assert.deepEqual(dataCallback.getCall(0).args[0], {
- data: '#EXAMPLE',
- type: 'custom',
- customType: 'test',
- segment: undefined
- });
- assert.deepEqual(dataCallback.getCall(1).args[0], {
- data: '#NEW-COMMENT',
- type: 'custom',
- customType: 'test2',
- segment: undefined
- });
- assert.deepEqual(dataCallback.getCall(2).args[0], {
- text: 'SOMETHING-ELSE',
- type: 'comment'
- });
- });
- QUnit.test('maps custom tags', function(assert) {
- const manifest = '#EXAMPLE\n';
- const commentMapper = sinon.spy(line => '#NEW-COMMENT');
- const dataCallback = sinon.spy();
- this.parseStream.addTagMapper({
- expression: /^#EXAMPLE/,
- map: commentMapper
- });
- this.parseStream.on('data', dataCallback);
- this.lineStream.push(manifest);
- assert.ok(commentMapper.called);
- assert.strictEqual(dataCallback.callCount, 2);
- assert.deepEqual(dataCallback.getCall(0).args[0], {
- text: 'EXAMPLE',
- type: 'comment'
- });
- assert.deepEqual(dataCallback.getCall(1).args[0], {
- text: 'NEW-COMMENT',
- type: 'comment'
- });
- });
- QUnit.test('maps multiple custom tags', function(assert) {
- const manifest = '#VOD-STARTTIMESTAMP:1501533337573\n';
- const commentMapper = sinon.spy(line => '#NEW-COMMENT');
- const pdtMapper = sinon.spy((line) => {
- const match = /#VOD-STARTTIMESTAMP:(\d+)/g.exec(line)[1];
- const ISOdate = new Date(Number(match)).toISOString();
- return `#EXT-X-PROGRAM-DATE-TIME:${ISOdate}`;
- });
- const dataCallback = sinon.spy();
- this.parseStream.addTagMapper({
- expression: /^#VOD-STARTTIMESTAMP/,
- map: commentMapper
- });
- this.parseStream.addTagMapper({
- expression: /^#VOD-STARTTIMESTAMP/,
- map: pdtMapper
- });
- this.parseStream.on('data', dataCallback);
- this.lineStream.push(manifest);
- assert.ok(commentMapper.called);
- assert.ok(pdtMapper.called);
- assert.strictEqual(dataCallback.callCount, 3);
- assert.deepEqual(dataCallback.getCall(0).args[0], {
- text: 'VOD-STARTTIMESTAMP:1501533337573',
- type: 'comment'
- });
- assert.deepEqual(dataCallback.getCall(1).args[0], {
- text: 'NEW-COMMENT',
- type: 'comment'
- });
- const dateTag = dataCallback.getCall(2).args[0];
- assert.strictEqual(dateTag.dateTimeString, '2017-07-31T20:35:37.573Z');
- assert.strictEqual(dateTag.tagType, 'program-date-time');
- assert.strictEqual(dateTag.type, 'tag');
- });
- QUnit.test('mapper ignores tags', function(assert) {
- const manifest = '#TAG\n';
- const dataCallback = sinon.spy();
- this.parseStream.addTagMapper({
- expression: /^#NO-MATCH/,
- map(line) {
- return '#MAPPED';
- }
- });
- this.parseStream.on('data', dataCallback);
- this.lineStream.push(manifest);
- assert.strictEqual(dataCallback.callCount, 1);
- assert.deepEqual(dataCallback.getCall(0).args[0], {
- text: 'TAG',
- type: 'comment'
- });
- });
- QUnit.test('parses comment lines', function(assert) {
- const manifest = '# a line that starts with a hash mark without "EXT" is a comment\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'comment', 'the type is comment');
- assert.strictEqual(
- element.text,
- manifest.slice(1, manifest.length - 1),
- 'the comment text is parsed'
- );
- });
- QUnit.test('parses uri lines', function(assert) {
- const manifest = 'any non-blank line that does not start with a hash-mark is a URI\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'uri', 'the type is uri');
- assert.strictEqual(
- element.uri,
- manifest.substring(0, manifest.length - 1),
- 'the uri text is parsed'
- );
- });
- QUnit.test('parses unknown tag types', function(assert) {
- const manifest = '#EXT-X-EXAMPLE-TAG:some,additional,stuff\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the type is tag');
- assert.strictEqual(
- element.data,
- manifest.slice(4, manifest.length - 1),
- 'unknown tag data is preserved'
- );
- });
- // #EXTM3U
- QUnit.test('parses #EXTM3U tags', function(assert) {
- const manifest = '#EXTM3U\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'm3u', 'the tag type is m3u');
- });
- // #EXTINF
- QUnit.test('parses minimal #EXTINF tags', function(assert) {
- const manifest = '#EXTINF:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'inf', 'the tag type is inf');
- });
- QUnit.test('parses #EXTINF tags with durations', function(assert) {
- let manifest = '#EXTINF:15\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'inf', 'the tag type is inf');
- assert.strictEqual(element.duration, 15, 'the duration is parsed');
- assert.ok(!('title' in element), 'no title is parsed');
- manifest = '#EXTINF:21,\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'inf', 'the tag type is inf');
- assert.strictEqual(element.duration, 21, 'the duration is parsed');
- assert.ok(!('title' in element), 'no title is parsed');
- });
- QUnit.test('parses #EXTINF tags with a duration and title', function(assert) {
- const manifest = '#EXTINF:13,Does anyone really use the title attribute?\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'inf', 'the tag type is inf');
- assert.strictEqual(element.duration, 13, 'the duration is parsed');
- assert.strictEqual(
- element.title,
- manifest.substring(manifest.indexOf(',') + 1, manifest.length - 1),
- 'the title is parsed'
- );
- });
- QUnit.test('parses #EXTINF tags with carriage returns', function(assert) {
- const manifest = '#EXTINF:13,Does anyone really use the title attribute?\r\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'inf', 'the tag type is inf');
- assert.strictEqual(element.duration, 13, 'the duration is parsed');
- assert.strictEqual(
- element.title,
- manifest.substring(manifest.indexOf(',') + 1, manifest.length - 2),
- 'the title is parsed'
- );
- });
- // #EXT-X-TARGETDURATION
- QUnit.test('parses minimal #EXT-X-TARGETDURATION tags', function(assert) {
- const manifest = '#EXT-X-TARGETDURATION:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'targetduration', 'the tag type is targetduration');
- assert.ok(!('duration' in element), 'no duration is parsed');
- });
- QUnit.test('parses #EXT-X-TARGETDURATION with duration', function(assert) {
- const manifest = '#EXT-X-TARGETDURATION:47\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'targetduration', 'the tag type is targetduration');
- assert.strictEqual(element.duration, 47, 'the duration is parsed');
- });
- // #EXT-X-VERSION
- QUnit.test('parses minimal #EXT-X-VERSION tags', function(assert) {
- const manifest = '#EXT-X-VERSION:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'version', 'the tag type is version');
- assert.ok(!('version' in element), 'no version is present');
- });
- QUnit.test('parses #EXT-X-VERSION with a version', function(assert) {
- const manifest = '#EXT-X-VERSION:99\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'version', 'the tag type is version');
- assert.strictEqual(element.version, 99, 'the version is parsed');
- });
- // #EXT-X-MEDIA-SEQUENCE
- QUnit.test('parses minimal #EXT-X-MEDIA-SEQUENCE tags', function(assert) {
- const manifest = '#EXT-X-MEDIA-SEQUENCE:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'media-sequence', 'the tag type is media-sequence');
- assert.ok(!('number' in element), 'no number is present');
- });
- QUnit.test('parses #EXT-X-MEDIA-SEQUENCE with sequence numbers', function(assert) {
- const manifest = '#EXT-X-MEDIA-SEQUENCE:109\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'media-sequence', 'the tag type is media-sequence');
- assert.ok(element.number, 109, 'the number is parsed');
- });
- // #EXT-X-PLAYLIST-TYPE
- QUnit.test('parses minimal #EXT-X-PLAYLIST-TYPE tags', function(assert) {
- const manifest = '#EXT-X-PLAYLIST-TYPE:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
- assert.ok(!('playlistType' in element), 'no playlist type is present');
- });
- QUnit.test('parses #EXT-X-PLAYLIST-TYPE with mutability info', function(assert) {
- let manifest = '#EXT-X-PLAYLIST-TYPE:EVENT\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
- assert.strictEqual(element.playlistType, 'EVENT', 'the playlist type is EVENT');
- manifest = '#EXT-X-PLAYLIST-TYPE:VOD\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
- assert.strictEqual(element.playlistType, 'VOD', 'the playlist type is VOD');
- manifest = '#EXT-X-PLAYLIST-TYPE:nonsense\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
- assert.strictEqual(element.playlistType, 'nonsense', 'the playlist type is parsed');
- });
- // #EXT-X-BYTERANGE
- QUnit.test('parses minimal #EXT-X-BYTERANGE tags', function(assert) {
- const manifest = '#EXT-X-BYTERANGE:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
- assert.ok(!('length' in element), 'no length is present');
- assert.ok(!('offset' in element), 'no offset is present');
- });
- QUnit.test('parses #EXT-X-BYTERANGE with length and offset', function(assert) {
- let manifest = '#EXT-X-BYTERANGE:45\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
- assert.strictEqual(element.length, 45, 'length is parsed');
- assert.ok(!('offset' in element), 'no offset is present');
- manifest = '#EXT-X-BYTERANGE:108@16\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
- assert.strictEqual(element.length, 108, 'length is parsed');
- assert.strictEqual(element.offset, 16, 'offset is parsed');
- });
- // #EXT-X-ALLOW-CACHE
- QUnit.test('parses minimal #EXT-X-ALLOW-CACHE tags', function(assert) {
- const manifest = '#EXT-X-ALLOW-CACHE:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
- assert.ok(!('allowed' in element), 'no allowed is present');
- });
- QUnit.test('parses valid #EXT-X-ALLOW-CACHE tags', function(assert) {
- let manifest = '#EXT-X-ALLOW-CACHE:YES\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
- assert.ok(element.allowed, 'allowed is parsed');
- manifest = '#EXT-X-ALLOW-CACHE:NO\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
- assert.ok(!element.allowed, 'allowed is parsed');
- });
- // #EXT-X-MAP
- QUnit.test('parses minimal #EXT-X-MAP tags', function(assert) {
- const manifest = '#EXT-X-MAP:URI="init.m4s"\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'map', 'the tag type is map');
- assert.strictEqual(element.uri, 'init.m4s', 'parsed the uri');
- });
- QUnit.test('parses #EXT-X-MAP tags with a byterange', function(assert) {
- const manifest = '#EXT-X-MAP:URI="0.m4s", BYTERANGE="1000@23"\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.uri, '0.m4s', 'parsed the uri');
- assert.strictEqual(
- element.byterange.length,
- 1000,
- 'parsed the byterange length'
- );
- assert.strictEqual(
- element.byterange.offset,
- 23,
- 'parsed the byterange offset'
- );
- });
- QUnit.test('parses #EXT-X-MAP tags with arbitrary attributes', function(assert) {
- const manifest = '#EXT-X-MAP:URI="init.mp4", SOMETHING=YES,BYTERANGE="720@0"\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.uri, 'init.mp4', 'parsed the uri');
- assert.strictEqual(
- element.byterange.length,
- 720,
- 'parsed the byterange length'
- );
- assert.strictEqual(
- element.byterange.offset,
- 0,
- 'parsed the byterange offset'
- );
- });
- // #EXT-X-STREAM-INF
- QUnit.test('parses minimal #EXT-X-STREAM-INF tags', function(assert) {
- const manifest = '#EXT-X-STREAM-INF:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.ok(!('attributes' in element), 'no attributes are present');
- });
- // #EXT-X-PROGRAM-DATE-TIME
- QUnit.test('parses minimal EXT-X-PROGRAM-DATE-TIME tags', function(assert) {
- const manifest = '#EXT-X-PROGRAM-DATE-TIME:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'program-date-time', 'the tag type is date-time');
- assert.ok(!('dateTimeString' in element), 'no dateTime is present');
- });
- QUnit.test(
- 'parses EXT-X-PROGRAM-DATE-TIME tags with valid date-time formats',
- function(assert) {
- let manifest = '#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:16.166-04:00\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'program-date-time', 'the tag type is date-time');
- assert.strictEqual(
- element.dateTimeString, '2016-06-22T09:20:16.166-04:00',
- 'dateTimeString is parsed'
- );
- assert.deepEqual(
- element.dateTimeObject, new Date('2016-06-22T09:20:16.166-04:00'),
- 'dateTimeObject is parsed'
- );
- manifest = '#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:16.16389Z\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'program-date-time', 'the tag type is date-time');
- assert.strictEqual(
- element.dateTimeString, '2016-06-22T09:20:16.16389Z',
- 'dateTimeString is parsed'
- );
- assert.deepEqual(
- element.dateTimeObject, new Date('2016-06-22T09:20:16.16389Z'),
- 'dateTimeObject is parsed'
- );
- }
- );
- QUnit.test('parses #EXT-X-STREAM-INF with common attributes', function(assert) {
- let manifest = '#EXT-X-STREAM-INF:BANDWIDTH=14400\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.strictEqual(element.attributes.BANDWIDTH, 14400, 'bandwidth is parsed');
- manifest = '#EXT-X-STREAM-INF:PROGRAM-ID=7\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.strictEqual(element.attributes['PROGRAM-ID'], 7, 'program-id is parsed');
- manifest = '#EXT-X-STREAM-INF:RESOLUTION=396x224\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.strictEqual(element.attributes.RESOLUTION.width, 396, 'width is parsed');
- assert.strictEqual(element.attributes.RESOLUTION.height, 224, 'heigth is parsed');
- manifest = '#EXT-X-STREAM-INF:CODECS="avc1.4d400d, mp4a.40.2"\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.strictEqual(
- element.attributes.CODECS,
- 'avc1.4d400d, mp4a.40.2',
- 'codecs are parsed'
- );
- });
- QUnit.test('parses #EXT-X-STREAM-INF with arbitrary attributes', function(assert) {
- const manifest = '#EXT-X-STREAM-INF:NUMERIC=24,ALPHA=Value,MIXED=123abc\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
- assert.strictEqual(element.attributes.NUMERIC, '24', 'numeric attributes are parsed');
- assert.strictEqual(
- element.attributes.ALPHA,
- 'Value',
- 'alphabetic attributes are parsed'
- );
- assert.strictEqual(element.attributes.MIXED, '123abc', 'mixed attributes are parsed');
- });
- // #EXT-X-ENDLIST
- QUnit.test('parses #EXT-X-ENDLIST tags', function(assert) {
- const manifest = '#EXT-X-ENDLIST\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'endlist', 'the tag type is stream-inf');
- });
- // #EXT-X-KEY
- QUnit.test('parses valid #EXT-X-KEY tags', function(assert) {
- let manifest =
- '#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52"\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.deepEqual(element, {
- type: 'tag',
- tagType: 'key',
- attributes: {
- METHOD: 'AES-128',
- URI: 'https://priv.example.com/key.php?r=52'
- }
- }, 'parsed a valid key');
- manifest = '#EXT-X-KEY:URI="https://example.com/key#1",METHOD=FutureType-1024\n';
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.deepEqual(element, {
- type: 'tag',
- tagType: 'key',
- attributes: {
- METHOD: 'FutureType-1024',
- URI: 'https://example.com/key#1'
- }
- }, 'parsed the attribute list independent of order');
- manifest = '#EXT-X-KEY:IV=1234567890abcdef1234567890abcdef\n';
- this.lineStream.push(manifest);
- assert.ok(element.attributes.IV, 'detected an IV attribute');
- assert.deepEqual(element.attributes.IV, new Uint32Array([
- 0x12345678,
- 0x90abcdef,
- 0x12345678,
- 0x90abcdef
- ]), 'parsed an IV value');
- });
- QUnit.test('parses minimal #EXT-X-KEY tags', function(assert) {
- const manifest = '#EXT-X-KEY:\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.deepEqual(element, {
- type: 'tag',
- tagType: 'key'
- }, 'parsed a minimal key tag');
- });
- QUnit.test('parses lightly-broken #EXT-X-KEY tags', function(assert) {
- let manifest = '#EXT-X-KEY:URI=\'https://example.com/single-quote\',METHOD=AES-128\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.strictEqual(
- element.attributes.URI,
- 'https://example.com/single-quote',
- 'parsed a single-quoted uri'
- );
- element = null;
- manifest = '#EXT-X-KEY: URI = "https://example.com/key",METHOD=AES-128\n';
- this.lineStream.push(manifest);
- assert.strictEqual(
- element.attributes.URI,
- 'https://example.com/key',
- 'trims and removes quotes around the URI'
- );
- });
- QUnit.test('parses prefixed with 0x or 0X #EXT-X-KEY:IV tags', function(assert) {
- let manifest;
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- manifest = '#EXT-X-KEY:IV=0x1234567890abcdef1234567890abcdef\n';
- this.lineStream.push(manifest);
- assert.ok(element.attributes.IV, 'detected an IV attribute');
- assert.deepEqual(element.attributes.IV, new Uint32Array([
- 0x12345678,
- 0x90abcdef,
- 0x12345678,
- 0x90abcdef
- ]), 'parsed an IV value with 0x');
- manifest = '#EXT-X-KEY:IV=0X1234567890abcdef1234567890abcdef\n';
- this.lineStream.push(manifest);
- assert.ok(element.attributes.IV, 'detected an IV attribute');
- assert.deepEqual(element.attributes.IV, new Uint32Array([
- 0x12345678,
- 0x90abcdef,
- 0x12345678,
- 0x90abcdef
- ]), 'parsed an IV value with 0X');
- });
- // #EXT-X-START
- QUnit.test('parses EXT-X-START tags', function(assert) {
- const manifest = '#EXT-X-START:TIME-OFFSET=1.1\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'start', 'the tag type is start');
- assert.strictEqual(element.attributes['TIME-OFFSET'], 1.1, 'parses time offset');
- assert.strictEqual(element.attributes.PRECISE, false, 'precise defaults to false');
- });
- QUnit.test('parses EXT-X-START PRECISE attribute', function(assert) {
- const manifest = '#EXT-X-START:TIME-OFFSET=1.4,PRECISE=YES\n';
- let element;
- this.parseStream.on('data', function(elem) {
- element = elem;
- });
- this.lineStream.push(manifest);
- assert.ok(element, 'an event was triggered');
- assert.strictEqual(element.type, 'tag', 'the line type is tag');
- assert.strictEqual(element.tagType, 'start', 'the tag type is start');
- assert.strictEqual(element.attributes['TIME-OFFSET'], 1.4, 'parses time offset');
- assert.strictEqual(element.attributes.PRECISE, true, 'parses precise attribute');
- });
- QUnit.test('ignores empty lines', function(assert) {
- const manifest = '\n';
- let event = false;
- this.parseStream.on('data', function() {
- event = true;
- });
- this.lineStream.push(manifest);
- assert.ok(!event, 'no event is triggered');
- });
|