Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
10.0 kB · 282 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283import { assert, expect } from 'chai';import clone from "clone";import { describe, it } from 'mocha';import { genericSourcePlayMatch, playsAreAddedOnly, playsAreBumpedOnly, playsAreSortConsistent } from "../../utils/PlayComparisonUtils.js";import { generatePlay, generatePlays } from "../../../core/PlayTestUtils.js";import { PlayObject } from "../../../core/Atomic.js";
const newPlay = generatePlay();
const existingList = generatePlays(10);
describe('Compare lists by order', function () {
describe('Identity', function () { it('Identical lists are equal', function () { const identicalList = [...existingList.map(x => clone(x))]; assert.isTrue(playsAreSortConsistent(existingList, identicalList)); });
it('Non-identical lists are not equal', function () { assert.isFalse(playsAreSortConsistent(existingList, generatePlays(11))); });
it('Non-identical lists with modifications are not equal', function () { const modified = [...existingList.map(x => clone(x))]; modified.splice(2, 1, generatePlay()); modified[6].data.track = 'A CHANGE'; modified.splice(8, 0, generatePlay()); const modded = [...modified, generatePlay()]; assert.isFalse(playsAreSortConsistent(existingList, modded)); }); });
describe('Non-identical lists', function() { let candidateList: PlayObject[];
before(function() { candidateList = generatePlays(10); });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with only prepended additions', function() { let candidateList: PlayObject[];
before(function() { candidateList = [generatePlay(), generatePlay(), ...existingList]; });
it('are add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isTrue(ok); assert.equal(addType, 'prepend'); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with only appended additions', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList, generatePlay(), generatePlay()]; });
it('are add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isTrue(ok); assert.equal(addType, 'append'); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists of fixed length with prepends', function() { let candidateList: PlayObject[];
before(function() { candidateList = [generatePlay(), generatePlay(), ...existingList].slice(0, 9); });
it('are add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isTrue(ok); assert.equal(addType, 'prepend'); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with inserts', function() { let candidateList: PlayObject[], candidateList2: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; candidateList.splice(4, 0, generatePlay())
candidateList2 = [...existingList.map(x => clone(x))]; candidateList2.splice(2, 0, generatePlay()) candidateList2.splice(6, 0, generatePlay()) });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok)
const [ok2, diff2, addType2] = playsAreAddedOnly(existingList, candidateList2) assert.isFalse(ok2) });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok)
const [ok2, diff2, addType2] = playsAreBumpedOnly(existingList, candidateList2) assert.isFalse(ok2) }); });
describe('Lists with inserts and prepends', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; candidateList.splice(2, 0, generatePlay()) candidateList.splice(6, 0, generatePlay()) candidateList = [generatePlay(), generatePlay(), ...candidateList] });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with inserts and appends', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; candidateList.splice(2, 0, generatePlay()) candidateList.splice(6, 0, generatePlay()) candidateList = [...candidateList, generatePlay(), generatePlay()] });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with inserts and appends and prepends', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; candidateList = [generatePlay(), generatePlay(), ...candidateList, generatePlay(), generatePlay()] });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList) assert.isFalse(ok); });
it('are not bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList) assert.isFalse(ok); }); });
describe('Lists with plays bumped-by-prepend', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; const bumped = candidateList[6]; candidateList.splice(6, 1); candidateList.unshift(bumped); });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList); assert.isFalse(ok); });
it('are bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList); assert.isTrue(ok); assert.equal(addType, 'prepend'); }); });
describe('Lists with plays bumped-by-append', function() { let candidateList: PlayObject[];
before(function() { candidateList = [...existingList.map(x => clone(x))]; const bumped = candidateList[6]; candidateList.splice(6, 1); candidateList.push(bumped); });
it('are not add only', function () { const [ok, diff, addType] = playsAreAddedOnly(existingList, candidateList); assert.isFalse(ok); });
it('are bump only', function () { const [ok, diff, addType] = playsAreBumpedOnly(existingList, candidateList); assert.isTrue(ok); assert.equal(addType, 'append'); }); });
describe('Source Play Comparisons', function() {
describe('Generic Source Comparison', function() {
it('matches identical plays', function() { expect(genericSourcePlayMatch(newPlay, newPlay)).to.be.true; });
it('matches identical plays with close timestamps', function() { const closePlay = clone(newPlay); closePlay.data.playDate = closePlay.data.playDate.add(3, 's'); expect(genericSourcePlayMatch(newPlay, closePlay)).to.be.true; });
it('does not match unique plays', function() { expect(genericSourcePlayMatch(newPlay, generatePlay())).to.be.false; });
it('does not match unique plays with exact timestamps', function() { const diffPlay = generatePlay(); diffPlay.data.playDate = newPlay.data.playDate; expect(genericSourcePlayMatch(newPlay, diffPlay)).to.be.false; });
it('does not match unique plays with close timestamps', function() { const diffPlay = generatePlay(); diffPlay.data.playDate = newPlay.data.playDate.add(3, 's'); expect(genericSourcePlayMatch(newPlay, diffPlay)).to.be.false; }); });
});});