[Pkg-javascript-commits] [node-music-library-index] 01/02: Imported Upstream version 1.2.1

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Mon Jun 30 05:58:08 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to branch master
in repository node-music-library-index.

commit ef68aea9be2a3f76bf29452c81052e6524175eb3
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Mon Jun 30 05:46:41 2014 +0000

    Imported Upstream version 1.2.1
---
 .gitignore        |   1 +
 .jshintrc         |  73 +++++++++
 README.md         |  95 ++++++++++++
 index.js          | 308 +++++++++++++++++++++++++++++++++++++
 package.json      |  28 ++++
 test/benchmark.js |  35 +++++
 test/test.js      | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 988 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07e6e47
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/node_modules
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..7cb9418
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,73 @@
+{
+    // 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.
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fbdb5d3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,95 @@
+# 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 
+```
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..d62b9af
--- /dev/null
+++ b/index.js
@@ -0,0 +1,308 @@
+var 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();
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..31fcac4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "music-library-index",
+  "version": "1.2.1",
+  "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 <superjoe30 at gmail.com>",
+  "license": "MIT",
+  "dependencies": {
+    "diacritics": "~1.2.0"
+  },
+  "devDependencies": {
+    "mocha": "^1.17.1"
+  },
+  "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"
+  }
+}
diff --git a/test/benchmark.js b/test/benchmark.js
new file mode 100644
index 0000000..5a9f0f2
--- /dev/null
+++ b/test/benchmark.js
@@ -0,0 +1,35 @@
+// 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");
+}
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..8ae2ab8
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,448 @@
+var 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);
+  });
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-music-library-index.git



More information about the Pkg-javascript-commits mailing list