diff --git a/package.json b/package.json index cbe0ff0..ba59761 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "ignore": [ "dist", "docs", - "test/dist" + "test/dist", + "test/fixtures" ] }, "files": [ diff --git a/scripts/export-m3u8s.js b/scripts/export-m3u8s.js index e1c00e4..8842061 100644 --- a/scripts/export-m3u8s.js +++ b/scripts/export-m3u8s.js @@ -6,7 +6,7 @@ const path = require('path'); const basePath = path.resolve(__dirname, '..'); const testDataDir = path.join(basePath, 'test'); -const manifestDir = path.join(basePath, 'test', 'fixtures', 'm3u8'); +const manifestDir = path.join(basePath, 'test', 'fixtures', 'integration'); const manifestFilepath = path.join(testDataDir, 'dist', 'test-manifests.js'); const expectedFilepath = path.join(testDataDir, 'dist', 'test-expected.js'); @@ -32,9 +32,9 @@ const build = function() { // strip leading spaces and the trailing '+' .slice(4, -3); manifests += ',\n'; - } else if (extname === '.json') { + } else if (extname === '.js') { // append the expected parse - expected += ' "' + path.basename(file, '.json') + '": '; + expected += ' "' + path.basename(file, '.js') + '": '; expected += fs.readFileSync(file, 'utf8'); expected += ',\n'; } else { diff --git a/test/fixtures/m3u8/absoluteUris.json b/test/fixtures/integration/absoluteUris.js similarity index 100% rename from test/fixtures/m3u8/absoluteUris.json rename to test/fixtures/integration/absoluteUris.js diff --git a/test/fixtures/m3u8/absoluteUris.m3u8 b/test/fixtures/integration/absoluteUris.m3u8 similarity index 100% rename from test/fixtures/m3u8/absoluteUris.m3u8 rename to test/fixtures/integration/absoluteUris.m3u8 diff --git a/test/fixtures/m3u8/allowCache.json b/test/fixtures/integration/allowCache.js similarity index 100% rename from test/fixtures/m3u8/allowCache.json rename to test/fixtures/integration/allowCache.js diff --git a/test/fixtures/m3u8/allowCache.m3u8 b/test/fixtures/integration/allowCache.m3u8 similarity index 100% rename from test/fixtures/m3u8/allowCache.m3u8 rename to test/fixtures/integration/allowCache.m3u8 diff --git a/test/fixtures/m3u8/allowCacheInvalid.json b/test/fixtures/integration/allowCacheInvalid.js similarity index 100% rename from test/fixtures/m3u8/allowCacheInvalid.json rename to test/fixtures/integration/allowCacheInvalid.js diff --git a/test/fixtures/m3u8/allowCacheInvalid.m3u8 b/test/fixtures/integration/allowCacheInvalid.m3u8 similarity index 100% rename from test/fixtures/m3u8/allowCacheInvalid.m3u8 rename to test/fixtures/integration/allowCacheInvalid.m3u8 diff --git a/test/fixtures/m3u8/alternateAudio.json b/test/fixtures/integration/alternateAudio.js similarity index 100% rename from test/fixtures/m3u8/alternateAudio.json rename to test/fixtures/integration/alternateAudio.js diff --git a/test/fixtures/m3u8/alternateAudio.m3u8 b/test/fixtures/integration/alternateAudio.m3u8 similarity index 100% rename from test/fixtures/m3u8/alternateAudio.m3u8 rename to test/fixtures/integration/alternateAudio.m3u8 diff --git a/test/fixtures/m3u8/alternateVideo.json b/test/fixtures/integration/alternateVideo.js similarity index 100% rename from test/fixtures/m3u8/alternateVideo.json rename to test/fixtures/integration/alternateVideo.js diff --git a/test/fixtures/m3u8/alternateVideo.m3u8 b/test/fixtures/integration/alternateVideo.m3u8 similarity index 100% rename from test/fixtures/m3u8/alternateVideo.m3u8 rename to test/fixtures/integration/alternateVideo.m3u8 diff --git a/test/fixtures/m3u8/brightcove.json b/test/fixtures/integration/brightcove.js similarity index 100% rename from test/fixtures/m3u8/brightcove.json rename to test/fixtures/integration/brightcove.js diff --git a/test/fixtures/m3u8/brightcove.m3u8 b/test/fixtures/integration/brightcove.m3u8 similarity index 100% rename from test/fixtures/m3u8/brightcove.m3u8 rename to test/fixtures/integration/brightcove.m3u8 diff --git a/test/fixtures/m3u8/byteRange.json b/test/fixtures/integration/byteRange.js similarity index 100% rename from test/fixtures/m3u8/byteRange.json rename to test/fixtures/integration/byteRange.js diff --git a/test/fixtures/m3u8/byteRange.m3u8 b/test/fixtures/integration/byteRange.m3u8 similarity index 100% rename from test/fixtures/m3u8/byteRange.m3u8 rename to test/fixtures/integration/byteRange.m3u8 diff --git a/test/fixtures/m3u8/dateTime.json b/test/fixtures/integration/dateTime.js similarity index 100% rename from test/fixtures/m3u8/dateTime.json rename to test/fixtures/integration/dateTime.js diff --git a/test/fixtures/m3u8/dateTime.m3u8 b/test/fixtures/integration/dateTime.m3u8 similarity index 100% rename from test/fixtures/m3u8/dateTime.m3u8 rename to test/fixtures/integration/dateTime.m3u8 diff --git a/test/fixtures/m3u8/disallowCache.json b/test/fixtures/integration/disallowCache.js similarity index 100% rename from test/fixtures/m3u8/disallowCache.json rename to test/fixtures/integration/disallowCache.js diff --git a/test/fixtures/m3u8/disallowCache.m3u8 b/test/fixtures/integration/disallowCache.m3u8 similarity index 100% rename from test/fixtures/m3u8/disallowCache.m3u8 rename to test/fixtures/integration/disallowCache.m3u8 diff --git a/test/fixtures/m3u8/disc-sequence.json b/test/fixtures/integration/disc-sequence.js similarity index 100% rename from test/fixtures/m3u8/disc-sequence.json rename to test/fixtures/integration/disc-sequence.js diff --git a/test/fixtures/m3u8/disc-sequence.m3u8 b/test/fixtures/integration/disc-sequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/disc-sequence.m3u8 rename to test/fixtures/integration/disc-sequence.m3u8 diff --git a/test/fixtures/m3u8/discontinuity.json b/test/fixtures/integration/discontinuity.js similarity index 100% rename from test/fixtures/m3u8/discontinuity.json rename to test/fixtures/integration/discontinuity.js diff --git a/test/fixtures/m3u8/discontinuity.m3u8 b/test/fixtures/integration/discontinuity.m3u8 similarity index 100% rename from test/fixtures/m3u8/discontinuity.m3u8 rename to test/fixtures/integration/discontinuity.m3u8 diff --git a/test/fixtures/m3u8/domainUris.json b/test/fixtures/integration/domainUris.js similarity index 100% rename from test/fixtures/m3u8/domainUris.json rename to test/fixtures/integration/domainUris.js diff --git a/test/fixtures/m3u8/domainUris.m3u8 b/test/fixtures/integration/domainUris.m3u8 similarity index 100% rename from test/fixtures/m3u8/domainUris.m3u8 rename to test/fixtures/integration/domainUris.m3u8 diff --git a/test/fixtures/m3u8/empty.json b/test/fixtures/integration/empty.js similarity index 100% rename from test/fixtures/m3u8/empty.json rename to test/fixtures/integration/empty.js diff --git a/test/fixtures/m3u8/empty.m3u8 b/test/fixtures/integration/empty.m3u8 similarity index 100% rename from test/fixtures/m3u8/empty.m3u8 rename to test/fixtures/integration/empty.m3u8 diff --git a/test/fixtures/m3u8/emptyAllowCache.json b/test/fixtures/integration/emptyAllowCache.js similarity index 100% rename from test/fixtures/m3u8/emptyAllowCache.json rename to test/fixtures/integration/emptyAllowCache.js diff --git a/test/fixtures/m3u8/emptyAllowCache.m3u8 b/test/fixtures/integration/emptyAllowCache.m3u8 similarity index 100% rename from test/fixtures/m3u8/emptyAllowCache.m3u8 rename to test/fixtures/integration/emptyAllowCache.m3u8 diff --git a/test/fixtures/m3u8/emptyMediaSequence.json b/test/fixtures/integration/emptyMediaSequence.js similarity index 100% rename from test/fixtures/m3u8/emptyMediaSequence.json rename to test/fixtures/integration/emptyMediaSequence.js diff --git a/test/fixtures/m3u8/emptyMediaSequence.m3u8 b/test/fixtures/integration/emptyMediaSequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/emptyMediaSequence.m3u8 rename to test/fixtures/integration/emptyMediaSequence.m3u8 diff --git a/test/fixtures/m3u8/emptyPlaylistType.json b/test/fixtures/integration/emptyPlaylistType.js similarity index 100% rename from test/fixtures/m3u8/emptyPlaylistType.json rename to test/fixtures/integration/emptyPlaylistType.js diff --git a/test/fixtures/m3u8/emptyPlaylistType.m3u8 b/test/fixtures/integration/emptyPlaylistType.m3u8 similarity index 100% rename from test/fixtures/m3u8/emptyPlaylistType.m3u8 rename to test/fixtures/integration/emptyPlaylistType.m3u8 diff --git a/test/fixtures/m3u8/emptyTargetDuration.json b/test/fixtures/integration/emptyTargetDuration.js similarity index 100% rename from test/fixtures/m3u8/emptyTargetDuration.json rename to test/fixtures/integration/emptyTargetDuration.js diff --git a/test/fixtures/m3u8/emptyTargetDuration.m3u8 b/test/fixtures/integration/emptyTargetDuration.m3u8 similarity index 100% rename from test/fixtures/m3u8/emptyTargetDuration.m3u8 rename to test/fixtures/integration/emptyTargetDuration.m3u8 diff --git a/test/fixtures/m3u8/encrypted.json b/test/fixtures/integration/encrypted.js similarity index 100% rename from test/fixtures/m3u8/encrypted.json rename to test/fixtures/integration/encrypted.js diff --git a/test/fixtures/m3u8/encrypted.m3u8 b/test/fixtures/integration/encrypted.m3u8 similarity index 100% rename from test/fixtures/m3u8/encrypted.m3u8 rename to test/fixtures/integration/encrypted.m3u8 diff --git a/test/fixtures/m3u8/event.json b/test/fixtures/integration/event.js similarity index 100% rename from test/fixtures/m3u8/event.json rename to test/fixtures/integration/event.js diff --git a/test/fixtures/m3u8/event.m3u8 b/test/fixtures/integration/event.m3u8 similarity index 100% rename from test/fixtures/m3u8/event.m3u8 rename to test/fixtures/integration/event.m3u8 diff --git a/test/fixtures/m3u8/extXPlaylistTypeInvalidPlaylist.json b/test/fixtures/integration/extXPlaylistTypeInvalidPlaylist.js similarity index 100% rename from test/fixtures/m3u8/extXPlaylistTypeInvalidPlaylist.json rename to test/fixtures/integration/extXPlaylistTypeInvalidPlaylist.js diff --git a/test/fixtures/m3u8/extXPlaylistTypeInvalidPlaylist.m3u8 b/test/fixtures/integration/extXPlaylistTypeInvalidPlaylist.m3u8 similarity index 100% rename from test/fixtures/m3u8/extXPlaylistTypeInvalidPlaylist.m3u8 rename to test/fixtures/integration/extXPlaylistTypeInvalidPlaylist.m3u8 diff --git a/test/fixtures/m3u8/extinf.json b/test/fixtures/integration/extinf.js similarity index 100% rename from test/fixtures/m3u8/extinf.json rename to test/fixtures/integration/extinf.js diff --git a/test/fixtures/m3u8/extinf.m3u8 b/test/fixtures/integration/extinf.m3u8 similarity index 100% rename from test/fixtures/m3u8/extinf.m3u8 rename to test/fixtures/integration/extinf.m3u8 diff --git a/test/fixtures/m3u8/fmp4.json b/test/fixtures/integration/fmp4.js similarity index 100% rename from test/fixtures/m3u8/fmp4.json rename to test/fixtures/integration/fmp4.js diff --git a/test/fixtures/m3u8/fmp4.m3u8 b/test/fixtures/integration/fmp4.m3u8 similarity index 100% rename from test/fixtures/m3u8/fmp4.m3u8 rename to test/fixtures/integration/fmp4.m3u8 diff --git a/test/fixtures/m3u8/headerOnly.json b/test/fixtures/integration/headerOnly.js similarity index 100% rename from test/fixtures/m3u8/headerOnly.json rename to test/fixtures/integration/headerOnly.js diff --git a/test/fixtures/m3u8/headerOnly.m3u8 b/test/fixtures/integration/headerOnly.m3u8 similarity index 100% rename from test/fixtures/m3u8/headerOnly.m3u8 rename to test/fixtures/integration/headerOnly.m3u8 diff --git a/test/fixtures/m3u8/invalidAllowCache.json b/test/fixtures/integration/invalidAllowCache.js similarity index 100% rename from test/fixtures/m3u8/invalidAllowCache.json rename to test/fixtures/integration/invalidAllowCache.js diff --git a/test/fixtures/m3u8/invalidAllowCache.m3u8 b/test/fixtures/integration/invalidAllowCache.m3u8 similarity index 100% rename from test/fixtures/m3u8/invalidAllowCache.m3u8 rename to test/fixtures/integration/invalidAllowCache.m3u8 diff --git a/test/fixtures/m3u8/invalidMediaSequence.json b/test/fixtures/integration/invalidMediaSequence.js similarity index 100% rename from test/fixtures/m3u8/invalidMediaSequence.json rename to test/fixtures/integration/invalidMediaSequence.js diff --git a/test/fixtures/m3u8/invalidMediaSequence.m3u8 b/test/fixtures/integration/invalidMediaSequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/invalidMediaSequence.m3u8 rename to test/fixtures/integration/invalidMediaSequence.m3u8 diff --git a/test/fixtures/m3u8/invalidPlaylistType.json b/test/fixtures/integration/invalidPlaylistType.js similarity index 100% rename from test/fixtures/m3u8/invalidPlaylistType.json rename to test/fixtures/integration/invalidPlaylistType.js diff --git a/test/fixtures/m3u8/invalidPlaylistType.m3u8 b/test/fixtures/integration/invalidPlaylistType.m3u8 similarity index 100% rename from test/fixtures/m3u8/invalidPlaylistType.m3u8 rename to test/fixtures/integration/invalidPlaylistType.m3u8 diff --git a/test/fixtures/m3u8/invalidTargetDuration.json b/test/fixtures/integration/invalidTargetDuration.js similarity index 100% rename from test/fixtures/m3u8/invalidTargetDuration.json rename to test/fixtures/integration/invalidTargetDuration.js diff --git a/test/fixtures/m3u8/invalidTargetDuration.m3u8 b/test/fixtures/integration/invalidTargetDuration.m3u8 similarity index 100% rename from test/fixtures/m3u8/invalidTargetDuration.m3u8 rename to test/fixtures/integration/invalidTargetDuration.m3u8 diff --git a/test/fixtures/m3u8/liveMissingSegmentDuration.json b/test/fixtures/integration/liveMissingSegmentDuration.js similarity index 100% rename from test/fixtures/m3u8/liveMissingSegmentDuration.json rename to test/fixtures/integration/liveMissingSegmentDuration.js diff --git a/test/fixtures/m3u8/liveMissingSegmentDuration.m3u8 b/test/fixtures/integration/liveMissingSegmentDuration.m3u8 similarity index 100% rename from test/fixtures/m3u8/liveMissingSegmentDuration.m3u8 rename to test/fixtures/integration/liveMissingSegmentDuration.m3u8 diff --git a/test/fixtures/m3u8/liveStart30sBefore.json b/test/fixtures/integration/liveStart30sBefore.js similarity index 100% rename from test/fixtures/m3u8/liveStart30sBefore.json rename to test/fixtures/integration/liveStart30sBefore.js diff --git a/test/fixtures/m3u8/liveStart30sBefore.m3u8 b/test/fixtures/integration/liveStart30sBefore.m3u8 similarity index 100% rename from test/fixtures/m3u8/liveStart30sBefore.m3u8 rename to test/fixtures/integration/liveStart30sBefore.m3u8 diff --git a/test/fixtures/m3u8/llhls.json b/test/fixtures/integration/llhls.js similarity index 100% rename from test/fixtures/m3u8/llhls.json rename to test/fixtures/integration/llhls.js diff --git a/test/fixtures/m3u8/llhls.m3u8 b/test/fixtures/integration/llhls.m3u8 similarity index 100% rename from test/fixtures/m3u8/llhls.m3u8 rename to test/fixtures/integration/llhls.m3u8 diff --git a/test/fixtures/m3u8/llhlsDelta.json b/test/fixtures/integration/llhlsDelta.js similarity index 100% rename from test/fixtures/m3u8/llhlsDelta.json rename to test/fixtures/integration/llhlsDelta.js diff --git a/test/fixtures/m3u8/llhlsDelta.m3u8 b/test/fixtures/integration/llhlsDelta.m3u8 similarity index 100% rename from test/fixtures/m3u8/llhlsDelta.m3u8 rename to test/fixtures/integration/llhlsDelta.m3u8 diff --git a/test/fixtures/m3u8/manifestExtTTargetdurationNegative.json b/test/fixtures/integration/manifestExtTTargetdurationNegative.js similarity index 100% rename from test/fixtures/m3u8/manifestExtTTargetdurationNegative.json rename to test/fixtures/integration/manifestExtTTargetdurationNegative.js diff --git a/test/fixtures/m3u8/manifestExtTTargetdurationNegative.m3u8 b/test/fixtures/integration/manifestExtTTargetdurationNegative.m3u8 similarity index 100% rename from test/fixtures/m3u8/manifestExtTTargetdurationNegative.m3u8 rename to test/fixtures/integration/manifestExtTTargetdurationNegative.m3u8 diff --git a/test/fixtures/m3u8/manifestExtXEndlistEarly.json b/test/fixtures/integration/manifestExtXEndlistEarly.js similarity index 100% rename from test/fixtures/m3u8/manifestExtXEndlistEarly.json rename to test/fixtures/integration/manifestExtXEndlistEarly.js diff --git a/test/fixtures/m3u8/manifestExtXEndlistEarly.m3u8 b/test/fixtures/integration/manifestExtXEndlistEarly.m3u8 similarity index 100% rename from test/fixtures/m3u8/manifestExtXEndlistEarly.m3u8 rename to test/fixtures/integration/manifestExtXEndlistEarly.m3u8 diff --git a/test/fixtures/m3u8/manifestNoExtM3u.json b/test/fixtures/integration/manifestNoExtM3u.js similarity index 100% rename from test/fixtures/m3u8/manifestNoExtM3u.json rename to test/fixtures/integration/manifestNoExtM3u.js diff --git a/test/fixtures/m3u8/manifestNoExtM3u.m3u8 b/test/fixtures/integration/manifestNoExtM3u.m3u8 similarity index 100% rename from test/fixtures/m3u8/manifestNoExtM3u.m3u8 rename to test/fixtures/integration/manifestNoExtM3u.m3u8 diff --git a/test/fixtures/m3u8/master-fmp4.json b/test/fixtures/integration/master-fmp4.js similarity index 100% rename from test/fixtures/m3u8/master-fmp4.json rename to test/fixtures/integration/master-fmp4.js diff --git a/test/fixtures/m3u8/master-fmp4.m3u8 b/test/fixtures/integration/master-fmp4.m3u8 similarity index 100% rename from test/fixtures/m3u8/master-fmp4.m3u8 rename to test/fixtures/integration/master-fmp4.m3u8 diff --git a/test/fixtures/m3u8/master.json b/test/fixtures/integration/master.js similarity index 100% rename from test/fixtures/m3u8/master.json rename to test/fixtures/integration/master.js diff --git a/test/fixtures/m3u8/master.m3u8 b/test/fixtures/integration/master.m3u8 similarity index 100% rename from test/fixtures/m3u8/master.m3u8 rename to test/fixtures/integration/master.m3u8 diff --git a/test/fixtures/m3u8/media.json b/test/fixtures/integration/media.js similarity index 100% rename from test/fixtures/m3u8/media.json rename to test/fixtures/integration/media.js diff --git a/test/fixtures/m3u8/media.m3u8 b/test/fixtures/integration/media.m3u8 similarity index 100% rename from test/fixtures/m3u8/media.m3u8 rename to test/fixtures/integration/media.m3u8 diff --git a/test/fixtures/m3u8/mediaSequence.json b/test/fixtures/integration/mediaSequence.js similarity index 100% rename from test/fixtures/m3u8/mediaSequence.json rename to test/fixtures/integration/mediaSequence.js diff --git a/test/fixtures/m3u8/mediaSequence.m3u8 b/test/fixtures/integration/mediaSequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/mediaSequence.m3u8 rename to test/fixtures/integration/mediaSequence.m3u8 diff --git a/test/fixtures/m3u8/missingEndlist.json b/test/fixtures/integration/missingEndlist.js similarity index 100% rename from test/fixtures/m3u8/missingEndlist.json rename to test/fixtures/integration/missingEndlist.js diff --git a/test/fixtures/m3u8/missingEndlist.m3u8 b/test/fixtures/integration/missingEndlist.m3u8 similarity index 100% rename from test/fixtures/m3u8/missingEndlist.m3u8 rename to test/fixtures/integration/missingEndlist.m3u8 diff --git a/test/fixtures/m3u8/missingExtinf.json b/test/fixtures/integration/missingExtinf.js similarity index 100% rename from test/fixtures/m3u8/missingExtinf.json rename to test/fixtures/integration/missingExtinf.js diff --git a/test/fixtures/m3u8/missingExtinf.m3u8 b/test/fixtures/integration/missingExtinf.m3u8 similarity index 100% rename from test/fixtures/m3u8/missingExtinf.m3u8 rename to test/fixtures/integration/missingExtinf.m3u8 diff --git a/test/fixtures/m3u8/missingMediaSequence.json b/test/fixtures/integration/missingMediaSequence.js similarity index 100% rename from test/fixtures/m3u8/missingMediaSequence.json rename to test/fixtures/integration/missingMediaSequence.js diff --git a/test/fixtures/m3u8/missingMediaSequence.m3u8 b/test/fixtures/integration/missingMediaSequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/missingMediaSequence.m3u8 rename to test/fixtures/integration/missingMediaSequence.m3u8 diff --git a/test/fixtures/m3u8/missingSegmentDuration.json b/test/fixtures/integration/missingSegmentDuration.js similarity index 100% rename from test/fixtures/m3u8/missingSegmentDuration.json rename to test/fixtures/integration/missingSegmentDuration.js diff --git a/test/fixtures/m3u8/missingSegmentDuration.m3u8 b/test/fixtures/integration/missingSegmentDuration.m3u8 similarity index 100% rename from test/fixtures/m3u8/missingSegmentDuration.m3u8 rename to test/fixtures/integration/missingSegmentDuration.m3u8 diff --git a/test/fixtures/m3u8/multipleAudioGroups.json b/test/fixtures/integration/multipleAudioGroups.js similarity index 100% rename from test/fixtures/m3u8/multipleAudioGroups.json rename to test/fixtures/integration/multipleAudioGroups.js diff --git a/test/fixtures/m3u8/multipleAudioGroups.m3u8 b/test/fixtures/integration/multipleAudioGroups.m3u8 similarity index 100% rename from test/fixtures/m3u8/multipleAudioGroups.m3u8 rename to test/fixtures/integration/multipleAudioGroups.m3u8 diff --git a/test/fixtures/m3u8/multipleAudioGroupsCombinedMain.json b/test/fixtures/integration/multipleAudioGroupsCombinedMain.js similarity index 100% rename from test/fixtures/m3u8/multipleAudioGroupsCombinedMain.json rename to test/fixtures/integration/multipleAudioGroupsCombinedMain.js diff --git a/test/fixtures/m3u8/multipleAudioGroupsCombinedMain.m3u8 b/test/fixtures/integration/multipleAudioGroupsCombinedMain.m3u8 similarity index 100% rename from test/fixtures/m3u8/multipleAudioGroupsCombinedMain.m3u8 rename to test/fixtures/integration/multipleAudioGroupsCombinedMain.m3u8 diff --git a/test/fixtures/m3u8/multipleTargetDurations.json b/test/fixtures/integration/multipleTargetDurations.js similarity index 100% rename from test/fixtures/m3u8/multipleTargetDurations.json rename to test/fixtures/integration/multipleTargetDurations.js diff --git a/test/fixtures/m3u8/multipleTargetDurations.m3u8 b/test/fixtures/integration/multipleTargetDurations.m3u8 similarity index 100% rename from test/fixtures/m3u8/multipleTargetDurations.m3u8 rename to test/fixtures/integration/multipleTargetDurations.m3u8 diff --git a/test/fixtures/m3u8/multipleVideo.json b/test/fixtures/integration/multipleVideo.js similarity index 100% rename from test/fixtures/m3u8/multipleVideo.json rename to test/fixtures/integration/multipleVideo.js diff --git a/test/fixtures/m3u8/multipleVideo.m3u8 b/test/fixtures/integration/multipleVideo.m3u8 similarity index 100% rename from test/fixtures/m3u8/multipleVideo.m3u8 rename to test/fixtures/integration/multipleVideo.m3u8 diff --git a/test/fixtures/m3u8/negativeMediaSequence.json b/test/fixtures/integration/negativeMediaSequence.js similarity index 100% rename from test/fixtures/m3u8/negativeMediaSequence.json rename to test/fixtures/integration/negativeMediaSequence.js diff --git a/test/fixtures/m3u8/negativeMediaSequence.m3u8 b/test/fixtures/integration/negativeMediaSequence.m3u8 similarity index 100% rename from test/fixtures/m3u8/negativeMediaSequence.m3u8 rename to test/fixtures/integration/negativeMediaSequence.m3u8 diff --git a/test/fixtures/m3u8/playlist.json b/test/fixtures/integration/playlist.js similarity index 100% rename from test/fixtures/m3u8/playlist.json rename to test/fixtures/integration/playlist.js diff --git a/test/fixtures/m3u8/playlist.m3u8 b/test/fixtures/integration/playlist.m3u8 similarity index 100% rename from test/fixtures/m3u8/playlist.m3u8 rename to test/fixtures/integration/playlist.m3u8 diff --git a/test/fixtures/m3u8/playlistMediaSequenceHigher.json b/test/fixtures/integration/playlistMediaSequenceHigher.js similarity index 100% rename from test/fixtures/m3u8/playlistMediaSequenceHigher.json rename to test/fixtures/integration/playlistMediaSequenceHigher.js diff --git a/test/fixtures/m3u8/playlistMediaSequenceHigher.m3u8 b/test/fixtures/integration/playlistMediaSequenceHigher.m3u8 similarity index 100% rename from test/fixtures/m3u8/playlistMediaSequenceHigher.m3u8 rename to test/fixtures/integration/playlistMediaSequenceHigher.m3u8 diff --git a/test/fixtures/m3u8/start.json b/test/fixtures/integration/start.js similarity index 100% rename from test/fixtures/m3u8/start.json rename to test/fixtures/integration/start.js diff --git a/test/fixtures/m3u8/start.m3u8 b/test/fixtures/integration/start.m3u8 similarity index 100% rename from test/fixtures/m3u8/start.m3u8 rename to test/fixtures/integration/start.m3u8 diff --git a/test/fixtures/m3u8/streamInfInvalid.json b/test/fixtures/integration/streamInfInvalid.js similarity index 100% rename from test/fixtures/m3u8/streamInfInvalid.json rename to test/fixtures/integration/streamInfInvalid.js diff --git a/test/fixtures/m3u8/streamInfInvalid.m3u8 b/test/fixtures/integration/streamInfInvalid.m3u8 similarity index 100% rename from test/fixtures/m3u8/streamInfInvalid.m3u8 rename to test/fixtures/integration/streamInfInvalid.m3u8 diff --git a/test/fixtures/m3u8/twoMediaSequences.json b/test/fixtures/integration/twoMediaSequences.js similarity index 100% rename from test/fixtures/m3u8/twoMediaSequences.json rename to test/fixtures/integration/twoMediaSequences.js diff --git a/test/fixtures/m3u8/twoMediaSequences.m3u8 b/test/fixtures/integration/twoMediaSequences.m3u8 similarity index 100% rename from test/fixtures/m3u8/twoMediaSequences.m3u8 rename to test/fixtures/integration/twoMediaSequences.m3u8 diff --git a/test/fixtures/m3u8/versionInvalid.json b/test/fixtures/integration/versionInvalid.js similarity index 100% rename from test/fixtures/m3u8/versionInvalid.json rename to test/fixtures/integration/versionInvalid.js diff --git a/test/fixtures/m3u8/versionInvalid.m3u8 b/test/fixtures/integration/versionInvalid.m3u8 similarity index 100% rename from test/fixtures/m3u8/versionInvalid.m3u8 rename to test/fixtures/integration/versionInvalid.m3u8 diff --git a/test/fixtures/m3u8/whiteSpace.json b/test/fixtures/integration/whiteSpace.js similarity index 100% rename from test/fixtures/m3u8/whiteSpace.json rename to test/fixtures/integration/whiteSpace.js diff --git a/test/fixtures/m3u8/whiteSpace.m3u8 b/test/fixtures/integration/whiteSpace.m3u8 similarity index 100% rename from test/fixtures/m3u8/whiteSpace.m3u8 rename to test/fixtures/integration/whiteSpace.m3u8 diff --git a/test/fixtures/m3u8/zeroDuration.json b/test/fixtures/integration/zeroDuration.js similarity index 100% rename from test/fixtures/m3u8/zeroDuration.json rename to test/fixtures/integration/zeroDuration.js diff --git a/test/fixtures/m3u8/zeroDuration.m3u8 b/test/fixtures/integration/zeroDuration.m3u8 similarity index 100% rename from test/fixtures/m3u8/zeroDuration.m3u8 rename to test/fixtures/integration/zeroDuration.m3u8 diff --git a/test/fixtures/m3u8/media1.m3u8 b/test/fixtures/m3u8/media1.m3u8 deleted file mode 100644 index 68ba8cc..0000000 --- a/test/fixtures/m3u8/media1.m3u8 +++ /dev/null @@ -1,13 +0,0 @@ -#EXTM3U -#EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-TARGETDURATION:10 -#EXTINF:10, -media1-00001.ts -#EXTINF:10, -media1-00002.ts -#EXTINF:10, -media1-00003.ts -#EXTINF:10, -media1-00004.ts -#ZEN-TOTAL-DURATION:57.9911 -#EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/media2.m3u8 b/test/fixtures/m3u8/media2.m3u8 deleted file mode 100644 index ce918e2..0000000 --- a/test/fixtures/m3u8/media2.m3u8 +++ /dev/null @@ -1,13 +0,0 @@ -#EXTM3U -#EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-TARGETDURATION:10 -#EXTINF:10, -media2-00001.ts -#EXTINF:10, -media2-00002.ts -#EXTINF:10, -media2-00003.ts -#EXTINF:10, -media2-00004.ts -#ZEN-TOTAL-DURATION:57.9911 -#EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/media3.m3u8 b/test/fixtures/m3u8/media3.m3u8 deleted file mode 100644 index 399aaeb..0000000 --- a/test/fixtures/m3u8/media3.m3u8 +++ /dev/null @@ -1,13 +0,0 @@ -#EXTM3U -#EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-TARGETDURATION:10 -#EXTINF:10, -media3-00001.ts -#EXTINF:10, -media3-00002.ts -#EXTINF:10, -media3-00003.ts -#EXTINF:10, -media3-00004.ts -#ZEN-TOTAL-DURATION:57.9911 -#EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/playlist_allow_cache_template.m3u8 b/test/fixtures/m3u8/playlist_allow_cache_template.m3u8 deleted file mode 100644 index 931d07d..0000000 --- a/test/fixtures/m3u8/playlist_allow_cache_template.m3u8 +++ /dev/null @@ -1,58 +0,0 @@ -#EXTM3U -#EXT-X-TARGETDURATION:10 -#EXT-X-VERSION:{{{version}}} -{{#if allowCache}}#EXT-X-ALLOW-CACHE:{{{allowCache}}}{{/if}} -#EXT-X-MEDIA-SEQUENCE:0 -#EXT-X-PLAYLIST-TYPE:VOD -#EXTINF:10, -#EXT-X-BYTERANGE:522828@0 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:587500@522828 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:713084@1110328 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:476580@1823412 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:535612@2299992 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:207176@2835604 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:455900@3042780 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:657248@3498680 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:571708@4155928 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:485040@4727636 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:709136@5212676 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:730004@5921812 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:456276@6651816 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:468684@7108092 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:444996@7576776 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:331444@8021772 -hls_450k_video.ts -#EXTINF:1.4167, -#EXT-X-BYTERANGE:44556@8353216 -hls_450k_video.ts -#EXT-X-ENDLIST \ No newline at end of file diff --git a/test/fixtures/m3u8/playlist_byte_range_template.m3u8 b/test/fixtures/m3u8/playlist_byte_range_template.m3u8 deleted file mode 100644 index 1595923..0000000 --- a/test/fixtures/m3u8/playlist_byte_range_template.m3u8 +++ /dev/null @@ -1,60 +0,0 @@ -#EXTM3U -#EXT-X-TARGETDURATION:10 -#EXT-X-VERSION:{{{version}}} -#EXT-X-MEDIA-SEQUENCE:0 -#EXT-X-PLAYLIST-TYPE:VOD -#EXTINF:10, -{{#if byteRange}}#EXT-X-BYTERANGE:{{{byteRange}}}{{/if}} -//#EXT-X-BYTERANGE:522828@0 -hls_450k_video.ts -#EXTINF:10, -{{#if byteRange1}}#EXT-X-BYTERANGE:{{{byteRange1}}}{{/if}} -//#EXT-X-BYTERANGE:587500@522828 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:713084@1110328 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:476580@1823412 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:535612@2299992 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:207176@2835604 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:455900@3042780 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:657248@3498680 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:571708@4155928 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:485040@4727636 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:709136@5212676 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:730004@5921812 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:456276@6651816 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:468684@7108092 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:444996@7576776 -hls_450k_video.ts -#EXTINF:10, -#EXT-X-BYTERANGE:331444@8021772 -hls_450k_video.ts -#EXTINF:1.4167, -{{#if byteRange2}}#EXT-X-BYTERANGE:{{{byteRange2}}}{{/if}} -//#EXT-X-BYTERANGE:44556@8353216 -hls_450k_video.ts -#EXT-X-ENDLIST \ No newline at end of file diff --git a/test/fixtures/m3u8/playlist_extinf_template.m3u8 b/test/fixtures/m3u8/playlist_extinf_template.m3u8 deleted file mode 100644 index 2ead09b..0000000 --- a/test/fixtures/m3u8/playlist_extinf_template.m3u8 +++ /dev/null @@ -1,57 +0,0 @@ -#EXTM3U - #EXT-X-TARGETDURATION:10 - #EXT-X-VERSION:{{{version}}} - #EXT-X-MEDIA-SEQUENCE:0 - #EXT-X-PLAYLIST-TYPE:VOD - {{#if extInf}}#EXTINF:{{{extInf}}}{{/if}} - #EXT-X-BYTERANGE:522828@0 - {{#if segment}}{{{segment}}}\n{{/if}} - {{#if extInf1}}#EXTINF:{{{extInf1}}}{{/if}} - #EXT-X-BYTERANGE:587500@522828 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:713084@1110328 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:476580@1823412 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:535612@2299992 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:207176@2835604 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:455900@3042780 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:657248@3498680 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:571708@4155928 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:485040@4727636 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:709136@5212676 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:730004@5921812 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:456276@6651816 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:468684@7108092 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:444996@7576776 - hls_450k_video.ts - #EXTINF:10, - #EXT-X-BYTERANGE:331444@8021772 - hls_450k_video.ts - {{#if extInf2}}#EXTINF:{{{extInf2}}}{{/if}} - #EXT-X-BYTERANGE:44556@8353216 - hls_450k_video.ts - #EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/playlist_media_sequence_template.m3u8 b/test/fixtures/m3u8/playlist_media_sequence_template.m3u8 deleted file mode 100644 index 37e5a6c..0000000 --- a/test/fixtures/m3u8/playlist_media_sequence_template.m3u8 +++ /dev/null @@ -1,15 +0,0 @@ -#EXTM3U -#EXT-X-PLAYLIST-TYPE:VOD -{{#if mediaSequence}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence}}}{{/if}} -{{#if mediaSequence1}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence2}}}{{/if}} -#EXT-X-ALLOW-CACHE:YES -#EXT-X-TARGETDURATION:8 -#EXTINF:6.640,{} -/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts -#EXTINF:6.080,{} -/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts -#EXTINF:6.600,{} -/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts -#EXTINF:5.000,{} -/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts -#EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/playlist_target_duration_template.m3u8 b/test/fixtures/m3u8/playlist_target_duration_template.m3u8 deleted file mode 100644 index 1183160..0000000 --- a/test/fixtures/m3u8/playlist_target_duration_template.m3u8 +++ /dev/null @@ -1,14 +0,0 @@ -#EXTM3U -#EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-MEDIA-SEQUENCE:0 -#EXT-X-ALLOW-CACHE:YES -{{#if targetDuration}}#EXT-X-TARGETDURATION:{{{targetDuration}}}{{/if}} -#EXTINF:6.640,{} -/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts -#EXTINF:6.080,{} -/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts -#EXTINF:6.600,{} -/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts -#EXTINF:5.000,{} -/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts -#EXT-X-ENDLIST diff --git a/test/fixtures/m3u8/playlist_type_template.m3u8 b/test/fixtures/m3u8/playlist_type_template.m3u8 deleted file mode 100644 index 1c2b0e8..0000000 --- a/test/fixtures/m3u8/playlist_type_template.m3u8 +++ /dev/null @@ -1,17 +0,0 @@ -#EXTM3U -{{#if playlistType}}#EXT-X-PLAYLIST-TYPE:{{{playlistType}}}{{/if}} -#EXT-X-TARGETDURATION:10 -#EXTINF:10, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts -#EXTINF:10, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts -#EXTINF:10, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts -#EXTINF:10, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts -#EXTINF:10, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts -#EXTINF:8, -/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts -#ZEN-TOTAL-DURATION:57.9911 -#EXT-X-ENDLIST diff --git a/test/line-stream.test.js b/test/line-stream.test.js new file mode 100644 index 0000000..32cde92 --- /dev/null +++ b/test/line-stream.test.js @@ -0,0 +1,80 @@ +import {LineStream} from '../src'; +import QUnit from 'qunit'; + +QUnit.module('LineStream', { + beforeEach() { + this.lineStream = new LineStream(); + } +}); +QUnit.test('empty inputs produce no tokens', function(assert) { + let data = false; + + this.lineStream.on('data', function() { + data = true; + }); + this.lineStream.push(''); + assert.ok(!data, 'no tokens were produced'); +}); +QUnit.test('splits on newlines', function(assert) { + const lines = []; + + this.lineStream.on('data', function(line) { + lines.push(line); + }); + this.lineStream.push('#EXTM3U\nmovie.ts\n'); + + assert.strictEqual(2, lines.length, 'two lines are ready'); + assert.strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token'); + assert.strictEqual('movie.ts', lines.shift(), 'the second line is the second token'); +}); +QUnit.test('empty lines become empty strings', function(assert) { + const lines = []; + + this.lineStream.on('data', function(line) { + lines.push(line); + }); + this.lineStream.push('\n\n'); + + assert.strictEqual(2, lines.length, 'two lines are ready'); + assert.strictEqual('', lines.shift(), 'the first line is empty'); + assert.strictEqual('', lines.shift(), 'the second line is empty'); +}); +QUnit.test('handles lines broken across appends', function(assert) { + const lines = []; + + this.lineStream.on('data', function(line) { + lines.push(line); + }); + this.lineStream.push('#EXTM'); + assert.strictEqual(0, lines.length, 'no lines are ready'); + + this.lineStream.push('3U\nmovie.ts\n'); + assert.strictEqual(2, lines.length, 'two lines are ready'); + assert.strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token'); + assert.strictEqual('movie.ts', lines.shift(), 'the second line is the second token'); +}); +QUnit.test('stops sending events after deregistering', function(assert) { + const temporaryLines = []; + const temporary = function(line) { + temporaryLines.push(line); + }; + const permanentLines = []; + const permanent = function(line) { + permanentLines.push(line); + }; + + this.lineStream.on('data', temporary); + this.lineStream.on('data', permanent); + this.lineStream.push('line one\n'); + assert.strictEqual( + temporaryLines.length, + permanentLines.length, + 'both callbacks receive the event' + ); + + assert.ok(this.lineStream.off('data', temporary), 'a listener was removed'); + this.lineStream.push('line two\n'); + assert.strictEqual(1, temporaryLines.length, 'no new events are received'); + assert.strictEqual(2, permanentLines.length, 'new events are still received'); +}); + diff --git a/test/m3u8.test.js b/test/parse-stream.test.js similarity index 66% rename from test/m3u8.test.js rename to test/parse-stream.test.js index 30d737b..c9cf912 100644 --- a/test/m3u8.test.js +++ b/test/parse-stream.test.js @@ -1,85 +1,6 @@ -import {ParseStream, LineStream, Parser} from '../src'; +import {LineStream, ParseStream} from '../src'; import QUnit from 'qunit'; import sinon from 'sinon'; -import testDataExpected from './dist/test-expected.js'; -import testDataManifests from './dist/test-manifests.js'; - -QUnit.module('LineStream', { - beforeEach() { - this.lineStream = new LineStream(); - } -}); -QUnit.test('empty inputs produce no tokens', function(assert) { - let data = false; - - this.lineStream.on('data', function() { - data = true; - }); - this.lineStream.push(''); - assert.ok(!data, 'no tokens were produced'); -}); -QUnit.test('splits on newlines', function(assert) { - const lines = []; - - this.lineStream.on('data', function(line) { - lines.push(line); - }); - this.lineStream.push('#EXTM3U\nmovie.ts\n'); - - assert.strictEqual(2, lines.length, 'two lines are ready'); - assert.strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token'); - assert.strictEqual('movie.ts', lines.shift(), 'the second line is the second token'); -}); -QUnit.test('empty lines become empty strings', function(assert) { - const lines = []; - - this.lineStream.on('data', function(line) { - lines.push(line); - }); - this.lineStream.push('\n\n'); - - assert.strictEqual(2, lines.length, 'two lines are ready'); - assert.strictEqual('', lines.shift(), 'the first line is empty'); - assert.strictEqual('', lines.shift(), 'the second line is empty'); -}); -QUnit.test('handles lines broken across appends', function(assert) { - const lines = []; - - this.lineStream.on('data', function(line) { - lines.push(line); - }); - this.lineStream.push('#EXTM'); - assert.strictEqual(0, lines.length, 'no lines are ready'); - - this.lineStream.push('3U\nmovie.ts\n'); - assert.strictEqual(2, lines.length, 'two lines are ready'); - assert.strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token'); - assert.strictEqual('movie.ts', lines.shift(), 'the second line is the second token'); -}); -QUnit.test('stops sending events after deregistering', function(assert) { - const temporaryLines = []; - const temporary = function(line) { - temporaryLines.push(line); - }; - const permanentLines = []; - const permanent = function(line) { - permanentLines.push(line); - }; - - this.lineStream.on('data', temporary); - this.lineStream.on('data', permanent); - this.lineStream.push('line one\n'); - assert.strictEqual( - temporaryLines.length, - permanentLines.length, - 'both callbacks receive the event' - ); - - assert.ok(this.lineStream.off('data', temporary), 'a listener was removed'); - this.lineStream.push('line two\n'); - assert.strictEqual(1, temporaryLines.length, 'no new events are received'); - assert.strictEqual(2, permanentLines.length, 'new events are still received'); -}); QUnit.module('ParseStream', { beforeEach() { @@ -968,28 +889,6 @@ QUnit.test('parses EXT-X-START PRECISE attribute', function(assert) { assert.strictEqual(element.attributes['TIME-OFFSET'], 1.4, 'parses time offset'); assert.strictEqual(element.attributes.PRECISE, true, 'parses precise attribute'); }); -QUnit.test('flags missing EXT-X-START TIME-OFFSET attribute', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXT-X-VERSION:3', - '#EXT-X-TARGETDURATION:10', - '#EXT-X-START:PRECISE=YES', - '#EXTINF:10,', - 'media-00001.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - let warning; - - parser.on('warn', function(warn) { - warning = warn; - }); - parser.push(manifest); - - assert.ok(warning, 'a warning was triggered'); - assert.ok((/ignoring start/).test(warning.message), 'message is about start tag'); - assert.strictEqual(typeof parser.manifest.start, 'undefined', 'does not parse start'); -}); QUnit.test('ignores empty lines', function(assert) { const manifest = '\n'; @@ -1002,409 +901,3 @@ QUnit.test('ignores empty lines', function(assert) { assert.ok(!event, 'no event is triggered'); }); - -QUnit.module('m3u8 parser'); - -QUnit.test('can be constructed', function(assert) { - assert.notStrictEqual(typeof new Parser(), 'undefined', 'parser is defined'); -}); - -QUnit.test('can set custom parsers', function(assert) { - const parser = new Parser(); - const manifest = [ - '#EXTM3U', - '#EXT-X-VERSION:3', - '#EXT-X-TARGETDURATION:10', - '#EXT-X-MEDIA-SEQUENCE:0', - '#EXT-X-PROGRAM-DATE-TIME:2017-07-31T20:35:35.053+00:00', - '#VOD-STARTTIMESTAMP:1501533337573', - '#VOD-TOTALDELETEDDURATION:0.0', - '#VOD-FRAMERATE:29.97', - '' - ].join('\n'); - - parser.addParser({ - expression: /^#VOD-STARTTIMESTAMP/, - customType: 'startTimestamp' - }); - parser.addParser({ - expression: /^#VOD-TOTALDELETEDDURATION/, - customType: 'totalDeleteDuration' - }); - parser.addParser({ - expression: /^#VOD-FRAMERATE/, - customType: 'framerate', - dataParser: (line) => (line.split(':')[1]) - }); - - parser.push(manifest); - assert.strictEqual( - parser.manifest.custom.startTimestamp, - '#VOD-STARTTIMESTAMP:1501533337573', - 'sets custom timestamp line' - ); - - assert.strictEqual( - parser.manifest.custom.totalDeleteDuration, - '#VOD-TOTALDELETEDDURATION:0.0', - 'sets custom delete duration' - ); - - assert.strictEqual(parser.manifest.custom.framerate, '29.97', 'sets framerate'); -}); - -QUnit.test('segment level custom data', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#VOD-TIMING:1511816599485', - '#COMMENT', - '#EXTINF:8.0,', - 'ex1.ts', - '#VOD-TIMING', - '#EXTINF:8.0,', - 'ex2.ts', - '#VOD-TIMING:1511816615485', - '#EXT-UNKNOWN', - '#EXTINF:8.0,', - 'ex3.ts', - '#VOD-TIMING:1511816623485', - '#EXTINF:8.0,', - 'ex3.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.addParser({ - expression: /^#VOD-TIMING/, - customType: 'vodTiming', - segment: true - }); - - parser.push(manifest); - assert.equal( - parser.manifest.segments[0].custom.vodTiming, - '#VOD-TIMING:1511816599485', - 'parser attached segment level custom data' - ); - assert.equal( - parser.manifest.segments[1].custom.vodTiming, - '#VOD-TIMING', - 'parser got segment level custom data without :' - ); -}); - -QUnit.test('attaches cue-out data to segment', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXTINF:5,', - '#COMMENT', - 'ex1.ts', - '#EXT-X-CUE-OUT:10', - '#EXTINF:5,', - 'ex2.ts', - '#EXT-X-CUE-OUT15', - '#EXT-UKNOWN-TAG', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-CUE-OUT', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.equal(parser.manifest.segments[1].cueOut, '10', 'parser attached cue out tag'); - assert.equal(parser.manifest.segments[2].cueOut, '15', 'cue out without : seperator'); - assert.equal(parser.manifest.segments[3].cueOut, '', 'cue out without data'); -}); - -QUnit.test('attaches cue-out-cont data to segment', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXTINF:5,', - '#COMMENT', - 'ex1.ts', - '#EXT-X-CUE-OUT-CONT:10/60', - '#EXTINF:5,', - 'ex2.ts', - '#EXT-X-CUE-OUT-CONT15/30', - '#EXT-UKNOWN-TAG', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-CUE-OUT-CONT', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.equal( - parser.manifest.segments[1].cueOutCont, '10/60', - 'parser attached cue out cont tag' - ); - assert.equal( - parser.manifest.segments[2].cueOutCont, '15/30', - 'cue out cont without : seperator' - ); - assert.equal(parser.manifest.segments[3].cueOutCont, '', 'cue out cont without data'); -}); - -QUnit.test('attaches cue-in data to segment', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXTINF:5,', - '#COMMENT', - 'ex1.ts', - '#EXT-X-CUE-IN', - '#EXTINF:5,', - 'ex2.ts', - '#EXT-X-CUE-IN:15', - '#EXT-UKNOWN-TAG', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-CUE-IN=abc', - '#EXTINF:5,', - 'ex3.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.equal(parser.manifest.segments[1].cueIn, '', 'parser attached cue in tag'); - assert.equal(parser.manifest.segments[2].cueIn, '15', 'cue in with data'); - assert.equal( - parser.manifest.segments[3].cueIn, '=abc', - 'cue in without colon seperator' - ); -}); - -QUnit.test('parses characteristics attribute', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",CHARACTERISTICS="char",NAME="test"', - '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="mp4a.40.2, avc1.4d400d",SUBTITLES="subs"', - 'index.m3u8' - ].join('\n'); - - parser.push(manifest); - - assert.equal( - parser.manifest.mediaGroups.SUBTITLES.subs.test.characteristics, - 'char', - 'parsed CHARACTERISTICS attribute' - ); -}); - -QUnit.test('parses FORCED attribute', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",CHARACTERISTICS="char",NAME="test",FORCED=YES', - '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="mp4a.40.2, avc1.4d400d",SUBTITLES="subs"', - 'index.m3u8' - ].join('\n'); - - parser.push(manifest); - - assert.ok( - parser.manifest.mediaGroups.SUBTITLES.subs.test.forced, - 'parsed FORCED attribute' - ); -}); - -QUnit.test('parses Widevine #EXT-X-KEY attributes and attaches to manifest', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + - 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + - 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + - 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', - '#EXTINF:5,', - 'ex1.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.ok(parser.manifest.contentProtection, 'contentProtection property added'); - assert.equal( - parser.manifest.contentProtection['com.widevine.alpha'].attributes.schemeIdUri, - 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', - 'schemeIdUri set correctly' - ); - assert.equal( - parser.manifest.contentProtection['com.widevine.alpha'].attributes.keyId, - '800AACAA522958AE888062B5695DB6BF', - 'keyId set correctly' - ); - assert.equal( - parser.manifest.contentProtection['com.widevine.alpha'].pssh.byteLength, - 62, - 'base64 URI decoded to TypedArray' - ); -}); - -QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if METHOD is invalid', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-KEY:METHOD=NONE,' + - 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + - 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + - 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', - '#EXTINF:5,', - 'ex1.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.notOk(parser.manifest.contentProtection, 'contentProtection not added'); -}); - -QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if URI is invalid', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + - 'URI="AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + - 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + - 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', - '#EXTINF:5,', - 'ex1.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.notOk(parser.manifest.contentProtection, 'contentProtection not added'); -}); - -QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if KEYID is invalid', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + - 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + - 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=800AACAA522958AE888062B5695DB6BF,' + - 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', - '#EXTINF:5,', - 'ex1.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.notOk(parser.manifest.contentProtection, 'contentProtection not added'); -}); - -QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if KEYFORMAT is not Widevine UUID', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + - 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + - 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + - 'KEYFORMATVERSIONS="1",KEYFORMAT="invalid-keyformat"', - '#EXTINF:5,', - 'ex1.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.notOk(parser.manifest.contentProtection, 'contentProtection not added'); -}); - -QUnit.test('byterange offset defaults to next byte', function(assert) { - const parser = new Parser(); - - const manifest = [ - '#EXTM3U', - '#EXTINF:5,', - '#EXT-X-BYTERANGE:10@5', - 'segment.ts', - '#EXTINF:5,', - '#EXT-X-BYTERANGE:20', - 'segment.ts', - '#EXTINF:5,', - '#EXT-X-BYTERANGE:30', - 'segment.ts', - '#EXTINF:5,', - 'segment2.ts', - '#EXT-X-BYTERANGE:15@100', - 'segment.ts', - '#EXT-X-BYTERANGE:17', - 'segment.ts', - '#EXT-X-ENDLIST' - ].join('\n'); - - parser.push(manifest); - - assert.deepEqual( - parser.manifest.segments[0].byterange, - { length: 10, offset: 5 }, - 'first segment has correct byterange' - ); - assert.deepEqual( - parser.manifest.segments[1].byterange, - { length: 20, offset: 15 }, - 'second segment has correct byterange' - ); - assert.deepEqual( - parser.manifest.segments[2].byterange, - { length: 30, offset: 35 }, - 'third segment has correct byterange' - ); - assert.notOk(parser.manifest.segments[3].byterange, 'fourth segment has no byterange'); - assert.deepEqual( - parser.manifest.segments[4].byterange, - { length: 15, offset: 100 }, - 'fifth segment has correct byterange' - ); - // not tested is a segment with no offset coming after a segment that isn't a sub range, - // as the spec requires that a byterange without an offset must follow a segment that - // is a sub range of the same media resource - assert.deepEqual( - parser.manifest.segments[5].byterange, - { length: 17, offset: 115 }, - 'sixth segment has correct byterange' - ); -}); - -QUnit.module('m3u8s'); - -for (const key in testDataManifests) { - if (!testDataExpected[key]) { - continue; - } - QUnit.test(`parses ${key} as expected`, function(assert) { - const parser = new Parser(); - - parser.push(testDataManifests[key]); - assert.deepEqual( - parser.manifest, - testDataExpected[key], - key + '.m3u8 was parsed correctly' - ); - }); -} - diff --git a/test/parser.test.js b/test/parser.test.js new file mode 100644 index 0000000..946cb49 --- /dev/null +++ b/test/parser.test.js @@ -0,0 +1,435 @@ +import QUnit from 'qunit'; +import testDataExpected from './dist/test-expected.js'; +import testDataManifests from './dist/test-manifests.js'; +import {Parser} from '../src'; + +QUnit.module('m3u8s', function(hooks) { + hooks.beforeEach(function() { + this.parser = new Parser(); + }); + + QUnit.module('general'); + + QUnit.test('can be constructed', function(assert) { + assert.notStrictEqual(this.parser, 'undefined', 'parser is defined'); + }); + + QUnit.test('can set custom parsers', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-VERSION:3', + '#EXT-X-TARGETDURATION:10', + '#EXT-X-MEDIA-SEQUENCE:0', + '#EXT-X-PROGRAM-DATE-TIME:2017-07-31T20:35:35.053+00:00', + '#VOD-STARTTIMESTAMP:1501533337573', + '#VOD-TOTALDELETEDDURATION:0.0', + '#VOD-FRAMERATE:29.97', + '' + ].join('\n'); + + this.parser.addParser({ + expression: /^#VOD-STARTTIMESTAMP/, + customType: 'startTimestamp' + }); + this.parser.addParser({ + expression: /^#VOD-TOTALDELETEDDURATION/, + customType: 'totalDeleteDuration' + }); + this.parser.addParser({ + expression: /^#VOD-FRAMERATE/, + customType: 'framerate', + dataParser: (line) => (line.split(':')[1]) + }); + + this.parser.push(manifest); + this.parser.end(); + assert.strictEqual( + this.parser.manifest.custom.startTimestamp, + '#VOD-STARTTIMESTAMP:1501533337573', + 'sets custom timestamp line' + ); + + assert.strictEqual( + this.parser.manifest.custom.totalDeleteDuration, + '#VOD-TOTALDELETEDDURATION:0.0', + 'sets custom delete duration' + ); + + assert.strictEqual(this.parser.manifest.custom.framerate, '29.97', 'sets framerate'); + }); + + QUnit.test('segment level custom data', function(assert) { + const manifest = [ + '#EXTM3U', + '#VOD-TIMING:1511816599485', + '#COMMENT', + '#EXTINF:8.0,', + 'ex1.ts', + '#VOD-TIMING', + '#EXTINF:8.0,', + 'ex2.ts', + '#VOD-TIMING:1511816615485', + '#EXT-UNKNOWN', + '#EXTINF:8.0,', + 'ex3.ts', + '#VOD-TIMING:1511816623485', + '#EXTINF:8.0,', + 'ex3.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.addParser({ + expression: /^#VOD-TIMING/, + customType: 'vodTiming', + segment: true + }); + + this.parser.push(manifest); + this.parser.end(); + assert.equal( + this.parser.manifest.segments[0].custom.vodTiming, + '#VOD-TIMING:1511816599485', + 'parser attached segment level custom data' + ); + assert.equal( + this.parser.manifest.segments[1].custom.vodTiming, + '#VOD-TIMING', + 'parser got segment level custom data without :' + ); + }); + + QUnit.test('attaches cue-out data to segment', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXTINF:5,', + '#COMMENT', + 'ex1.ts', + '#EXT-X-CUE-OUT:10', + '#EXTINF:5,', + 'ex2.ts', + '#EXT-X-CUE-OUT15', + '#EXT-UKNOWN-TAG', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-CUE-OUT', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.equal(this.parser.manifest.segments[1].cueOut, '10', 'parser attached cue out tag'); + assert.equal(this.parser.manifest.segments[2].cueOut, '15', 'cue out without : seperator'); + assert.equal(this.parser.manifest.segments[3].cueOut, '', 'cue out without data'); + }); + + QUnit.test('attaches cue-out-cont data to segment', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXTINF:5,', + '#COMMENT', + 'ex1.ts', + '#EXT-X-CUE-OUT-CONT:10/60', + '#EXTINF:5,', + 'ex2.ts', + '#EXT-X-CUE-OUT-CONT15/30', + '#EXT-UKNOWN-TAG', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-CUE-OUT-CONT', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.equal( + this.parser.manifest.segments[1].cueOutCont, '10/60', + 'parser attached cue out cont tag' + ); + assert.equal( + this.parser.manifest.segments[2].cueOutCont, '15/30', + 'cue out cont without : seperator' + ); + assert.equal(this.parser.manifest.segments[3].cueOutCont, '', 'cue out cont without data'); + }); + + QUnit.test('attaches cue-in data to segment', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXTINF:5,', + '#COMMENT', + 'ex1.ts', + '#EXT-X-CUE-IN', + '#EXTINF:5,', + 'ex2.ts', + '#EXT-X-CUE-IN:15', + '#EXT-UKNOWN-TAG', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-CUE-IN=abc', + '#EXTINF:5,', + 'ex3.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.equal(this.parser.manifest.segments[1].cueIn, '', 'parser attached cue in tag'); + assert.equal(this.parser.manifest.segments[2].cueIn, '15', 'cue in with data'); + assert.equal( + this.parser.manifest.segments[3].cueIn, '=abc', + 'cue in without colon seperator' + ); + }); + + QUnit.test('parses characteristics attribute', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",CHARACTERISTICS="char",NAME="test"', + '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="mp4a.40.2, avc1.4d400d",SUBTITLES="subs"', + 'index.m3u8' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.equal( + this.parser.manifest.mediaGroups.SUBTITLES.subs.test.characteristics, + 'char', + 'parsed CHARACTERISTICS attribute' + ); + }); + + QUnit.test('parses FORCED attribute', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",CHARACTERISTICS="char",NAME="test",FORCED=YES', + '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="mp4a.40.2, avc1.4d400d",SUBTITLES="subs"', + 'index.m3u8' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.ok( + this.parser.manifest.mediaGroups.SUBTITLES.subs.test.forced, + 'parsed FORCED attribute' + ); + }); + + QUnit.test('parses Widevine #EXT-X-KEY attributes and attaches to manifest', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + + 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + + 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + + 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', + '#EXTINF:5,', + 'ex1.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.ok(this.parser.manifest.contentProtection, 'contentProtection property added'); + assert.equal( + this.parser.manifest.contentProtection['com.widevine.alpha'].attributes.schemeIdUri, + 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', + 'schemeIdUri set correctly' + ); + assert.equal( + this.parser.manifest.contentProtection['com.widevine.alpha'].attributes.keyId, + '800AACAA522958AE888062B5695DB6BF', + 'keyId set correctly' + ); + assert.equal( + this.parser.manifest.contentProtection['com.widevine.alpha'].pssh.byteLength, + 62, + 'base64 URI decoded to TypedArray' + ); + }); + + QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if METHOD is invalid', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-KEY:METHOD=NONE,' + + 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + + 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + + 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', + '#EXTINF:5,', + 'ex1.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.notOk(this.parser.manifest.contentProtection, 'contentProtection not added'); + }); + + QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if URI is invalid', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + + 'URI="AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + + 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + + 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', + '#EXTINF:5,', + 'ex1.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.notOk(this.parser.manifest.contentProtection, 'contentProtection not added'); + }); + + QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if KEYID is invalid', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + + 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + + 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=800AACAA522958AE888062B5695DB6BF,' + + 'KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"', + '#EXTINF:5,', + 'ex1.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.notOk(this.parser.manifest.contentProtection, 'contentProtection not added'); + }); + + QUnit.test('Widevine #EXT-X-KEY attributes not attached to manifest if KEYFORMAT is not Widevine UUID', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,' + + 'URI="data:text/plain;base64,AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnN' + + 'oYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY=",KEYID=0x800AACAA522958AE888062B5695DB6BF,' + + 'KEYFORMATVERSIONS="1",KEYFORMAT="invalid-keyformat"', + '#EXTINF:5,', + 'ex1.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.notOk(this.parser.manifest.contentProtection, 'contentProtection not added'); + }); + + QUnit.test('byterange offset defaults to next byte', function(assert) { + const manifest = [ + '#EXTM3U', + '#EXTINF:5,', + '#EXT-X-BYTERANGE:10@5', + 'segment.ts', + '#EXTINF:5,', + '#EXT-X-BYTERANGE:20', + 'segment.ts', + '#EXTINF:5,', + '#EXT-X-BYTERANGE:30', + 'segment.ts', + '#EXTINF:5,', + 'segment2.ts', + '#EXT-X-BYTERANGE:15@100', + 'segment.ts', + '#EXT-X-BYTERANGE:17', + 'segment.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + + this.parser.push(manifest); + this.parser.end(); + + assert.deepEqual( + this.parser.manifest.segments[0].byterange, + { length: 10, offset: 5 }, + 'first segment has correct byterange' + ); + assert.deepEqual( + this.parser.manifest.segments[1].byterange, + { length: 20, offset: 15 }, + 'second segment has correct byterange' + ); + assert.deepEqual( + this.parser.manifest.segments[2].byterange, + { length: 30, offset: 35 }, + 'third segment has correct byterange' + ); + assert.notOk(this.parser.manifest.segments[3].byterange, 'fourth segment has no byterange'); + assert.deepEqual( + this.parser.manifest.segments[4].byterange, + { length: 15, offset: 100 }, + 'fifth segment has correct byterange' + ); + // not tested is a segment with no offset coming after a segment that isn't a sub range, + // as the spec requires that a byterange without an offset must follow a segment that + // is a sub range of the same media resource + assert.deepEqual( + this.parser.manifest.segments[5].byterange, + { length: 17, offset: 115 }, + 'sixth segment has correct byterange' + ); + }); + + QUnit.module('warn/info'); + + QUnit.test('triggers warning for missing EXT-X-START TIME-OFFSET attribute', function(assert) { + + const manifest = [ + '#EXT-X-VERSION:3', + '#EXT-X-TARGETDURATION:10', + '#EXT-X-START:PRECISE=YES', + '#EXTINF:10,', + 'media-00001.ts', + '#EXT-X-ENDLIST' + ].join('\n'); + let warning; + + this.parser.on('warn', function(warn) { + warning = warn; + }); + this.parser.push(manifest); + this.parser.end(); + + assert.ok(warning, 'a warning was triggered'); + assert.ok((/ignoring start/).test(warning.message), 'message is about start tag'); + assert.strictEqual(typeof this.parser.manifest.start, 'undefined', 'does not parse start'); + }); + + QUnit.module('integration'); + + for (const key in testDataExpected) { + if (!testDataManifests[key]) { + throw new Error(`${key}.js does not have an equivelent m3u8 manifest to test against`); + } + } + + for (const key in testDataManifests) { + if (!testDataExpected[key]) { + throw new Error(`${key}.m3u8 does not have an equivelent expected js file to test against`); + } + QUnit.test(`parses ${key}.m3u8 as expected in ${key}.js`, function(assert) { + this.parser.push(testDataManifests[key]); + this.parser.end(); + + assert.deepEqual( + this.parser.manifest, + testDataExpected[key], + key + '.m3u8 was parsed correctly' + ); + }); + } + +});