import { inheritAttributes, buildBaseUrls, getSegmentInformation } from '../src/inheritAttributes'; import { stringToMpdXml } from '../src/stringToMpdXml'; import errors from '../src/errors'; import QUnit from 'qunit'; import { toPlaylists } from '../src/toPlaylists'; QUnit.module('buildBaseUrls'); QUnit.test('returns reference urls when no BaseURL nodes', function(assert) { const reference = ['https://example.com/', 'https://foo.com/']; assert.deepEqual(buildBaseUrls(reference, []), reference, 'returns reference urls'); }); QUnit.test('single reference url with single BaseURL node', function(assert) { const reference = ['https://example.com']; const node = [{ textContent: 'bar/' }]; const expected = ['https://example.com/bar/']; assert.deepEqual(buildBaseUrls(reference, node), expected, 'builds base url'); }); QUnit.test('multiple reference urls with single BaseURL node', function(assert) { const reference = ['https://example.com/', 'https://foo.com/']; const node = [{ textContent: 'bar/' }]; const expected = ['https://example.com/bar/', 'https://foo.com/bar/']; assert.deepEqual( buildBaseUrls(reference, node), expected, 'base url for each reference url' ); }); QUnit.test('multiple BaseURL nodes with single reference url', function(assert) { const reference = ['https://example.com/']; const nodes = [{ textContent: 'bar/' }, { textContent: 'baz/' }]; const expected = ['https://example.com/bar/', 'https://example.com/baz/']; assert.deepEqual(buildBaseUrls(reference, nodes), expected, 'base url for each node'); }); QUnit.test('multiple reference urls with multiple BaseURL nodes', function(assert) { const reference = ['https://example.com/', 'https://foo.com/', 'http://example.com']; const nodes = [{ textContent: 'bar/' }, { textContent: 'baz/' }, { textContent: 'buzz/' }]; const expected = [ 'https://example.com/bar/', 'https://example.com/baz/', 'https://example.com/buzz/', 'https://foo.com/bar/', 'https://foo.com/baz/', 'https://foo.com/buzz/', 'http://example.com/bar/', 'http://example.com/baz/', 'http://example.com/buzz/' ]; assert.deepEqual(buildBaseUrls(reference, nodes), expected, 'creates all base urls'); }); QUnit.test('absolute BaseURL overwrites reference', function(assert) { const reference = ['https://example.com']; const node = [{ textContent: 'https://foo.com/bar/' }]; const expected = ['https://foo.com/bar/']; assert.deepEqual( buildBaseUrls(reference, node), expected, 'absolute url overwrites reference' ); }); QUnit.module('getSegmentInformation'); QUnit.test('undefined Segment information when no Segment nodes', function(assert) { const adaptationSet = { childNodes: [] }; const expected = {}; assert.deepEqual( getSegmentInformation(adaptationSet), expected, 'undefined segment info' ); }); QUnit.test('gets SegmentTemplate attributes', function(assert) { const adaptationSet = { childNodes: [{ tagName: 'SegmentTemplate', attributes: [{ name: 'media', value: 'video.mp4' }], childNodes: [] }] }; const expected = { template: { media: 'video.mp4' } }; assert.deepEqual( getSegmentInformation(adaptationSet), expected, 'SegmentTemplate info' ); }); QUnit.test('gets SegmentList attributes', function(assert) { const adaptationSet = { childNodes: [{ tagName: 'SegmentList', attributes: [{ name: 'duration', value: '10' }], childNodes: [] }] }; const expected = { list: { duration: 10, segmentUrls: [], initialization: {} } }; assert.deepEqual( getSegmentInformation(adaptationSet), expected, 'SegmentList info' ); }); QUnit.test('gets SegmentBase attributes', function(assert) { const adaptationSet = { childNodes: [{ tagName: 'SegmentBase', attributes: [{ name: 'duration', value: '10' }], childNodes: [] }] }; const expected = { base: { duration: 10, initialization: {} } }; assert.deepEqual( getSegmentInformation(adaptationSet), expected, 'SegmentBase info' ); }); QUnit.test('gets SegmentTemplate and SegmentTimeline attributes', function(assert) { const adaptationSet = { childNodes: [{ tagName: 'SegmentTemplate', attributes: [{ name: 'media', value: 'video.mp4' }], childNodes: [{ tagName: 'SegmentTimeline', childNodes: [{ tagName: 'S', attributes: [{ name: 'd', value: '10' }] }, { tagName: 'S', attributes: [{ name: 'd', value: '5' }] }, { tagName: 'S', attributes: [{ name: 'd', value: '7' }] }] }] }] }; const expected = { template: { media: 'video.mp4' }, timeline: [{ d: 10 }, { d: 5 }, { d: 7 }] }; assert.deepEqual( getSegmentInformation(adaptationSet), expected, 'SegmentTemplate and SegmentTimeline info' ); }); QUnit.module('inheritAttributes'); QUnit.test('needs at least one Period', function(assert) { assert.throws( () => inheritAttributes(stringToMpdXml('')), new RegExp(errors.INVALID_NUMBER_OF_PERIOD) ); }); QUnit.test('end to end - basic', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: {} }] }; assert.equal(actual.representationInfo.length, 2); assert.deepEqual(actual, expected); }); QUnit.test('end to end - inherits BaseURL from all levels', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ foo/ bar/ buzz/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/foo/bar/buzz/', clientOffset: 0, codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: { } }] }; assert.equal(actual.representationInfo.length, 2); assert.deepEqual(actual, expected); }); QUnit.test('end to end - alternate BaseURLs', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ https://www.test.com/base/ segments/ media/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/segments/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/media/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 5000000, baseUrl: 'https://www.test.com/base/segments/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 5000000, baseUrl: 'https://www.test.com/base/media/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { template: {} } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: {} }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: {} }] }; assert.equal(actual.representationInfo.length, 6); assert.deepEqual(actual, expected); }); QUnit.test( ' End to End test for checking support of segments in representation', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp6', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '820-2087', indexRangeExact: 'true', initialization: { range: '0-567' } } } }, { attributes: { baseUrl: 'https://www.example.com/base/', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, height: 545, role: { value: 'main' }, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '820-2087', indexRangeExact: 'true', initialization: { range: '0-987' } } } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: {} }] }; assert.equal(actual.representationInfo.length, 3); assert.deepEqual(actual, expected); } ); QUnit.test( ' End to End test for checking support of segments in period ', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp6', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '9999', indexRangeExact: 'false', initialization: { range: '0-1111' } } } }, { attributes: { baseUrl: 'https://www.example.com/base/', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, height: 545, role: { value: 'main' }, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '9999', indexRangeExact: 'false', initialization: { range: '0-1111' } } } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '9999', indexRangeExact: 'false', initialization: { range: '0-1111' } } } }] }; assert.equal(actual.representationInfo.length, 3); assert.deepEqual(actual, expected); } ); QUnit.test( ' End to End test for checking support of Segments in Adaptation set', function(assert) { const NOW = Date.now(); const actual = inheritAttributes(stringToMpdXml(` https://www.example.com/base/ https://example.com/en.vtt `), { NOW }); const expected = { locations: undefined, representationInfo: [{ attributes: { bandwidth: 5000000, baseUrl: 'https://www.example.com/base/', codecs: 'avc1.64001e', height: 404, id: 'test', mediaPresentationDuration: 30, mimeType: 'video/mp6', periodIndex: 0, role: { value: 'main' }, sourceDuration: 30, width: 720, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '1212', indexRangeExact: 'true', initialization: { range: '0-8888' } } } }, { attributes: { baseUrl: 'https://www.example.com/base/', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, height: 545, role: { value: 'main' }, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: { base: { indexRange: '1212', indexRangeExact: 'true', initialization: { range: '0-8888' } } } }, { attributes: { bandwidth: 256, baseUrl: 'https://example.com/en.vtt', id: 'en', lang: 'en', mediaPresentationDuration: 30, mimeType: 'text/vtt', periodIndex: 0, role: {}, sourceDuration: 30, NOW, clientOffset: 0 }, segmentInfo: {} }] }; assert.equal(actual.representationInfo.length, 3); assert.deepEqual(actual, expected); } ); // Although according to the Spec, at most one set of Segment information should be // present at each level, this test would still handle the case and prevent errors if // multiple set of segment information are present at any particular level. QUnit.test( 'Test for checking use of only one set of Segment Information when multiple are present', function(assert) { const NOW = Date.now(); const actual = toPlaylists(inheritAttributes(stringToMpdXml(` https://www.example.com/base `), { NOW }).representationInfo); const expected = [{ attributes: { NOW, bandwidth: 5000000, baseUrl: 'https://www.example.com/base', duration: 1.984, codecs: 'avc1.64001e', height: 404, id: '125000', lang: 'es', mediaPresentationDuration: 30, mimeType: 'video/mp6', periodIndex: 0, startNumber: 0, timescale: 48000, role: { value: 'main' }, clientOffset: 0, initialization: { sourceURL: '$RepresentationID$/es/init.m4f' }, media: '$RepresentationID$/es/$Number$.m4f', segmentAlignment: 'true', sourceDuration: 30, width: 720, startWithSAP: '1' }, segments: [{ duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/0.m4f', timeline: 0, uri: '125000/es/0.m4f', number: 0 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/1.m4f', timeline: 0, uri: '125000/es/1.m4f', number: 1 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/2.m4f', timeline: 0, uri: '125000/es/2.m4f', number: 2 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/3.m4f', timeline: 0, uri: '125000/es/3.m4f', number: 3 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/4.m4f', timeline: 0, uri: '125000/es/4.m4f', number: 4 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/5.m4f', timeline: 0, uri: '125000/es/5.m4f', number: 5 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/6.m4f', timeline: 0, uri: '125000/es/6.m4f', number: 6 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/7.m4f', timeline: 0, uri: '125000/es/7.m4f', number: 7 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/8.m4f', timeline: 0, uri: '125000/es/8.m4f', number: 8 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/9.m4f', timeline: 0, uri: '125000/es/9.m4f', number: 9 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/10.m4f', timeline: 0, uri: '125000/es/10.m4f', number: 10 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/11.m4f', timeline: 0, uri: '125000/es/11.m4f', number: 11 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/12.m4f', timeline: 0, uri: '125000/es/12.m4f', number: 12 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/13.m4f', timeline: 0, uri: '125000/es/13.m4f', number: 13 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/14.m4f', timeline: 0, uri: '125000/es/14.m4f', number: 14 }, { duration: 0.240000000000002, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/15.m4f', timeline: 0, uri: '125000/es/15.m4f', number: 15 }] }, { attributes: { NOW, baseUrl: 'https://www.example.com/base', duration: 1.984, lang: 'es', height: 545, id: '125000', mediaPresentationDuration: 30, mimeType: 'video/mp4', periodIndex: 0, role: { value: 'main' }, segmentAlignment: 'true', sourceDuration: 30, startWithSAP: '1', clientOffset: 0, initialization: { sourceURL: '$RepresentationID$/es/init.m4f' }, media: '$RepresentationID$/es/$Number$.m4f', startNumber: 0, timescale: 48000 }, segments: [{ duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/0.m4f', timeline: 0, uri: '125000/es/0.m4f', number: 0 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/1.m4f', timeline: 0, uri: '125000/es/1.m4f', number: 1 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/2.m4f', timeline: 0, uri: '125000/es/2.m4f', number: 2 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/3.m4f', timeline: 0, uri: '125000/es/3.m4f', number: 3 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/4.m4f', timeline: 0, uri: '125000/es/4.m4f', number: 4 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/5.m4f', timeline: 0, uri: '125000/es/5.m4f', number: 5 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/6.m4f', timeline: 0, uri: '125000/es/6.m4f', number: 6 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/7.m4f', timeline: 0, uri: '125000/es/7.m4f', number: 7 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/8.m4f', timeline: 0, uri: '125000/es/8.m4f', number: 8 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/9.m4f', timeline: 0, uri: '125000/es/9.m4f', number: 9 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/10.m4f', timeline: 0, uri: '125000/es/10.m4f', number: 10 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/11.m4f', timeline: 0, uri: '125000/es/11.m4f', number: 11 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/12.m4f', timeline: 0, uri: '125000/es/12.m4f', number: 12 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/13.m4f', timeline: 0, uri: '125000/es/13.m4f', number: 13 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/14.m4f', timeline: 0, uri: '125000/es/14.m4f', number: 14 }, { duration: 0.240000000000002, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/15.m4f', timeline: 0, uri: '125000/es/15.m4f', number: 15 }] }]; assert.equal(actual.length, 2); assert.deepEqual(actual, expected); } ); // Although the Spec states that if SegmentTemplate or SegmentList is present on one // level of the hierarchy the other one shall not be present on any lower level, this // test would still handle the case if both are present in the hierarchy and would // prevent throwing errors. QUnit.test('Test to check use of either Segment Template or Segment List when both are' + ' present in the hierarchy', function(assert) { const NOW = Date.now(); const actual = toPlaylists(inheritAttributes(stringToMpdXml(` https://www.example.com/base `), { NOW }).representationInfo); const expected = [{ attributes: { NOW, clientOffset: 0, initialization: { sourceURL: '$RepresentationID$/es/init.m4f' }, media: '$RepresentationID$/es/$Number$.m4f', bandwidth: 5000000, baseUrl: 'https://www.example.com/base', duration: 1.984, codecs: 'avc1.64001e', height: 404, id: '125000', lang: 'es', mediaPresentationDuration: 30, mimeType: 'video/mp6', periodIndex: 0, role: { value: 'main' }, segmentAlignment: 'true', sourceDuration: 30, width: 720, startWithSAP: '1', startNumber: 0, timescale: 48000 }, segments: [{ duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/0.m4f', timeline: 0, uri: '125000/es/0.m4f', number: 0 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/1.m4f', timeline: 0, uri: '125000/es/1.m4f', number: 1 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/2.m4f', timeline: 0, uri: '125000/es/2.m4f', number: 2 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/3.m4f', timeline: 0, uri: '125000/es/3.m4f', number: 3 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/4.m4f', timeline: 0, uri: '125000/es/4.m4f', number: 4 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/5.m4f', timeline: 0, uri: '125000/es/5.m4f', number: 5 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/6.m4f', timeline: 0, uri: '125000/es/6.m4f', number: 6 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/7.m4f', timeline: 0, uri: '125000/es/7.m4f', number: 7 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/8.m4f', timeline: 0, uri: '125000/es/8.m4f', number: 8 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/9.m4f', timeline: 0, uri: '125000/es/9.m4f', number: 9 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/10.m4f', timeline: 0, uri: '125000/es/10.m4f', number: 10 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/11.m4f', timeline: 0, uri: '125000/es/11.m4f', number: 11 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/12.m4f', timeline: 0, uri: '125000/es/12.m4f', number: 12 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/13.m4f', timeline: 0, uri: '125000/es/13.m4f', number: 13 }, { duration: 1.984, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/14.m4f', timeline: 0, uri: '125000/es/14.m4f', number: 14 }, { duration: 0.240000000000002, map: { resolvedUri: 'https://www.example.com/125000/es/init.m4f', uri: '125000/es/init.m4f' }, resolvedUri: 'https://www.example.com/125000/es/15.m4f', timeline: 0, uri: '125000/es/15.m4f', number: 15 }] }]; assert.equal(actual.length, 1); assert.deepEqual(actual, expected); });