Add remove semicolons to .vscode settings, update BookFinder.test formatting

This commit is contained in:
advplyr 2023-11-18 13:41:08 -06:00
parent ecba67da6d
commit 80e061115f
2 changed files with 319 additions and 318 deletions

View File

@ -16,5 +16,6 @@
}, },
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.detectIndentation": true, "editor.detectIndentation": true,
"editor.tabSize": 2 "editor.tabSize": 2,
"javascript.format.semicolons": "remove"
} }

View File

@ -1,344 +1,344 @@
const sinon = require('sinon'); const sinon = require('sinon')
const chai = require('chai'); const chai = require('chai')
const expect = chai.expect; const expect = chai.expect
const bookFinder = require('../../../server/finders/BookFinder'); const bookFinder = require('../../../server/finders/BookFinder')
const { LogLevel } = require('../../../server/utils/constants') const { LogLevel } = require('../../../server/utils/constants')
const Logger = require('../../../server/Logger') const Logger = require('../../../server/Logger')
Logger.setLogLevel(LogLevel.INFO) Logger.setLogLevel(LogLevel.INFO)
describe('TitleCandidates', () => { describe('TitleCandidates', () => {
describe('cleanAuthor non-empty', () => { describe('cleanAuthor non-empty', () => {
let titleCandidates; let titleCandidates
const cleanAuthor = 'leo tolstoy'; const cleanAuthor = 'leo tolstoy'
beforeEach(() => { beforeEach(() => {
titleCandidates = new bookFinder.constructor.TitleCandidates(cleanAuthor); titleCandidates = new bookFinder.constructor.TitleCandidates(cleanAuthor)
}); })
describe('no adds', () => { describe('no adds', () => {
it('returns no candidates', () => { it('returns no candidates', () => {
expect(titleCandidates.getCandidates()).to.deep.equal([]); expect(titleCandidates.getCandidates()).to.deep.equal([])
})
})
describe('single add', () => {
[
['adds candidate', 'anna karenina', ['anna karenina']],
['adds lowercased candidate', 'ANNA KARENINA', ['anna karenina']],
['adds candidate, removing redundant spaces', 'anna karenina', ['anna karenina']],
['adds candidate, removing author', `anna karenina by ${cleanAuthor}`, ['anna karenina']],
['does not add empty candidate after removing author', cleanAuthor, []],
['adds candidate, removing subtitle', 'anna karenina: subtitle', ['anna karenina']],
['adds candidate + variant, removing "by ..."', 'anna karenina by arnold schwarzenegger', ['anna karenina', 'anna karenina by arnold schwarzenegger']],
['adds candidate + variant, removing bitrate', 'anna karenina 64kbps', ['anna karenina', 'anna karenina 64kbps']],
['adds candidate + variant, removing edition 1', 'anna karenina 2nd edition', ['anna karenina', 'anna karenina 2nd edition']],
['adds candidate + variant, removing edition 2', 'anna karenina 4th ed.', ['anna karenina', 'anna karenina 4th ed.']],
['adds candidate + variant, removing fie type', 'anna karenina.mp3', ['anna karenina', 'anna karenina.mp3']],
['adds candidate + variant, removing "a novel"', 'anna karenina a novel', ['anna karenina', 'anna karenina a novel']],
['adds candidate + variant, removing preceding/trailing numbers', '1 anna karenina 2', ['anna karenina', '1 anna karenina 2']],
['does not add empty candidate', '', []],
['does not add spaces-only candidate', ' ', []],
['does not add empty variant', '1984', ['1984']],
].forEach(([name, title, expected]) => it(name, () => {
titleCandidates.add(title);
expect(titleCandidates.getCandidates()).to.deep.equal(expected);
}));
})
describe('multiple adds', () => {
[
['demotes digits-only candidates', ['01', 'anna karenina'], ['anna karenina', '01']],
['promotes transformed variants', ['title1 1', 'title2 1'], ['title1', 'title2', 'title1 1', 'title2 1']],
['orders by position', ['title2', 'title1'], ['title2', 'title1']],
['dedupes candidates', ['title1', 'title1'], ['title1']],
].forEach(([name, titles, expected]) => it(name, () => {
for (const title of titles) titleCandidates.add(title)
expect(titleCandidates.getCandidates()).to.deep.equal(expected);
}));
}) })
}) })
describe('cleanAuthor empty', () => { describe('single add', () => {
let titleCandidates [
let cleanAuthor = '' ['adds candidate', 'anna karenina', ['anna karenina']],
['adds lowercased candidate', 'ANNA KARENINA', ['anna karenina']],
beforeEach(() => { ['adds candidate, removing redundant spaces', 'anna karenina', ['anna karenina']],
titleCandidates = new bookFinder.constructor.TitleCandidates(cleanAuthor) ['adds candidate, removing author', `anna karenina by ${cleanAuthor}`, ['anna karenina']],
}) ['does not add empty candidate after removing author', cleanAuthor, []],
['adds candidate, removing subtitle', 'anna karenina: subtitle', ['anna karenina']],
describe('single add', () => { ['adds candidate + variant, removing "by ..."', 'anna karenina by arnold schwarzenegger', ['anna karenina', 'anna karenina by arnold schwarzenegger']],
[ ['adds candidate + variant, removing bitrate', 'anna karenina 64kbps', ['anna karenina', 'anna karenina 64kbps']],
['adds a candidate', 'leo tolstoy', ['leo tolstoy']], ['adds candidate + variant, removing edition 1', 'anna karenina 2nd edition', ['anna karenina', 'anna karenina 2nd edition']],
].forEach(([name, title, expected]) => it(name, () => { ['adds candidate + variant, removing edition 2', 'anna karenina 4th ed.', ['anna karenina', 'anna karenina 4th ed.']],
titleCandidates.add(title) ['adds candidate + variant, removing fie type', 'anna karenina.mp3', ['anna karenina', 'anna karenina.mp3']],
expect(titleCandidates.getCandidates()).to.deep.equal(expected); ['adds candidate + variant, removing "a novel"', 'anna karenina a novel', ['anna karenina', 'anna karenina a novel']],
})) ['adds candidate + variant, removing preceding/trailing numbers', '1 anna karenina 2', ['anna karenina', '1 anna karenina 2']],
}) ['does not add empty candidate', '', []],
['does not add spaces-only candidate', ' ', []],
['does not add empty variant', '1984', ['1984']],
].forEach(([name, title, expected]) => it(name, () => {
titleCandidates.add(title)
expect(titleCandidates.getCandidates()).to.deep.equal(expected)
}))
})
describe('multiple adds', () => {
[
['demotes digits-only candidates', ['01', 'anna karenina'], ['anna karenina', '01']],
['promotes transformed variants', ['title1 1', 'title2 1'], ['title1', 'title2', 'title1 1', 'title2 1']],
['orders by position', ['title2', 'title1'], ['title2', 'title1']],
['dedupes candidates', ['title1', 'title1'], ['title1']],
].forEach(([name, titles, expected]) => it(name, () => {
for (const title of titles) titleCandidates.add(title)
expect(titleCandidates.getCandidates()).to.deep.equal(expected)
}))
}) })
}) })
describe('AuthorCandidates', () => { describe('cleanAuthor empty', () => {
let authorCandidates; let titleCandidates
const audnexus = { let cleanAuthor = ''
authorASINsRequest: sinon.stub().resolves([
{ name: 'Leo Tolstoy' },
{ name: 'Nikolai Gogol' },
{ name: 'J. K. Rowling' },
]),
};
describe('cleanAuthor is null', () => {
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(null, audnexus);
});
describe('no adds', () => {
[
['returns empty author candidate', []],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
});
describe('single add', () => {
[
['adds recognized candidate', 'nikolai gogol', ['nikolai gogol']],
['does not add unrecognized candidate', 'fyodor dostoevsky', []],
['adds recognized author if candidate is a superstring', 'dr. nikolai gogol', ['nikolai gogol']],
['adds candidate if it is a substring of recognized author', 'gogol', ['gogol']],
['adds recognized author if edit distance from candidate is small', 'nicolai gogol', ['nikolai gogol']],
['does not add candidate if edit distance from any recognized author is large', 'nikolai google', []],
['adds normalized recognized candidate (contains redundant spaces)', 'nikolai gogol', ['nikolai gogol']],
['adds normalized recognized candidate (normalized initials)', 'j.k. rowling', ['j. k. rowling']],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}));
})
describe('multi add', () => {
[
['adds recognized author candidates', ['nikolai gogol', 'leo tolstoy'], ['nikolai gogol', 'leo tolstoy']],
['dedupes author candidates', ['nikolai gogol', 'nikolai gogol'], ['nikolai gogol']],
].forEach(([name, authors, expected]) => it(name, async () => {
for (const author of authors) authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
});
describe('cleanAuthor is a recognized author', () => {
const cleanAuthor = 'leo tolstoy';
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus);
});
describe('no adds', () => {
[
['adds cleanAuthor as candidate', [cleanAuthor]],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate', 'nikolai gogol', [cleanAuthor, 'nikolai gogol']],
['does not add candidate if it is a dupe of cleanAuthor', cleanAuthor, [cleanAuthor]],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
});
describe('cleanAuthor is an unrecognized author', () => {
const cleanAuthor = 'Fyodor Dostoevsky';
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus);
});
describe('no adds', () => {
[
['adds cleanAuthor as candidate', [cleanAuthor]],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate and removes cleanAuthor', 'nikolai gogol', ['nikolai gogol']],
['does not add unrecognized candidate', 'jackie chan', [cleanAuthor]],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
});
describe('cleanAuthor is unrecognized and dirty', () => {
describe('no adds', () => {
[
['adds aggressively cleaned cleanAuthor', 'fyodor dostoevsky, translated by jackie chan', ['fyodor dostoevsky']],
['adds cleanAuthor if aggresively cleaned cleanAuthor is empty', ', jackie chan', [', jackie chan']],
].forEach(([name, cleanAuthor, expected]) => it(name, async () => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate and removes cleanAuthor', 'fyodor dostoevsky, translated by jackie chan', 'nikolai gogol', ['nikolai gogol']],
].forEach(([name, cleanAuthor, author, expected]) => it(name, async () => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
});
});
describe('search', () => {
const t = 'title';
const a = 'author';
const u = 'unrecognized';
const r = ['book'];
const runSearchStub = sinon.stub(bookFinder, 'runSearch')
runSearchStub.resolves([])
runSearchStub.withArgs(t, a).resolves(r);
runSearchStub.withArgs(t, u).resolves(r);
const audnexusStub = sinon.stub(bookFinder.audnexus, 'authorASINsRequest')
audnexusStub.resolves([ { name: a } ])
beforeEach(() => { beforeEach(() => {
bookFinder.runSearch.resetHistory(); titleCandidates = new bookFinder.constructor.TitleCandidates(cleanAuthor)
}); })
describe('search title is empty', () => { describe('single add', () => {
it('returns empty result', async () => {
expect(await bookFinder.search('', '', a)).to.deep.equal([]);
sinon.assert.callCount(bookFinder.runSearch, 0);
});
});
describe('search title is a recognized title and search author is a recognized author', () => {
it('returns non-empty result (no fuzzy searches)', async () => {
expect(await bookFinder.search('', t, a)).to.deep.equal(r);
sinon.assert.callCount(bookFinder.runSearch, 1);
});
});
describe('search title contains recognized title and search author is a recognized author', () => {
[ [
[`${t} -`], ['adds a candidate', 'leo tolstoy', ['leo tolstoy']],
[`${t} - ${a}`], ].forEach(([name, title, expected]) => it(name, () => {
[`${a} - ${t}`], titleCandidates.add(title)
[`${t}- ${a}`], expect(titleCandidates.getCandidates()).to.deep.equal(expected)
[`${t} -${a}`], }))
[`${t} ${a}`], })
[`${a} - ${t} (unabridged)`], })
[`${a} - ${t} (subtitle) - mp3`], })
[`${t} {narrator} - series-01 64kbps 10:00:00`],
[`${a} - ${t} (2006) narrated by narrator [unabridged]`],
[`${t} - ${a} 2022 mp3`],
[`01 ${t}`],
[`2022_${t}_HQ`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns non-empty result (with 1 fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal(r);
sinon.assert.callCount(bookFinder.runSearch, 2);
});
});
describe('AuthorCandidates', () => {
let authorCandidates
const audnexus = {
authorASINsRequest: sinon.stub().resolves([
{ name: 'Leo Tolstoy' },
{ name: 'Nikolai Gogol' },
{ name: 'J. K. Rowling' },
]),
}
describe('cleanAuthor is null', () => {
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(null, audnexus)
})
describe('no adds', () => {
[
['returns empty author candidate', []],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate', 'nikolai gogol', ['nikolai gogol']],
['does not add unrecognized candidate', 'fyodor dostoevsky', []],
['adds recognized author if candidate is a superstring', 'dr. nikolai gogol', ['nikolai gogol']],
['adds candidate if it is a substring of recognized author', 'gogol', ['gogol']],
['adds recognized author if edit distance from candidate is small', 'nicolai gogol', ['nikolai gogol']],
['does not add candidate if edit distance from any recognized author is large', 'nikolai google', []],
['adds normalized recognized candidate (contains redundant spaces)', 'nikolai gogol', ['nikolai gogol']],
['adds normalized recognized candidate (normalized initials)', 'j.k. rowling', ['j. k. rowling']],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('multi add', () => {
[
['adds recognized author candidates', ['nikolai gogol', 'leo tolstoy'], ['nikolai gogol', 'leo tolstoy']],
['dedupes author candidates', ['nikolai gogol', 'nikolai gogol'], ['nikolai gogol']],
].forEach(([name, authors, expected]) => it(name, async () => {
for (const author of authors) authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
})
describe('cleanAuthor is a recognized author', () => {
const cleanAuthor = 'leo tolstoy'
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
})
describe('no adds', () => {
[
['adds cleanAuthor as candidate', [cleanAuthor]],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate', 'nikolai gogol', [cleanAuthor, 'nikolai gogol']],
['does not add candidate if it is a dupe of cleanAuthor', cleanAuthor, [cleanAuthor]],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
})
describe('cleanAuthor is an unrecognized author', () => {
const cleanAuthor = 'Fyodor Dostoevsky'
beforeEach(() => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
})
describe('no adds', () => {
[
['adds cleanAuthor as candidate', [cleanAuthor]],
].forEach(([name, expected]) => it(name, async () => {
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate and removes cleanAuthor', 'nikolai gogol', ['nikolai gogol']],
['does not add unrecognized candidate', 'jackie chan', [cleanAuthor]],
].forEach(([name, author, expected]) => it(name, async () => {
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
})
describe('cleanAuthor is unrecognized and dirty', () => {
describe('no adds', () => {
[
['adds aggressively cleaned cleanAuthor', 'fyodor dostoevsky, translated by jackie chan', ['fyodor dostoevsky']],
['adds cleanAuthor if aggresively cleaned cleanAuthor is empty', ', jackie chan', [', jackie chan']],
].forEach(([name, cleanAuthor, expected]) => it(name, async () => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
describe('single add', () => {
[
['adds recognized candidate and removes cleanAuthor', 'fyodor dostoevsky, translated by jackie chan', 'nikolai gogol', ['nikolai gogol']],
].forEach(([name, cleanAuthor, author, expected]) => it(name, async () => {
authorCandidates = new bookFinder.constructor.AuthorCandidates(cleanAuthor, audnexus)
authorCandidates.add(author)
expect(await authorCandidates.getCandidates()).to.deep.equal([...expected, ''])
}))
})
})
})
describe('search', () => {
const t = 'title'
const a = 'author'
const u = 'unrecognized'
const r = ['book']
const runSearchStub = sinon.stub(bookFinder, 'runSearch')
runSearchStub.resolves([])
runSearchStub.withArgs(t, a).resolves(r)
runSearchStub.withArgs(t, u).resolves(r)
const audnexusStub = sinon.stub(bookFinder.audnexus, 'authorASINsRequest')
audnexusStub.resolves([{ name: a }])
beforeEach(() => {
bookFinder.runSearch.resetHistory()
})
describe('search title is empty', () => {
it('returns empty result', async () => {
expect(await bookFinder.search('', '', a)).to.deep.equal([])
sinon.assert.callCount(bookFinder.runSearch, 0)
})
})
describe('search title is a recognized title and search author is a recognized author', () => {
it('returns non-empty result (no fuzzy searches)', async () => {
expect(await bookFinder.search('', t, a)).to.deep.equal(r)
sinon.assert.callCount(bookFinder.runSearch, 1)
})
})
describe('search title contains recognized title and search author is a recognized author', () => {
[
[`${t} -`],
[`${t} - ${a}`],
[`${a} - ${t}`],
[`${t}- ${a}`],
[`${t} -${a}`],
[`${t} ${a}`],
[`${a} - ${t} (unabridged)`],
[`${a} - ${t} (subtitle) - mp3`],
[`${t} {narrator} - series-01 64kbps 10:00:00`],
[`${a} - ${t} (2006) narrated by narrator [unabridged]`],
[`${t} - ${a} 2022 mp3`],
[`01 ${t}`],
[`2022_${t}_HQ`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns non-empty result (with 1 fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal(r)
sinon.assert.callCount(bookFinder.runSearch, 2)
})
});
[
[`s-01 - ${t} (narrator) 64kbps 10:00:00`],
[`${a} - series 01 - ${t}`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns non-empty result (with 2 fuzzy searches)`, async () => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal(r)
sinon.assert.callCount(bookFinder.runSearch, 3)
})
});
[
[`${t}-${a}`],
[`${t} junk`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns an empty result`, async () => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal([])
})
})
describe('maxFuzzySearches = 0', () => {
[
[`${t} - ${a}`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns an empty result (with no fuzzy searches)`, async () => {
expect(await bookFinder.search('', searchTitle, a, null, null, { maxFuzzySearches: 0 })).to.deep.equal([])
sinon.assert.callCount(bookFinder.runSearch, 1)
})
})
})
describe('maxFuzzySearches = 1', () => {
[ [
[`s-01 - ${t} (narrator) 64kbps 10:00:00`], [`s-01 - ${t} (narrator) 64kbps 10:00:00`],
[`${a} - series 01 - ${t}`], [`${a} - series 01 - ${t}`],
].forEach(([searchTitle]) => { ].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns non-empty result (with 2 fuzzy searches)`, async () => { it(`search('${searchTitle}', '${a}') returns an empty result (1 fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal(r); expect(await bookFinder.search('', searchTitle, a, null, null, { maxFuzzySearches: 1 })).to.deep.equal([])
sinon.assert.callCount(bookFinder.runSearch, 3); sinon.assert.callCount(bookFinder.runSearch, 2)
}); })
}); })
})
})
[ describe('search title contains recognized title and search author is empty', () => {
[`${t}-${a}`], [
[`${t} junk`], [`${t} - ${a}`],
].forEach(([searchTitle]) => { [`${a} - ${t}`],
it(`search('${searchTitle}', '${a}') returns an empty result`, async () => { ].forEach(([searchTitle]) => {
expect(await bookFinder.search('', searchTitle, a)).to.deep.equal([]); it(`search('${searchTitle}', '') returns a non-empty result (1 fuzzy search)`, async () => {
}); expect(await bookFinder.search('', searchTitle, '')).to.deep.equal(r)
}); sinon.assert.callCount(bookFinder.runSearch, 2)
})
describe('maxFuzzySearches = 0', () => {
[
[`${t} - ${a}`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns an empty result (with no fuzzy searches)`, async () => {
expect(await bookFinder.search('', searchTitle, a, null, null, { maxFuzzySearches: 0 })).to.deep.equal([]);
sinon.assert.callCount(bookFinder.runSearch, 1);
});
});
});
describe('maxFuzzySearches = 1', () => {
[
[`s-01 - ${t} (narrator) 64kbps 10:00:00`],
[`${a} - series 01 - ${t}`],
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${a}') returns an empty result (1 fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, a, null, null, { maxFuzzySearches: 1 })).to.deep.equal([]);
sinon.assert.callCount(bookFinder.runSearch, 2);
});
});
});
}); });
describe('search title contains recognized title and search author is empty', () => { [
[ [`${t}`],
[`${t} - ${a}`], [`${t} - ${u}`],
[`${a} - ${t}`], [`${u} - ${t}`]
].forEach(([searchTitle]) => { ].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '') returns a non-empty result (1 fuzzy search)`, async () => { it(`search('${searchTitle}', '') returns an empty result`, async () => {
expect(await bookFinder.search('', searchTitle, '')).to.deep.equal(r); expect(await bookFinder.search('', searchTitle, '')).to.deep.equal([])
sinon.assert.callCount(bookFinder.runSearch, 2); })
}); })
}); })
[ describe('search title contains recognized title and search author is an unrecognized author', () => {
[`${t}`], [
[`${t} - ${u}`], [`${t} - ${u}`],
[`${u} - ${t}`] [`${u} - ${t}`]
].forEach(([searchTitle]) => { ].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '') returns an empty result`, async () => { it(`search('${searchTitle}', '${u}') returns a non-empty result (1 fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, '')).to.deep.equal([]); expect(await bookFinder.search('', searchTitle, u)).to.deep.equal(r)
}); sinon.assert.callCount(bookFinder.runSearch, 2)
}); })
}); });
describe('search title contains recognized title and search author is an unrecognized author', () => { [
[ [`${t}`]
[`${t} - ${u}`], ].forEach(([searchTitle]) => {
[`${u} - ${t}`] it(`search('${searchTitle}', '${u}') returns a non-empty result (no fuzzy search)`, async () => {
].forEach(([searchTitle]) => { expect(await bookFinder.search('', searchTitle, u)).to.deep.equal(r)
it(`search('${searchTitle}', '${u}') returns a non-empty result (1 fuzzy search)`, async () => { sinon.assert.callCount(bookFinder.runSearch, 1)
expect(await bookFinder.search('', searchTitle, u)).to.deep.equal(r); })
sinon.assert.callCount(bookFinder.runSearch, 2); })
}); })
}); })
[
[`${t}`]
].forEach(([searchTitle]) => {
it(`search('${searchTitle}', '${u}') returns a non-empty result (no fuzzy search)`, async () => {
expect(await bookFinder.search('', searchTitle, u)).to.deep.equal(r);
sinon.assert.callCount(bookFinder.runSearch, 1);
});
});
});
});