pax_global_header00006660000000000000000000000064123650204070014511gustar00rootroot0000000000000052 comment=904c3d3be0edbee37f0acefd177eb01a06aff243 node-music-library-index-1.2.2/000077500000000000000000000000001236502040700163255ustar00rootroot00000000000000node-music-library-index-1.2.2/.gitignore000066400000000000000000000000161236502040700203120ustar00rootroot00000000000000/node_modules node-music-library-index-1.2.2/.jshintrc000066400000000000000000000070671236502040700201640ustar00rootroot00000000000000{ // Settings "passfail" : false, // Stop on first error. "maxerr" : 100, // Maximum errors before stopping. // Predefined globals whom JSHint will ignore. "browser" : false, // Standard browser globals e.g. `window`, `document`. "predef" : [ // extra globals "describe", "beforeEach", "afterEach", "it" ], "node" : true, "rhino" : false, "couch" : false, "wsh" : false, // Windows Scripting Host. "jquery" : false, "prototypejs" : false, "mootools" : false, "dojo" : false, // Development. "debug" : true, // Allow debugger statements e.g. browser breakpoints. "devel" : true, // Allow development statements e.g. `console.log();`. // EcmaScript 5. "es5" : true, // Allow EcmaScript 5 syntax. "strict" : false, // Require `use strict` pragma in every file. "globalstrict" : true, // Allow global "use strict" (also enables 'strict'). // The Good Parts. "asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons). "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. "laxcomma" : true, "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.). "boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. "curly" : false, // Require {} for every new block or scope. "eqeqeq" : true, // Require triple equals i.e. `===`. "eqnull" : true, // Tolerate use of `== null`. "evil" : false, // Tolerate use of `eval`. "expr" : false, // Tolerate `ExpressionStatement` as Programs. "forin" : false, // Prohibt `for in` loops without `hasOwnProperty`. "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` "latedef" : false, // Prohibit variable use before definition. "loopfunc" : false, // Allow functions to be defined within loops. "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. "regexp" : false, // Prohibit `.` and `[^...]` in regular expressions. "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`. "scripturl" : false, // Tolerate script-targeted URLs. "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. "undef" : true, // Require all non-global variables be declared before they are used. // Persone styling prefrences. "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`. "noempty" : true, // Prohibit use of empty blocks. "nonew" : true, // Prohibit use of constructors for side-effects. "nomen" : false, // Prohibit use of initial or trailing underbars in names. "onevar" : false, // Allow only one `var` statement per function. "plusplus" : false, // Prohibit use of `++` & `--`. "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. "trailing" : true, // Prohibit trailing whitespaces. "white" : false // Check against strict whitespace and indentation rules. } node-music-library-index-1.2.2/LICENSE000066400000000000000000000020411236502040700173270ustar00rootroot00000000000000Copyright (c) 2014 Andrew Kelley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-music-library-index-1.2.2/README.md000066400000000000000000000047321236502040700176120ustar00rootroot00000000000000# Music Library Index Given track metadata objects, constructs a searchable object model. This module is used both in the client and the server of [Groove Basin](https://github.com/superjoe30/groovebasin). ## Features * Sort order ignores 'a', 'an' and 'the' in artists, albums, and names. * Sorting and searching is case insensitive and [diacritics-insensitive](https://github.com/superjoe30/diacritics). * Searching uses word-based filtering (this is how most music player applications implement filtering) on all track fields. * Distinguishes albums by name, date, and album artist. * Produces these indexes: * Artists in sorted order - For each of these artists, albums in sorted order. - For each of these albums, tracks in sorted order. * Albums in sorted order - For each of these albums, tracks in sorted order. * Tracks by user-defined key. * Artists by library-defined key. * Albums by library-defined key. ## Usage ```js var MusicLibraryIndex = require('music-library-index'); var library = new MusicLibraryIndex(); library.addTrack({ key: "Anberlin/Never Take Friendship Personal/02. Paperthin Hymn.mp3", name: "Paperthin Hymn", artistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 2, albumArtistName: "Anberlin", }); library.addTrack({ key: "Anberlin/Never Take Friendship Personal/08. The Feel Good Drag.mp3", name: "The Feel Good Drag", artistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 8, albumArtistName: "Anberlin", }); library.rebuild(); console.log(library.artistList[0]); console.log(library.trackTable); ``` ## Tests ``` basic index building ✓ trackTable ✓ artistList ✓ albumList ✓ searching compilation album ✓ filed in various artists tracks from same album missing year metadata ✓ still knows they're in the same album different albums with same name ✓ detects that they are different album with a few tracks by different artists ✓ only creates one album album by an artist ✓ should be filed under the artist album by an artist ✓ sorts by disc before track album artist with no album ✓ shouldn't be various artists unknown artist, unknown album ✓ should be put into the same album ✓ searching should not affect anything album with album artist ✓ shouldn't be various artists ``` node-music-library-index-1.2.2/index.js000066400000000000000000000202571236502040700200000ustar00rootroot00000000000000var removeDiacritics = require('diacritics').remove; module.exports = MusicLibraryIndex; MusicLibraryIndex.defaultPrefixesToStrip = [/^\s*the\s+/, /^\s*a\s+/, /^\s*an\s+/]; MusicLibraryIndex.defaultVariousArtistsKey = "VariousArtists"; MusicLibraryIndex.defaultVariousArtistsName = "Various Artists"; MusicLibraryIndex.defaultSearchFields = ['artistName', 'albumArtistName', 'albumName', 'name']; function MusicLibraryIndex(options) { options = options || {}; this.searchFields = options.searchFields || MusicLibraryIndex.defaultSearchFields; this.variousArtistsKey = options.variousArtistsKey || MusicLibraryIndex.defaultVariousArtistsKey; this.variousArtistsName = options.variousArtistsName || MusicLibraryIndex.defaultVariousArtistsName; this.prefixesToStrip = options.prefixesToStrip || MusicLibraryIndex.defaultPrefixesToStrip; this.artistComparator = this.artistComparator.bind(this); this.albumComparator = this.albumComparator.bind(this); this.trackComparator = this.trackComparator.bind(this); this.clear(); } MusicLibraryIndex.prototype.stripPrefixes = function(str) { for (var i = 0; i < this.prefixesToStrip.length; i += 1) { var regex = this.prefixesToStrip[i]; str = str.replace(regex, ''); break; } return str; }; MusicLibraryIndex.prototype.sortableTitle = function(title) { return this.stripPrefixes(formatSearchable(title)); }; MusicLibraryIndex.prototype.titleCompare = function(a, b) { var _a = this.sortableTitle(a); var _b = this.sortableTitle(b); if (_a < _b) { return -1; } else if (_a > _b) { return 1; } else { if (a < b) { return -1; } else if (a > b) { return 1; } else { return 0; } } }; MusicLibraryIndex.prototype.trackComparator = function(a, b) { if (a.disc < b.disc) { return -1; } else if (a.disc > b.disc) { return 1; } else if (a.track < b.track) { return -1; } else if (a.track > b.track) { return 1; } else { return this.titleCompare(a.name, b.name); } } MusicLibraryIndex.prototype.albumComparator = function(a, b) { if (a.year < b.year) { return -1; } else if (a.year > b.year) { return 1; } else { return this.titleCompare(a.name, b.name); } } MusicLibraryIndex.prototype.artistComparator = function(a, b) { return this.titleCompare(a.name, b.name); } MusicLibraryIndex.prototype.getAlbumKey = function(track) { var artistName = track.albumArtistName || (track.compilation ? this.variousArtistsName : track.artistName); return formatSearchable(track.albumName + "\n" + artistName); }; MusicLibraryIndex.prototype.getArtistKey = function(artistName) { return formatSearchable(artistName); }; MusicLibraryIndex.prototype.clear = function() { this.trackTable = {}; this.artistTable = {}; this.artistList = []; this.albumTable = {}; this.albumList = []; this.dirty = false; this.dirtyAlbumTable = false; }; MusicLibraryIndex.prototype.rebuildAlbumTable = function() { if (!this.dirtyAlbumTable) return; // builds everything from trackTable this.artistTable = {}; this.artistList = []; this.albumTable = {}; this.albumList = []; var thisAlbumList = this.albumList; for (var trackKey in this.trackTable) { var track = this.trackTable[trackKey]; this.trackTable[track.key] = track; var searchTags = ""; for (var i = 0; i < this.searchFields.length; i += 1) { searchTags += track[this.searchFields[i]] + "\n"; } track.searchTags = formatSearchable(searchTags); if (track.albumArtistName === this.variousArtistsName) { track.albumArtistName = ""; track.compilation = true; } track.albumArtistName = track.albumArtistName || ""; var albumKey = this.getAlbumKey(track); var album = getOrCreate(albumKey, this.albumTable, createAlbum); track.album = album; album.trackList.push(track); if (album.year == null) { album.year = track.year; } } this.dirtyAlbumTable = false; function createAlbum() { var album = { name: track.albumName, year: track.year, trackList: [], key: albumKey, }; thisAlbumList.push(album); return album; } }; MusicLibraryIndex.prototype.rebuild = function() { if (!this.dirty) return; this.rebuildAlbumTable(); this.albumList.sort(this.albumComparator); var albumArtistName, artistKey, artist; var albumKey, track, album; var i; for (albumKey in this.albumTable) { album = this.albumTable[albumKey]; var albumArtistSet = {}; album.trackList.sort(this.trackComparator); albumArtistName = ""; var isCompilation = false; for (i = 0; i < album.trackList.length; i += 1) { track = album.trackList[i]; track.index = i; if (track.albumArtistName) { albumArtistName = track.albumArtistName; albumArtistSet[this.getArtistKey(albumArtistName)] = true; } if (!albumArtistName) albumArtistName = track.artistName; albumArtistSet[this.getArtistKey(albumArtistName)] = true; isCompilation = isCompilation || track.compilation; } if (isCompilation || moreThanOneKey(albumArtistSet)) { albumArtistName = this.variousArtistsName; artistKey = this.variousArtistsKey; for (i = 0; i < album.trackList.length; i += 1) { track = album.trackList[i]; track.compilation = true; } } else { artistKey = this.getArtistKey(albumArtistName); } artist = getOrCreate(artistKey, this.artistTable, createArtist); album.artist = artist; artist.albumList.push(album); } this.artistList = []; var variousArtist = null; for (artistKey in this.artistTable) { artist = this.artistTable[artistKey]; artist.albumList.sort(this.albumComparator); for (i = 0; i < artist.albumList.length; i += 1) { album = artist.albumList[i]; album.index = i; } if (artist.key === this.variousArtistsKey) { variousArtist = artist; } else { this.artistList.push(artist); } } this.artistList.sort(this.artistComparator); if (variousArtist) { this.artistList.unshift(variousArtist); } for (i = 0; i < this.artistList.length; i += 1) { artist = this.artistList[i]; artist.index = i; } this.dirty = false; function createArtist() { return { name: albumArtistName, albumList: [], key: artistKey, }; } } MusicLibraryIndex.prototype.addTrack = function(track) { var oldTrack = this.trackTable[track.key]; this.dirty = this.dirty || oldTrack == null || oldTrack.artistName !== track.artistName || oldTrack.albumArtistName !== track.albumArtistName || oldTrack.albumName !== track.albumName || oldTrack.track !== track.track || oldTrack.disc !== track.disc || oldTrack.year !== track.year; this.dirtyAlbumTable = this.dirty; this.trackTable[track.key] = track; } MusicLibraryIndex.prototype.removeTrack = function(key) { delete this.trackTable[key]; this.dirty = true; this.dirtyAlbumTable = true; } MusicLibraryIndex.prototype.search = function(query) { query = query.trim(); var searchResults = new MusicLibraryIndex({ searchFields: this.searchFields, variousArtistsKey: this.variousArtistsKey, variousArtistsName: this.variousArtistsName, prefixesToStrip: this.prefixesToStrip, }); var words = formatSearchable(query).split(/\s+/); var track; for (var trackKey in this.trackTable) { track = this.trackTable[trackKey]; if (testMatch()) { searchResults.trackTable[track.key] = track; } } searchResults.dirty = true; searchResults.dirtyAlbumTable = true; searchResults.rebuild(); return searchResults; function testMatch() { for (var i = 0; i < words.length; i += 1) { var word = words[i]; if (track.searchTags.indexOf(word) === -1) { return false; } } return true; } }; function getOrCreate(key, table, initObjFunc) { var result = table[key]; if (result == null) { result = initObjFunc(); table[key] = result; } return result; } function moreThanOneKey(object){ var count = -2; for (var k in object) { if (!++count) { return true; } } return false; } function formatSearchable(str) { return removeDiacritics(str).toLowerCase(); } node-music-library-index-1.2.2/package.json000066400000000000000000000013371236502040700206170ustar00rootroot00000000000000{ "name": "music-library-index", "version": "1.2.2", "description": "build a searchable javascript object model given track metadata objects", "main": "index.js", "scripts": { "test": "mocha --reporter spec test/test.js" }, "author": "Andrew Kelley ", "license": "MIT", "dependencies": { "diacritics": "~1.2.0" }, "devDependencies": { "mocha": "~1.21.0" }, "repository": { "type": "git", "url": "git://github.com/superjoe30/node-music-library-index.git" }, "bugs": { "url": "https://github.com/superjoe30/node-music-library-index/issues" }, "homepage": "https://github.com/superjoe30/node-music-library-index", "directories": { "test": "test" } } node-music-library-index-1.2.2/test/000077500000000000000000000000001236502040700173045ustar00rootroot00000000000000node-music-library-index-1.2.2/test/benchmark.js000066400000000000000000000015111236502040700215720ustar00rootroot00000000000000// usage: node benchmark.js path/to/index.json ["search query" ...] var fs = require('fs'); var MusicLibraryIndex = require('../'); var indexPath = process.argv[2]; fs.readFile(indexPath, function(err, data) { if (err) throw err; var input = JSON.parse(data); var library = new MusicLibraryIndex(); for (var key in input) { library.addTrack(input[key]); } timed("rebuild()", function() { library.rebuild(); }); for (var i = 3; i < process.argv.length; i++) { timedSearch(process.argv[i]); } function timedSearch(query) { timed("search(" + JSON.stringify(query) + ")", function() { library.search(query); }); } }); function timed(name, func) { process.stdout.write(name + "..."); var start = new Date(); func(); var duration = new Date() - start; console.log(duration + "ms"); } node-music-library-index-1.2.2/test/test.js000066400000000000000000000271461236502040700206330ustar00rootroot00000000000000var assert = require('assert'); var MusicLibraryIndex = require('../'); describe("basic index building", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "Anberlin/Never Take Friendship Personal/02. Paperthin Hymn.mp3", name: "Paperthin Hymn", artistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 2, albumArtistName: "Anberlin", }); library.addTrack({ key: "Anberlin/Never Take Friendship Personal/08. The Feel Good Drag.mp3", name: "The Feel Good Drag", artistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 8, albumArtistName: "Anberlin", }); library.rebuild(); it("trackTable", function() { var track = library.trackTable["Anberlin/Never Take Friendship Personal/08. The Feel Good Drag.mp3"]; assert.strictEqual(track.name, "The Feel Good Drag"); assert.strictEqual(track.artistName, "Anberlin"); assert.strictEqual(track.album.name, "Never Take Friendship Personal"); assert.strictEqual(track.year, 2005); }); it("artistList", function() { assert.strictEqual(library.artistList.length, 1); var artist = library.artistList[0]; assert.strictEqual(artist.name, "Anberlin"); assert.strictEqual(artist.index, 0); assert.strictEqual(artist.albumList.length, 1); var album = artist.albumList[0]; assert.strictEqual(album.name, "Never Take Friendship Personal"); assert.strictEqual(album.year, 2005); assert.strictEqual(album.index, 0); assert.strictEqual(album.trackList.length, 2); assert.strictEqual(album.trackList[0].name, "Paperthin Hymn"); assert.strictEqual(album.trackList[0].index, 0); assert.strictEqual(album.trackList[1].name, "The Feel Good Drag"); assert.strictEqual(album.trackList[1].index, 1); }); it("albumList", function() { assert.strictEqual(library.albumList.length, 1); var album = library.albumList[0]; assert.strictEqual(album.name, "Never Take Friendship Personal"); assert.strictEqual(album.year, 2005); assert.strictEqual(album.index, 0); assert.strictEqual(album.trackList.length, 2); assert.strictEqual(album.trackList[0].name, "Paperthin Hymn"); assert.strictEqual(album.trackList[0].index, 0); assert.strictEqual(album.trackList[1].name, "The Feel Good Drag"); assert.strictEqual(album.trackList[1].index, 1); }); it("searching", function() { var results = library.search("never drag"); assert.strictEqual(results.albumList.length, 1); assert.strictEqual(results.albumList[0].trackList.length, 1); assert.strictEqual(results.albumList[0].trackList[0].name, "The Feel Good Drag"); }); }); describe("compilation album", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "jqvq-tpiu", name: "No News Is Good News", artistName: "New Found Glory", albumName: "2004 Warped Tour Compilation [Disc 1]", year: 2004, disc: 1, discCount: 2, genre: "Alternative & Punk", albumArtistName: "Various Artists", track: 1, }); library.addTrack({ key: "dldd-itve", name: "American Errorist (I Hate Hate Haters)", artistName: "NOFX", albumName: "2004 Warped Tour Compilation [Disc 1]", year: 2004, disc: 1, discCount: 2, genre: "Alternative & Punk", albumArtistName: "Various Artists", track: 2, }); library.addTrack({ key: "ukjv-ndsz", name: "Fire Down Below", artistName: "Alkaline Trio", albumName: "2007 Warped Tour Compilation [Disc 1]", compilation: true, year: 2007, genre: "Alternative & Punk", track: 1, trackCount: 25, }); library.addTrack({ key: "gfkt-esqz", name: "Requiem For Dissent", artistName: "Bad Religion", albumName: "2007 Warped Tour Compilation [Disc 1]", compilation: true, year: 2007, genre: "Alternative & Punk", track: 2, trackCount: 25, }); library.rebuild(); it("filed in various artists", function() { assert.strictEqual(library.albumList.length, 2); assert.strictEqual(library.artistList.length, 1); var artist = library.artistList[0]; assert.strictEqual(artist.name, "Various Artists"); assert.strictEqual(artist.albumList.length, 2); assert.strictEqual(library.albumList.length, 2); assert.strictEqual(library.trackTable["jqvq-tpiu"].albumArtistName, ""); assert.strictEqual(library.trackTable["dldd-itve"].albumArtistName, ""); assert.strictEqual(library.trackTable["ukjv-ndsz"].albumArtistName, ""); assert.strictEqual(library.trackTable["gfkt-esqz"].albumArtistName, ""); }); }); describe("tracks from same album missing year metadata", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "wwxj-unhr", name: "Dog-Eared Page", artistName: "The Matches", albumName: "E. Von Dahl Killed the Locals", year: 2004, genre: "Punk", track: 1, }); library.addTrack({ key: "xekw-lvne", name: "Audio Blood", artistName: "The Matches", albumName: "E. Von Dahl Killed the Locals", // missing year genre: "Rock", track: 2, }); library.addTrack({ key: "lpka-dugc", name: "Chain Me Free", artistName: "The Matches", albumName: "E. Von Dahl Killed the Locals", year: 2004, genre: "Rock", track: 3, }); library.rebuild(); it("still knows they're in the same album", function() { assert.strictEqual(library.albumList.length, 1); assert.strictEqual(library.albumList[0].year, 2004); assert.strictEqual(library.trackTable["xekw-lvne"].album.year, 2004); }); }); describe("different albums with same name", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "sbao-lcvn", name: "6:00", artistName: "Dream Theater", albumName: "Awake", year: 1994, genre: "Progressive Rock", track: 1, }); library.addTrack({ key: "qtru-gdtp", name: "Awake", artistName: "Godsmack", albumName: "Awake", year: 2000, genre: "Rock", track: 2, }); library.rebuild(); it("detects that they are different", function() { assert.strictEqual(library.albumList.length, 2); }); }); describe("album with a few tracks by different artists", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "ikoe-nujf", name: "Paperthin Hymn", artistName: "Anberlin", albumArtistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 2, }); library.addTrack({ key: "msnq-swpc", name: "The Feel Good Drag", artistName: "Anberlin, some other band", albumArtistName: "Anberlin", albumName: "Never Take Friendship Personal", year: 2005, genre: "Other", track: 8, }); library.rebuild(); it("only creates one album", function() { assert.strictEqual(library.albumList.length, 1); }); }); describe("album by an artist", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "ynji-lcfu", name: "The Truth", artistName: "Relient K", albumName: "Apathetic ep", track: 1, trackCount: 7, }); library.addTrack({ key: "lxed-bsor", name: "Apathetic Way to Be", artistName: "Relient K", albumName: "Apathetic ep", track: 2, trackCount: 7, }); library.rebuild(); it("should be filed under the artist", function() { assert.strictEqual(library.artistList.length, 1); assert.strictEqual(library.artistList[0].name, "Relient K"); }); }); describe("album by an artist", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: "jqvq-tpiu", name: "No News Is Good News", artistName: "New Found Glory", albumName: "2004 Warped Tour Compilation", year: 2004, disc: 1, discCount: 2, genre: "Alternative & Punk", albumArtistName: "Various Artists", track: 1, }); library.addTrack({ key: "dldd-itve", name: "American Errorist (I Hate Hate Haters)", artistName: "NOFX", albumName: "2004 Warped Tour Compilation", year: 2004, disc: 1, discCount: 2, genre: "Alternative & Punk", albumArtistName: "Various Artists", track: 2, }); library.addTrack({ key: "ukjv-ndsz", name: "Fire Down Below", artistName: "Alkaline Trio", albumName: "2004 Warped Tour Compilation", disc: 2, compilation: true, year: 2004, genre: "Alternative & Punk", track: 1, trackCount: 25, }); library.addTrack({ key: "gfkt-esqz", name: "Requiem For Dissent", artistName: "Bad Religion", albumName: "2004 Warped Tour Compilation", disc: 2, compilation: true, year: 2004, genre: "Alternative & Punk", track: 2, trackCount: 25, }); library.rebuild(); it("sorts by disc before track", function() { assert.strictEqual(library.albumList[0].trackList[0].name, "No News Is Good News"); assert.strictEqual(library.albumList[0].trackList[1].name, "American Errorist (I Hate Hate Haters)"); assert.strictEqual(library.albumList[0].trackList[2].name, "Fire Down Below"); assert.strictEqual(library.albumList[0].trackList[3].name, "Requiem For Dissent"); }); }); describe("album artist with no album", function() { var library = new MusicLibraryIndex(); var id = '5a89ea73-71aa-4c22-97a5-3b3509131cca'; library.addTrack({ key: id, name: 'I Miss You', artistName: 'Blink 182', composerName: '', performerName: '', albumArtistName: 'blink-182', albumName: '', compilation: false, track: 3, duration: 227.6815, year: 2003, genre: 'Rock', }); library.rebuild(); it("shouldn't be various artists", function() { assert.notStrictEqual(library.trackTable[id].albumArtistName, "Various Artists"); }); }); describe("unknown artist, unknown album", function() { var library = new MusicLibraryIndex(); library.addTrack({ key: 'imnd-sxde', name: '01 Shining Armor', artistName: '', albumArtistName: '', albumName: '', }); library.addTrack({ key: 'jakg-nbfg', name: '02 Weird Kids', artistName: '', albumArtistName: '', albumName: '', }); library.rebuild(); var results = library; it("should be put into the same album", check); library.search("n"); results = library.search(""); it("searching should not affect anything", check); function check() { assert.strictEqual(results.artistList.length, 1); assert.strictEqual(results.artistList[0].albumList.length, 1); assert.strictEqual(results.artistList[0].albumList[0].trackList.length, 2); assert.strictEqual(results.artistList[0].albumList[0].trackList[0].album.trackList.length, 2); } }); describe("album with album artist", function() { var library = new MusicLibraryIndex(); var id1 = 'imnd-sxde'; library.addTrack({ key: id1, name: 'Palladio', artistName: 'Escala', albumArtistName: 'Escala', albumName: 'Escala', track: 1, }); var id2 = 'vewu-hqbx'; library.addTrack({ key: id2, name: 'Requiem for a Tower', artistName: 'Escala', albumArtistName: 'Escala', albumName: 'Escala', track: 2, }); var id3 = 'ixbc-oshh'; library.addTrack({ key: id3, name: 'Kashmir', artistName: 'Escala; Slash', albumArtistName: 'Escala', albumName: 'Escala', track: 3, }); library.rebuild(); it("shouldn't be various artists", function() { assert.strictEqual(library.trackTable[id1].albumArtistName, "Escala"); assert.strictEqual(library.trackTable[id2].albumArtistName, "Escala"); assert.strictEqual(library.artistList.length, 1); }); });