You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

482 lines
12 KiB

import QUnit from 'qunit';
import window from 'global/window';
import {
setupMediaPlaylists,
resolveMediaGroupUris,
mainForMedia,
addPropertiesToMain,
parseManifest
} from '../src/manifest';
import {
useFakeEnvironment,
urlTo
} from './test-helpers';
QUnit.module('manifest', function() {
QUnit.module('parseManifest');
QUnit.test('sets target duration to largest segment duration', function(assert) {
let manifestString = '#EXTM3U\n' +
'#EXT-X-VERSION:3\n' +
'#EXT-X-PLAYLIST-TYPE:VOD\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n';
for (let i = 0; i < 100; i++) {
manifestString += `#EXTINF:${i + 1},\n`;
manifestString += `segment-${i + 1}.ts\n`;
}
manifestString += '#EXT-X-ENDLIST\n';
const manifest = parseManifest({manifestString});
assert.equal(manifest.targetDuration, 100, 'target duration is 100');
});
QUnit.test('sets target duration to 10 without segments', function(assert) {
let manifestString = '#EXTM3U\n' +
'#EXT-X-VERSION:3\n' +
'#EXT-X-PLAYLIST-TYPE:VOD\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n';
manifestString += '#EXT-X-ENDLIST\n';
const manifest = parseManifest({manifestString});
assert.equal(manifest.targetDuration, 10, 'target duration is 10');
});
QUnit.module('setupMediaPlaylists', {
beforeEach(assert) {
this.env = useFakeEnvironment(assert);
},
afterEach() {
this.env.restore();
}
});
QUnit.test('setupMediaPlaylists does nothing if no playlists', function(assert) {
const main = {
playlists: []
};
setupMediaPlaylists(main);
assert.deepEqual(main, {
playlists: []
}, 'main remains unchanged');
});
QUnit.test('setupMediaPlaylists adds URI keys for each playlist', function(assert) {
const main = {
uri: 'main-uri',
playlists: [{
uri: 'uri-0'
}, {
uri: 'uri-1'
}]
};
const expectedPlaylist0 = {
attributes: {},
resolvedUri: urlTo('uri-0'),
playlistErrors_: 0,
uri: 'uri-0',
id: '0-uri-0'
};
const expectedPlaylist1 = {
attributes: {},
resolvedUri: urlTo('uri-1'),
playlistErrors_: 0,
uri: 'uri-1',
id: '1-uri-1'
};
setupMediaPlaylists(main);
assert.deepEqual(main.playlists[0], expectedPlaylist0, 'retained playlist indices');
assert.deepEqual(main.playlists[1], expectedPlaylist1, 'retained playlist indices');
assert.deepEqual(main.playlists['0-uri-0'], expectedPlaylist0, 'added playlist key');
assert.deepEqual(main.playlists['1-uri-1'], expectedPlaylist1, 'added playlist key');
assert.equal(this.env.log.warn.calls, 2, 'logged two warnings');
assert.equal(
this.env.log.warn.args[0],
'Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.',
'logged a warning'
);
assert.equal(
this.env.log.warn.args[1],
'Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.',
'logged a warning'
);
});
QUnit.test('setupMediaPlaylists adds attributes objects if missing', function(assert) {
const main = {
uri: 'main-uri',
playlists: [{
uri: 'uri-0'
}, {
uri: 'uri-1'
}]
};
setupMediaPlaylists(main);
assert.ok(main.playlists[0].attributes, 'added attributes object');
assert.ok(main.playlists[1].attributes, 'added attributes object');
assert.equal(this.env.log.warn.calls, 2, 'logged two warnings');
assert.equal(
this.env.log.warn.args[0],
'Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.',
'logged a warning'
);
assert.equal(
this.env.log.warn.args[1],
'Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.',
'logged a warning'
);
});
QUnit.test('setupMediaPlaylists resolves playlist URIs', function(assert) {
const main = {
uri: 'main-uri',
playlists: [{
attributes: { BANDWIDTH: 10 },
uri: 'uri-0'
}, {
attributes: { BANDWIDTH: 100 },
uri: 'uri-1'
}]
};
setupMediaPlaylists(main);
assert.equal(main.playlists[0].resolvedUri, urlTo('uri-0'), 'resolves URI');
assert.equal(main.playlists[1].resolvedUri, urlTo('uri-1'), 'resolves URI');
});
QUnit.module('resolveMediaGroupUris');
QUnit.test('resolveMediaGroupUris does nothing when no media groups', function(assert) {
const main = {
uri: 'main-uri',
playlists: [],
mediaGroups: []
};
resolveMediaGroupUris(main);
assert.deepEqual(main, {
uri: 'main-uri',
playlists: [],
mediaGroups: []
}, 'does nothing when no media groups');
});
QUnit.test('resolveMediaGroupUris resolves media group URIs', function(assert) {
const main = {
uri: 'main-uri',
playlists: [{
attributes: { BANDWIDTH: 10 },
id: 'playlist-0',
uri: 'playlist-0'
}],
mediaGroups: {
// CLOSED-CAPTIONS will never have a URI
'CLOSED-CAPTIONS': {
cc1: {
English: {}
}
},
'AUDIO': {
low: {
// audio doesn't need a URI if it is a label for muxed
main: {},
commentary: {
uri: 'audio-low-commentary-uri'
}
},
high: {
main: {},
commentary: {
uri: 'audio-high-commentary-uri'
}
}
},
'SUBTITLES': {
sub1: {
english: {
uri: 'subtitles-1-english-uri'
},
spanish: {
uri: 'subtitles-1-spanish-uri'
}
},
sub2: {
english: {
uri: 'subtitles-2-english-uri'
},
spanish: {
uri: 'subtitles-2-spanish-uri'
}
},
sub3: {
english: {
uri: 'subtitles-3-english-uri'
},
spanish: {
uri: 'subtitles-3-spanish-uri'
}
}
}
}
};
resolveMediaGroupUris(main);
assert.deepEqual(main, {
uri: 'main-uri',
playlists: [{
attributes: { BANDWIDTH: 10 },
id: 'playlist-0',
uri: 'playlist-0'
}],
mediaGroups: {
// CLOSED-CAPTIONS will never have a URI
'CLOSED-CAPTIONS': {
cc1: {
English: {}
}
},
'AUDIO': {
low: {
// audio doesn't need a URI if it is a label for muxed
main: {},
commentary: {
uri: 'audio-low-commentary-uri',
resolvedUri: urlTo('audio-low-commentary-uri')
}
},
high: {
main: {},
commentary: {
uri: 'audio-high-commentary-uri',
resolvedUri: urlTo('audio-high-commentary-uri')
}
}
},
'SUBTITLES': {
sub1: {
english: {
uri: 'subtitles-1-english-uri',
resolvedUri: urlTo('subtitles-1-english-uri')
},
spanish: {
uri: 'subtitles-1-spanish-uri',
resolvedUri: urlTo('subtitles-1-spanish-uri')
}
},
sub2: {
english: {
uri: 'subtitles-2-english-uri',
resolvedUri: urlTo('subtitles-2-english-uri')
},
spanish: {
uri: 'subtitles-2-spanish-uri',
resolvedUri: urlTo('subtitles-2-spanish-uri')
}
},
sub3: {
english: {
uri: 'subtitles-3-english-uri',
resolvedUri: urlTo('subtitles-3-english-uri')
},
spanish: {
uri: 'subtitles-3-spanish-uri',
resolvedUri: urlTo('subtitles-3-spanish-uri')
}
}
}
}
}, 'resolved URIs of certain media groups');
});
QUnit.module('mainForMedia');
QUnit.test('creates a skeleton of a main playlist', function(assert) {
const main = mainForMedia({}, 'some-uri');
assert.deepEqual(
main,
{
mediaGroups: {
'AUDIO': {},
'VIDEO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
uri: window.location.href,
resolvedUri: window.location.href,
playlists: [{
uri: 'some-uri',
id: '0-some-uri',
resolvedUri: 'some-uri',
attributes: {}
}]
},
'created main playlist skeleton'
);
});
QUnit.test('adds by ID reference to playlists array', function(assert) {
const main = mainForMedia({}, 'some-uri');
assert.equal(
main.playlists['0-some-uri'],
main.playlists[0],
'added by ID reference to playlists array'
);
});
QUnit.module('addPropertiesToMain');
QUnit.test('adds uri to main', function(assert) {
const main = {
mediaGroups: {},
playlists: []
};
addPropertiesToMain(main, 'some-uri');
assert.equal(main.uri, 'some-uri', 'added uri to main');
});
QUnit.test('adds placeholder URIs to playlists if necessary', function(assert) {
const main = {
mediaGroups: {},
playlists: [{
uri: 'playlist-0-uri',
attributes: {}
}, {
attributes: {}
}]
};
addPropertiesToMain(main, 'some-uri');
assert.equal(main.playlists[0].uri, 'playlist-0-uri', 'did not overwrite uri');
assert.equal(main.playlists[1].uri, 'placeholder-uri-1', 'added placeholder uri');
});
QUnit.test('adds placeholder URIs to media groups if necessary', function(assert) {
const main = {
mediaGroups: {
AUDIO: {
default: {
en: {
playlists: [{
uri: 'audio-default-uri'
}, {}]
},
es: {
playlists: [{}, {}]
}
}
}
},
playlists: []
};
addPropertiesToMain(main, 'some-uri');
const groups = main.mediaGroups.AUDIO.default;
assert.equal(
groups.en.playlists[0].uri,
'audio-default-uri',
'did not overwrite uri'
);
assert.equal(
groups.en.playlists[1].uri,
'1-placeholder-uri-AUDIO-default-en',
'added placeholder uri with index'
);
assert.equal(
groups.es.playlists[0].uri,
'placeholder-uri-AUDIO-default-es',
'added placeholder uri without index'
);
assert.equal(
groups.es.playlists[1].uri,
'1-placeholder-uri-AUDIO-default-es',
'added placeholder with index uri'
);
assert.equal(
groups.en.playlists[0].id,
'0-placeholder-uri-AUDIO-default-en',
'added placeholder id with index'
);
assert.equal(
groups.en.playlists[1].id,
'1-placeholder-uri-AUDIO-default-en',
'added placeholder id with index'
);
assert.equal(
groups.es.playlists[0].id,
'0-placeholder-uri-AUDIO-default-es',
'added placeholder id with index'
);
assert.equal(
groups.es.playlists[1].id,
'1-placeholder-uri-AUDIO-default-es',
'added placeholder with index id'
);
});
QUnit.test('adds resolvedUri for media group URIs', function(assert) {
const main = {
mediaGroups: {
AUDIO: {
default: {
en: { uri: 'audio-default-uri' },
es: {}
}
}
},
playlists: []
};
addPropertiesToMain(main, 'some-uri');
assert.equal(
main.mediaGroups.AUDIO.default.en.resolvedUri,
urlTo('audio-default-uri'),
'added resolvedUri'
);
assert.notOk(
main.mediaGroups.AUDIO.default.es.resolvedUri,
'did not add resolvedUri when no uri'
);
});
});
QUnit.test('does not add placeholder properties if playlist is a main playlist', function(assert) {
const main = {
mediaGroups: {
AUDIO: {
default: {
en: {default: true}
}
}
},
playlists: [
{uri: 'foo', attributes: {AUDIO: 'default', CODECS: 'mp4a.40.2', BANDWIDTH: 20}}
]
};
addPropertiesToMain(main, 'some-uri');
assert.notOk(main.mediaGroups.AUDIO.default.en.playlists, 'did not add playlists');
});