diff --git a/package.json b/package.json index 361cdd5d..ef67f7d2 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "test:module4": "NODE_ENV=test mocha 'test/unit/mocha/part4/*.spec.js' || true", "test:module5": "NODE_ENV=test mocha 'test/unit/mocha/part5/*.spec.js' || true", "test:module6": "NODE_ENV=test mocha 'test/unit/mocha/part6/*.spec.js' || true", + "test:module7": "NODE_ENV=test mocha 'test/unit/mocha/part7/*.spec.js' || true", "test": "NODE_ENV=test mocha 'test/unit/mocha/**/*.spec.js' || true", "debug": "NODE_ENV=test mocha --debug-brk", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", diff --git a/test/unit/mocha/part7/add-finished-reading-prop-to-books.spec.js b/test/unit/mocha/part7/add-finished-reading-prop-to-books.spec.js new file mode 100644 index 00000000..033d6a4b --- /dev/null +++ b/test/unit/mocha/part7/add-finished-reading-prop-to-books.spec.js @@ -0,0 +1,63 @@ +const assert = require("chai").assert; +const parse5 = require("parse5"); +const esquery = require("esquery"); +const esprima = require("esprima"); +const helpers = require("../helpers"); + +describe("BookList.vue", () => { + it("should contain a data function that returns a bookData object @book-list-contain-finishedReading-property", () => { + const file = helpers.readFile("src/components/BookList.vue"); + const nodes = helpers.parseFile(file); + const script = helpers.getHtmlTag("script", nodes); + + if (script.length == 0) { + assert( + false, + "We either didn't find a script tag, or any code in a script tag in the BookForm component." + ); + } + + const ast = esprima.parse(script[0].childNodes[0].value, { + sourceType: "module" + }); + + const data = esquery(ast, "Property[key.name=data]"); + assert( + data.length > 0, + "The BookList's `data()` method's return is not present." + ); + + const books = esquery(ast, "Property[key.name=books]"); + assert(books.length > 0, "The BookList's `books` array is not present"); + + let finishedReading = esquery( + books[0], + "Property[key.name=finishedReading]" + ); + + assert( + finishedReading.length === 3, + "The `book` array should have a `finishedReading` property in each book object." + ); + + let finishedReadingTrue = esquery( + books[0], + "Property[key.name=finishedReading]>[value=true]" + ); + + assert( + finishedReadingTrue.length == 2, + "The `book` array should have two `finishedReading` properties with `true` as their values." + ); + + let finishedReadingFalse = esquery( + books[0], + "Property[key.name=finishedReading]>[value=false]" + ); + + assert( + finishedReadingFalse.length == 1, + "The `book` array should have one `finishedReading` property with `false` as its value." + ); + }); +}); diff --git a/test/unit/mocha/part7/appendBook()-pushes-new-array-data.spec.js b/test/unit/mocha/part7/appendBook()-pushes-new-array-data.spec.js new file mode 100644 index 00000000..2459a109 --- /dev/null +++ b/test/unit/mocha/part7/appendBook()-pushes-new-array-data.spec.js @@ -0,0 +1,89 @@ +const assert = require("chai").assert; +const esquery = require("esquery"); +const esprima = require("esprima"); +const helpers = require("../helpers"); + +describe("BookList.vue", () => { + it("should contain a method that uses bookData to push to array contents @append-book-uses-bookData-to-push", () => { + const file = helpers.readFile("src/components/BookList.vue"); + const nodes = helpers.parseFile(file); + const script = helpers.getHtmlTag("script", nodes); + let methods; + + if (script.length == 0) { + assert( + false, + "We either didn't find a script tag, or any code in a script tag in the BookForm component." + ); + } + + const ast = esprima.parse(script[0].childNodes[0].value, { + sourceType: "module" + }); + + try { + methods = esquery(ast, "Property[key.name=methods]"); + } catch (e) { + assert( + false, + "Something went wrong and we weren't able to check your code." + ); + } + + assert( + methods.length > 0, + "The BookList's `methods` declaration is not present." + ); + + let results = esquery(methods[0], 'Identifier[name="appendBook"]'); + assert( + results.length > 0, + "The BookList's `methods` object is not defining an `appendBook()` method." + ); + + results = esquery( + methods[0], + 'MemberExpression > MemberExpression > Identifier[name="books"]' + ); + assert( + results.length > 0, + "The BookList's `appendBook()` method is not pushing anything to the array `books`." + ); + + results = esquery( + methods[0], + 'CallExpression > ObjectExpression > Property[key.name="title"] > MemberExpression[object.name="bookData"][property.name="bookTitle"]' + ); + assert( + results.length > 0, + "In BookList's `appendBook()` method, the `title` key is not being assigned to the `bookData.bookTitle` value." + ); + + results = esquery( + methods[0], + 'CallExpression > ObjectExpression > Property[key.name="author"] > MemberExpression[object.name="bookData"][property.name="bookAuthor"]' + ); + assert( + results.length > 0, + "In BookList's `appendBook()` method, the `author` key is not being assigned to the `bookData.bookAuthor` value." + ); + + results = esquery( + methods[0], + 'CallExpression > ObjectExpression > Property[key.name="finishedReading"]' + ); + assert( + results.length > 0, + "The BookList's `appendBook()` method should be pushing a `finishedReading` property with the `bookData.finishedReading` value to the `books` data." + ); + + results = esquery( + methods[0], + 'CallExpression > ObjectExpression > Property[key.name="finishedReading"] > MemberExpression[object.name="bookData"][property.name="finishedReading"]' + ); + assert( + results.length > 0, + "In BookList's `appendBook()` method call, the `finishedReading` key is not being assigned to the `bookData.finishedReading` value." + ); + }); +}); diff --git a/test/unit/mocha/part7/refactor-appendBook-method.spec.js b/test/unit/mocha/part7/refactor-appendBook-method.spec.js new file mode 100644 index 00000000..2d82d9f7 --- /dev/null +++ b/test/unit/mocha/part7/refactor-appendBook-method.spec.js @@ -0,0 +1,52 @@ +const assert = require("chai").assert; +const esquery = require("esquery"); +const esprima = require("esprima"); +const helpers = require("../helpers"); + +describe("BookList.vue", () => { + it("should pass bookData as an argument to appendBook() @refactor-appendBook-method", () => { + const file = helpers.readFile("src/components/BookList.vue"); + const nodes = helpers.parseFile(file); + const script = helpers.getHtmlTag("script", nodes); + let methods; + + if (script.length == 0) { + assert( + false, + "We either didn't find a script tag, or any code in a script tag in the BookForm component." + ); + } + + const ast = esprima.parse(script[0].childNodes[0].value, { + sourceType: "module" + }); + + try { + methods = esquery(ast, "Property[key.name=methods]"); + } catch (e) { + assert( + false, + "Something went wrong and we weren't able to check your code." + ); + } + assert( + methods.length > 0, + "The BookForm's `methods` declaration is not present" + ); + + let results = esquery(methods[0], 'Identifier[name="appendBook"]'); + assert( + results.length > 0, + "The BookList's `methods` object is not defining an `appendBook()` method" + ); + + results = esquery( + methods[0], + 'Property[key.name="appendBook"] > FunctionExpression > Identifier[name="bookData"]' + ); + assert( + results.length > 0, + "The `appendBook()` method is not being called with `bookData` as its only argument." + ); + }); +}); diff --git a/test/unit/mocha/part7/should-show-read-in-book-item.spec.js b/test/unit/mocha/part7/should-show-read-in-book-item.spec.js new file mode 100644 index 00000000..7f6e1570 --- /dev/null +++ b/test/unit/mocha/part7/should-show-read-in-book-item.spec.js @@ -0,0 +1,60 @@ +const assert = require("chai").assert; +const parse5 = require("parse5"); +const cheerio = require("cheerio"); +const helpers = require("../helpers"); + +describe("BookItem.vue", () => { + it("should show read or not read according to book.finishedReading @show-read-or-not-read", () => { + const file = helpers.readFile("src/components/BookItem.vue"); + const nodes = helpers.parseFile(file); + const tagName = helpers.getHtmlTag("template", nodes); + const content = parse5.serialize(tagName[0].content); + const $ = cheerio.load(content); + + const firstSpan = $("span"); + const secondSpan = $("span:nth-child(2n)"); + + assert( + $(firstSpan).length > 0, + "It doesn't look like we are adding the `span` HTML element to the BookList template." + ); + + assert( + $(secondSpan).length > 0, + "It doesn't look like we are adding two `span` elements to the BookList template." + ); + + assert.hasAnyKeys( + firstSpan.attr(), + ["v-if"], + "The BookItem template does not a span with a `v-if` directive." + ); + + assert.propertyVal( + firstSpan.attr(), + "v-if", + "book.finishedReading", + "The BookItem template does not a span with a `v-if` directive containing `book.finishedReading`." + ); + + assert( + $(firstSpan) + .text() + .match(/\s*Read/gi), + "The BookItem span with the `v-if` directive does not have a text of `Read`." + ); + + assert.hasAnyKeys( + secondSpan.attr(), + ["v-else"], + "The BookItem template does not a span with a `v-else` directive." + ); + + assert( + $(secondSpan) + .text() + .match(/\s*Not\s*Read/gi), + "The BookItem span with the `v-else` directive does not have a text of `Not Read`." + ); + }); +});