-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/************************************************************** | ||
* getBookById(bookId, books): | ||
* - receives a bookId | ||
* - recieves an array of book objects | ||
* - returns the book object that matches that id | ||
* - returns undefined if no matching book is found | ||
****************************************************************/ | ||
function getBookById(bookId, books) { | ||
// Your code goes here | ||
// return books.find(book => book.id === bookId); | ||
} | ||
|
||
/************************************************************** | ||
* getAuthorByName(authorName, authors): | ||
* - receives an authorName | ||
* - recieves an array of author objects | ||
* - returns the author that matches that name (CASE INSENSITIVE) | ||
* - returns undefined if no matching author is found | ||
****************************************************************/ | ||
function getAuthorByName(authorName, authors) { | ||
// Your code goes here | ||
// return authors.find( | ||
// author => author.name.toLowerCase() === authorName.toLowerCase() | ||
// ); | ||
} | ||
|
||
/************************************************************** | ||
* bookCountsByAuthor(authors): | ||
* - receives an array of authors | ||
* - returns an array of objects with the format: | ||
* [{ author: <NAME>, bookCount: <NUMBER_OF_BOOKS> }] | ||
****************************************************************/ | ||
function bookCountsByAuthor(authors) { | ||
// Your code goes here | ||
// return authors.map(author => ({ | ||
// author: author.name, | ||
// bookCount: author.books.length | ||
// })); | ||
} | ||
|
||
/************************************************************** | ||
* booksByColor(books): | ||
* - receives an array of books | ||
* - returns an object where the keys ar colors | ||
* and the values are arrays of book titles: | ||
* { <COLOR>: [<BOOK_TITLES>] } | ||
****************************************************************/ | ||
function booksByColor(books) { | ||
const colors = {}; | ||
|
||
// Your code goes here | ||
// books.forEach(book => { | ||
// if (colors[book.color]) { | ||
// colors[book.color].push(book.title); | ||
// } else { | ||
// colors[book.color] = [book.title]; | ||
// } | ||
// }); | ||
|
||
return colors; | ||
} | ||
|
||
/************************************************************** | ||
* titlesByAuthorName(authorName, authors, books): | ||
* - receives an authorName | ||
* - recieves an array of author objects | ||
* - recieves an array of book objects | ||
* - returns an array of the titles of the books written by that author: | ||
* ["The Hitchhikers Guide", "The Meaning of Liff"] | ||
****************************************************************/ | ||
function titlesByAuthorName(authorName, authors, books) { | ||
// Your code goes here | ||
// const author = getAuthorByName(authorName, authors); | ||
// if (!author) return []; | ||
// return author.books.map(bookId => getBookById(bookId, books).title); | ||
} | ||
|
||
/************************************************************** | ||
* mostProlificAuthor(authors): | ||
* - receives a list of authors | ||
* - returns the name of the author with the most books | ||
* | ||
* Note: assume there will never be a tie | ||
****************************************************************/ | ||
function mostProlificAuthor(authors) { | ||
// Your code goes here | ||
// let prolificAuthor = authors[0]; | ||
// authors.forEach(author => { | ||
// if (author.books.length > prolificAuthor.books.length) { | ||
// prolificAuthor = author; | ||
// } | ||
// }); | ||
// return prolificAuthor.name; | ||
/* One-liner using reduce and a ternary operator */ | ||
// return authors.reduce((a, b) => (a.books.length > b.books.length ? a : b)) | ||
// .name; | ||
} | ||
|
||
/************************************************************** | ||
* relatedBooks(bookId, books): | ||
* - receives a bookId | ||
* - receives a list of authors | ||
* - receives a list of books | ||
* - returns a list of the titles of all the books by | ||
* the same author as the book with bookId | ||
* (including the original book) | ||
* | ||
* NOTES: YOU NEED TO TAKE INTO ACCOUNT BOOKS WITH MULTIPLE AUTHORS | ||
* BONUS: REMOVE DUPLICATE BOOKS | ||
****************************************************************/ | ||
function relatedBooks(bookId, authors, books) { | ||
// Your code goes here | ||
// const book = getBookById(bookId, books); | ||
// let titles = []; | ||
// book.authors.forEach( | ||
// author => | ||
// (titles = titles.concat(titlesByAuthorName(author.name, authors, books))) | ||
// ); | ||
// /* BONUS */ | ||
// // titles = [...new Set(titles)]; | ||
// return titles; | ||
/* "One-liner" using reduce */ | ||
// return getBookById(bookId, books).authors.reduce( | ||
// (titles, author) => [ | ||
// ...new Set(titles.concat(titlesByAuthorName(author.name, authors, books))) | ||
// ], | ||
// [] | ||
// ); | ||
} | ||
|
||
/************************************************************** | ||
* friendliestAuthor(authors): | ||
* - receives a list of authors | ||
* - returns the name of the author that has | ||
* co-authored the greatest number of books | ||
****************************************************************/ | ||
function friendliestAuthor(authors) { | ||
// authors.forEach(author => { | ||
// author.coauthoringCount = 0; | ||
// authors.forEach(secondAuthor => { | ||
// if (secondAuthor.name !== author.name) { | ||
// const sharedBooks = secondAuthor.books.filter(bookId => | ||
// author.books.includes(bookId) | ||
// ); | ||
// author.coauthoringCount += sharedBooks.length; | ||
// } | ||
// }); | ||
// }); | ||
// let friendlyAuthor = authors[0]; | ||
// authors.forEach(author => { | ||
// if (author.coauthoringCount > friendlyAuthor.coauthoringCount) { | ||
// friendlyAuthor = author; | ||
// } | ||
// }); | ||
// return friendlyAuthor.name; | ||
} | ||
|
||
module.exports = { | ||
getBookById, | ||
getAuthorByName, | ||
bookCountsByAuthor, | ||
booksByColor, | ||
titlesByAuthorName, | ||
mostProlificAuthor, | ||
relatedBooks, | ||
friendliestAuthor | ||
}; | ||
|
||
/** | ||
* Uncomment the following lines if you | ||
* want to manually test your code | ||
*/ | ||
|
||
// const authors = require("./authors.json"); | ||
// const books = require("./books.json"); | ||
|
||
// console.log(getBookById(12, books)); | ||
// console.log(getAuthorByName("J.K. Rowling", authors)); | ||
// console.log(bookCountsByAuthor(authors)); | ||
// console.log(booksByColor(books)); | ||
// console.log(titlesByAuthorName("George R.R. Martin", authors, books)); | ||
// console.log(mostProlificAuthor(authors)); | ||
// console.log(relatedBooks(50, books)); | ||
// console.log(friendliestAuthor(authors)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/************************** | ||
* | ||
* THIS IS A TESTING FILE | ||
* | ||
* DO NOT MODIFY THIS FILE | ||
* | ||
***************************/ | ||
|
||
import { | ||
getBookById, | ||
getAuthorByName, | ||
bookCountsByAuthor, | ||
booksByColor, | ||
titlesByAuthorName, | ||
mostProlificAuthor, | ||
relatedBooks, | ||
friendliestAuthor | ||
} from "./functions"; | ||
|
||
// Data | ||
import authors from "./authors.json"; | ||
import books from "./books.json"; | ||
|
||
describe("getBookById(bookId, books)", () => { | ||
test("returns the correct book", () => { | ||
const expected = books[Math.floor(Math.random() * books.length)]; | ||
const result = getBookById(expected.id, books); | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
test("returns undefined if the book is not found", () => { | ||
const result = getBookById(10000, books); | ||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe("getAuthorByName(authorName, authors)", () => { | ||
test("returns the correct author", () => { | ||
const expected = authors[Math.floor(Math.random() * authors.length)]; | ||
const result = getAuthorByName(expected.name, authors); | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
test("is case insensitive", () => { | ||
const expected = authors[Math.floor(Math.random() * authors.length)]; | ||
let result = getAuthorByName(expected.name.toLowerCase(), authors); | ||
expect(result).toBe(expected); | ||
result = getAuthorByName(expected.name.toUpperCase(), authors); | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
test("returns undefined if the author is not found", () => { | ||
const result = getAuthorByName("Dr Patatis", authors); | ||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe("bookCountsByAuthor(authors)", () => { | ||
test("returns the correct number of objects", () => { | ||
const expected = authors.length; | ||
const result = bookCountsByAuthor(authors).length; | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
test("returns the correct format", () => { | ||
const result = bookCountsByAuthor(authors).every(author => { | ||
const keys = Object.keys(author); | ||
return keys.includes("author") && keys.includes("bookCount"); | ||
}); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
test("returns the correct data", () => { | ||
const expected = [ | ||
{ author: "Margaret Atwood", bookCount: 4 }, | ||
{ author: "Lauren Beukes", bookCount: 2 } | ||
]; | ||
const result = bookCountsByAuthor(authors.slice(0, 2)); | ||
expect(result).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe("booksByColor(books)", () => { | ||
test("returns the correct number of colors", () => { | ||
const expected = 2; | ||
const onlyGreenAndBlueBooks = books.filter( | ||
book => book.color === "green" || book.color === "blue" | ||
); | ||
const result = Object.keys(booksByColor(onlyGreenAndBlueBooks)).length; | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
test("returns the correct format", () => { | ||
const result = Object.values(booksByColor(books)).every(bookList => | ||
Array.isArray(bookList) | ||
); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
test("returns the correct data", () => { | ||
const expected = { | ||
white: [ | ||
"12 Rules for Life: An Antidote to Chaos", | ||
"A Dance With Dragons" | ||
], | ||
yellow: ["A Clash of Kings"], | ||
red: ["A Feast for Crows"] | ||
}; | ||
const result = booksByColor(books.slice(0, 4)); | ||
expect(result).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe("titlesByAuthorName(authorName, authors, books)", () => { | ||
test("returns the correct list of books", () => { | ||
let expected = ["The Shining Girls", "Zoo City"].sort(); | ||
let result = titlesByAuthorName("Lauren Beukes", authors, books).sort(); | ||
expect(result).toEqual(expected); | ||
expected = ["Jane Eyre"]; | ||
result = titlesByAuthorName("Charlotte Brontë", authors, books); | ||
expect(result).toEqual(expected); | ||
}); | ||
|
||
test("is case-insensitive", () => { | ||
let expected = ["The Shining Girls", "Zoo City"].sort(); | ||
let result = titlesByAuthorName("LaUreN BEukeS", authors, books).sort(); | ||
expect(result).toEqual(expected); | ||
expected = ["Jane Eyre"]; | ||
result = titlesByAuthorName("CHaRlOttE BRontë", authors, books); | ||
expect(result).toEqual(expected); | ||
}); | ||
|
||
test("returns an empty array if the author is not found", () => { | ||
const result = titlesByAuthorName("Dr Patatis", authors, books); | ||
expect(result).toEqual([]); | ||
}); | ||
}); | ||
|
||
describe("mostProlificAuthor(authors)", () => { | ||
test("returns the correct author name", () => { | ||
const expected = "Agatha Christie"; | ||
const result = mostProlificAuthor(authors.slice(0, 5)); | ||
expect(result).toBe(expected); | ||
}); | ||
}); | ||
|
||
describe("relatedBooks(bookId, authors, books)", () => { | ||
test("returns the correct books", () => { | ||
const expected = ["The Shining Girls", "Zoo City"].sort(); | ||
const result = relatedBooks(37, authors, books).sort(); | ||
expect(result).toEqual(expected); | ||
}); | ||
|
||
test("can handle co-authored books - returns the titles of books by BOTH authors", () => { | ||
const expected = [ | ||
"Good Omens", | ||
"Good Omens", | ||
"Neverwhere", | ||
"Coraline", | ||
"The Color of Magic", | ||
"The Hogfather", | ||
"Wee Free Men", | ||
"The Long Earth", | ||
"The Long War", | ||
"The Long Mars" | ||
].sort(); | ||
const result = relatedBooks(46, authors, books).sort(); | ||
expect(result).toEqual(expected); | ||
}); | ||
|
||
/** | ||
* Remove the x to unskip and run the bonus test. | ||
* Add an x to the previous test to skip it | ||
*/ | ||
xtest("BONUS - removes duplicate books", () => { | ||
const expected = [ | ||
"Good Omens", | ||
"Neverwhere", | ||
"Coraline", | ||
"The Color of Magic", | ||
"The Hogfather", | ||
"Wee Free Men", | ||
"The Long Earth", | ||
"The Long War", | ||
"The Long Mars" | ||
].sort(); | ||
const result = relatedBooks(46, authors, books).sort(); | ||
expect(result).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe("friendliestAuthor(authors)", () => { | ||
test("returns the correct author", () => { | ||
const expected = "Terry Pratchett"; | ||
const result = friendliestAuthor(authors); | ||
expect(result).toEqual(expected); | ||
}); | ||
}); |