Skip to content

Commit

Permalink
Add task file and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Octowl committed Oct 5, 2018
1 parent bce4c14 commit 34310c8
Show file tree
Hide file tree
Showing 2 changed files with 382 additions and 0 deletions.
184 changes: 184 additions & 0 deletions functions.js
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));
198 changes: 198 additions & 0 deletions functions.spec.js
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);
});
});

0 comments on commit 34310c8

Please sign in to comment.