From c6363c6eedb81d71d32434e21ce3c67881dcae36 Mon Sep 17 00:00:00 2001 From: Harriet Ryder Date: Thu, 31 Oct 2019 17:29:28 +0000 Subject: [PATCH] Update requirements --- app/Book.js | 9 -- app/catalogue_service.js | 30 +++---- docs/TASKS.md | 147 +++++++++++++++++++-------------- test/Book.test.js | 73 ---------------- test/catalogue_service.test.js | 20 ++--- 5 files changed, 107 insertions(+), 172 deletions(-) delete mode 100644 app/Book.js delete mode 100644 test/Book.test.js diff --git a/app/Book.js b/app/Book.js deleted file mode 100644 index 8e0b78e..0000000 --- a/app/Book.js +++ /dev/null @@ -1,9 +0,0 @@ -class Book { - constructor(title, author, quantity) { - this.title = title; - this.author = author; - this.quantity = quantity; - } -} - -module.exports = Book; diff --git a/app/catalogue_service.js b/app/catalogue_service.js index 90ffcbb..3e935a9 100644 --- a/app/catalogue_service.js +++ b/app/catalogue_service.js @@ -19,38 +19,38 @@ const catalogue = [ "Great Expectations by Charles Dickens (1)", "The Blind Assassin by Margaret Atwood (8)", "Why Be Happy When You Could Be Normal? by Jeanette Winterson (19)", - "The Origin of Species by Charles Darwin (50)", + "The Origin of Species by Charles Darwin (50)" ]; -function checkBook(title) { - if (!title) throw new Error("Please provide a title"); +function countBooksByAuthor(author) { // Your code here } -function countBooksByKeyword(keyword) { - if (!keyword) throw new Error("Please provide a keyword"); +function checkBookByTitle(title) { // Your code here } -function getBooksByAuthor(author) { - if (!author) throw new Error("Please provide an author"); +function countBooksByFirstLetter(letter) { // Your code here } -function getStockCount(title) { - if (!title) throw new Error("Please provide a title"); +function getQuantity(title) { + // Your code here +} + +function getBooksByAuthor(author) { // Your code here } -function stockReview(title) { - if (!title) throw new Error("Please provide a title"); +function checkQuantity(title, quantity) { // Your code here } module.exports = { - checkBook, - countBooksByKeyword, + countBooksByAuthor, + checkBookByTitle, + countBooksByFirstLetter, + getQuantity, getBooksByAuthor, - getStockCount, - stockReview + checkQuantity }; diff --git a/docs/TASKS.md b/docs/TASKS.md index 34973cb..f2f38c3 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -52,115 +52,142 @@ const catalogue = [ Update **every** book in the array and save the file. -## 3) Implement the catalogue functions +## 3) Run the tests for the `countBooksByAuthor` function -Time to implement the 5 catalogue functions. You have already implemented these earlier in the week, in [programming_fundamentals_002](https://github.com/techreturners/programming_fundamentals_002), but now you need to make sure all the functions work with an _array of objects_ instead of an array of strings. +The tests for `countBooksByAuthor` are already written. -Tests are already written for the `checkBook` function but you will need to write your own tests for the other functions. +Run `npm test` in the terminal to run them. See that they fail. -This is likely to take you some time. +In these tests, we have written **three expectations** in the same test, as 3 examples of the same behaviour. All 3 expectations must pass for the test to pass: -Feel free to refer to your previous work for help, and to the [Tasks for programming_fundamentals_002](https://github.com/techreturners/programming_fundamentals_002/blob/master/docs/TASKS.md) if you need a reminder of how the Catalogue Service functions should behave. +```javascript +describe("catalogueService.countBooksByAuthor", () => { + test("returns the total number of books written by the given author", () => { + expect(catalogueService.countBooksByAuthor("Hilary Mantel")).toBe(5); + expect(catalogueService.countBooksByAuthor("Celeste Ng")).toBe(2); + expect(catalogueService.countBooksByAuthor("Charles Dickens")).toBe(3); + }); +}); +``` -## 4) A Book Class +## 4) Implement the `countBooksByAuthor` function -Currently you have created individual book objects withou the use of a class: +This function should return the total number of books in the catalogue written by the given author. -```javascript -const catalogue = [ - {title: "The Catcher in the Rye", author: "J.D. Salinger", quantity: 10}, - {title: "Dracula", author: "Bram Stoker", quantity: 0}, - {title: "Between the Assassinations", author: "Aravind Adiga", quantity: 9}, - ... -]; -``` +For example, there are 5 books by Hilary Mantel and 1 by Celeste Ng. -However, we might want to create a Class of `Book` to make it easier to create new books that follow a common blueprint, and to encapsulate common behaviour. +Go to the `app/catalogue_service.js` file and implement the function so that the tests pass. -Open the file `Book.js` in the `/app` directory and take a look at the class defined in there. +## 5) Write a test for the `checkBookByTitle` function -Now open `test/Book.test.js` and look at the tests which have been written for the book class. +This function receives a title as an argument and should return `true` if a book with this title exists in the array, and `false` otherwise. -The first test should be passing, but all the other tests are disabled, with a little `x` at the beginning of the `describe` block: +E.g. ```javascript -xdescribe("addStock()", () => { - // tests here -}); - +checkBookByTitle("The Origin of Species"); // true +checkBookByTitle("The Chronicles of Narnia"); // false ``` -Remove the `x` from the beginning of the `addStock()` tests and run `npm test` in the terminal to run the next set of tests too. +Your test suite now may look as follows: ```javascript -describe("addStock()", () => { - // tests here +describe("catalogueService", () => { + describe("catalogueService.countBooksByAuthor", () => { + test("returns the total number of books written by the given author", () => { + expect(catalogueService.countBooksByAuthor("Hilary Mantel")).toBe(5); + expect(catalogueService.countBooksByAuthor("Celeste Ng")).toBe(2); + expect(catalogueService.countBooksByAuthor("Charles Dickens")).toBe(3); + }); + }); + + describe("catalogueService.checkBookByTitle", () => { + test("returns true if the book exists", () => { + expect( + catalogueService.checkBookByTitle( + "The Assassination of Margaret Thatcher" + ) + ).toBe(5); + }); + }); }); ``` -You should see the following error: - -``` -TypeError: book.addStock is not a function -``` +## 6) Implement the `checkBookByTitle` function -## 5) Create an addStock method for a book +Go to the `app/catalogue_service.js` file and implement the function so that the tests you have just written pass. -Create an `addStock` method inside the `Book` class. +## 7) The other case -This method should take an argument of a number, and increase the number of books in stock by this number. +Write another test that ensures the function `checkBookByTitle` returns false when the book does not exists. -Run the tests again to ensure that they all pass. +Run this test and see whether it passes or fails. -## 6) Un-x the next test +If it fails, you'll need to update your function to ensure it returns `false` if the book is not found. -Now un-x the next test which tests the `removeStock()` method. +## 8) The `countBooksByFirstLetter` function -Run the tests and see that they fail. +This function should receive a letter as an argument (e.g. "H") and return the total number of books that begin with this letter. Note that the quantity is not relevant here. For example: -## 7) Create a removeStock method for a book +```javascript +countBooksByFirstLetter("W"); // returns 2 +``` -Create a `removeStock` method inside the `Book` class. +This returns 2 because Wolf Hall and Why Be Happy When You Could Be Normal? both begin with W. -This method should take an argument of a number, and decrease the number of books in stock by this number. +Begin by writing a test, as always, before implementing the function. -Note that the number of books in stock cannot fall below 0. +## 9) A lowercase letter -Run the tests again to ensure that they all pass. +What if the `countBooksByFirstLetter` function is given a lowercase letter, e.g. `countBooksByFirstLetter("h")`? -## 8) An array of Book Objects +It should still count the books beginning with H, ignoring the case of the letter. -Now we should be able to use our `Book` class to create the book objects that are populating our `catalogue` array. +Write a test for this functionality, and if the test doesn't pass, update you function so that it passes. -First, we need to **require** the Book class into the file where we're going to use it. +## 10) The `getQuantity` function -Add this line to the top of the `catalogue_service.js` file: +This function should receive a title as an argument (e.g. "The Origin of Species") and return the quantity of this item which is in stock. For example: ```javascript -const Book = require("./Book"); +getQuantity("A Place of Greater Safety"); // returns 11 ``` -Then, update each of the objects in the `catalogue` array to be new Book instances: +Begin by writing a test, as always, before implementing the function. + +## 11) The `getBooksByAuthor` function + +This function should receive an author as an argument (e.g. "Robert Bolaño") and return an array of books. For example: ```javascript -const catalogue = [ - new Book("The Catcher in the Rye", "J.D. Salinger", 10), - new Book("Dracula", "Bram Stoker", 0), - new Book("Between the Assassinations", "Aravind Adiga", 9), - ... +getBooksByAuthor("Robert Bolaño"); + +// Returns: +[ + { title: "2666", author: "Robert Bolaño", quantity: 12 }, + { title: "By Night In Chile", author: "Robert Bolaño", quantity: 8 } ]; ``` -Update **all** of your book objects so they look like the above. +Begin by writing a test, as always, before implementing the function. -Your tests should all still pass at this point. +Remember that when testing an array return value you should use `toEqual` and not `toBe` (see yesterday's work for a reminder) + +## 12) The `checkQuantity` function + +This function should receive a title and a quantity as an argument (e.g. "By Night In Chile" and 4) and return `true` if there are at least as many books in stock as the given quantity, and false otherwise. For example: + +```javascript +checkQuantity("By Night In Chile", 4); // true +checkQuantity("By Night In Chile", 100); // false +``` + +Begin by writing a test, as always, before implementing the function. ## Written Questions 1. If a book is an object, what is its encapsulated data? -2. Why do we create a new Book for every single test in `Book.test.js`? - -3. What data, of a book's encapsulated data, is changeable? +2. What data, of a book's encapsulated data, might be changeable? -4. Why is representing a book as an object a better idea than representing it as a string? +3. Why is representing a book as an object a better idea than representing it as a string? diff --git a/test/Book.test.js b/test/Book.test.js deleted file mode 100644 index 148c811..0000000 --- a/test/Book.test.js +++ /dev/null @@ -1,73 +0,0 @@ -const Book = require("../app/Book"); - -describe("Instantiating a book", () => { - test("it creates a book object", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.title).toBe("Oryx and Crake"); - expect(book.author).toBe("Margaret Atwood"); - expect(book.quantity).toBe(10); - }); -}); - -xdescribe("addStock()", () => { - test("allows adding a given quantity of stock", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.quantity).toBe(10); - - // We add 5 more books - book.addStock(5); - - expect(book.quantity).toBe(15); - }); - - test("does not allow negative numbers", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.quantity).toBe(10); - - // Try adding a negative number of stock - book.addStock(-5); - - // Book quantity has not changed - expect(book.quantity).toBe(10); - }); -}); - -xdescribe("removeStock()", () => { - test("allows removing a given quantity of stock", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.quantity).toBe(10); - - // We remove 5 books - book.removeStock(3); - - expect(book.quantity).toBe(7); - }); - - test("does not allow negative numbers", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.quantity).toBe(10); - - // Try removing a negative number of stock - book.removeStock(-5); - - // Book quantity has not changed - expect(book.quantity).toBe(10); - }); - - test("cannot reduce a book to below 0 quantity", () => { - const book = new Book("Oryx and Crake", "Margaret Atwood", 10); - - expect(book.quantity).toBe(10); - - // Try removing 15 books - book.removeStock(15); - - // Book quantity is 0 - expect(book.quantity).toBe(0); - }); -}); diff --git a/test/catalogue_service.test.js b/test/catalogue_service.test.js index de5d4a5..d1dcdab 100644 --- a/test/catalogue_service.test.js +++ b/test/catalogue_service.test.js @@ -1,21 +1,11 @@ const catalogueService = require("../app/catalogue_service"); describe("catalogueService", () => { - describe("catalogueService.checkBook", () => { - test("returns true when a book is found by title", () => { - expect(catalogueService.checkBook("Great Expectations")).toBe(true); - }); - - test("returns false when a book cannot be found by title", () => { - expect(catalogueService.checkBook("Gone With The Wind")).toBe(false); - }); - - test("returns true when a partial match is found", () => { - expect(catalogueService.checkBook("Expectations")).toBe(true); - }); - - test("returns false when not even a partial match is found", () => { - expect(catalogueService.checkBook("The Wind")).toBe(false); + describe("catalogueService.countBooksByAuthor", () => { + test("returns the total number of books written by the given author", () => { + expect(catalogueService.countBooksByAuthor("Hilary Mantel")).toBe(5); + expect(catalogueService.countBooksByAuthor("Celeste Ng")).toBe(2); + expect(catalogueService.countBooksByAuthor("Charles Dickens")).toBe(3); }); }); });