diff --git a/TODO b/TODO index 5cbc1f8..8c3a804 100644 --- a/TODO +++ b/TODO @@ -6,16 +6,13 @@ * Add tests verifying each implementation of an app returns the expected markup * For Vue, implement getFrameworkFragment(frameworkName) that returns either toHTMLString.Fragment or div depending on if frameworkName supports Fragments -* Consider changing flight booker to do input validation to demonstrate how that flow works... - * Would also make it easier to test since using date input in puppeteer is hard - * Perhaps require dates to match yyyy-mm-dd format (ISO format?) using regex /([0-9]{4})-([0-9]{2})-([0-9]{2})/ + simplified validation logic (month <= 12, day <= 31). Perhaps incorrect values are marked as invalid for date values that don't match parsed date after passing into Date constructor -* Consider having one page per app with a framework selector? with standalone page option? -* Add Compare page - * plus button to add multiple frameworks of one app to view source and Compare * Consider showing source files inline under app * Perhaps add toggle for source and js output? Particularly useful for compiler frameworks (Vue, Svelte) * Add link to framework repl if exists +* Consider having one page per app with a framework selector? with standalone page option? +* Add Compare page + * plus button to add multiple frameworks of one app to view source and Compare * Add brotli/gzip radio option to summary page (power radios using /scripts/bundles/summary.js) * Add rollup-plugin-visualizer html to output diff --git a/dist/frameworks/preact-hooks/7GUIs-flight-booker.html b/dist/frameworks/preact-hooks/7GUIs-flight-booker.html index c1ef158..f551241 100644 --- a/dist/frameworks/preact-hooks/7GUIs-flight-booker.html +++ b/dist/frameworks/preact-hooks/7GUIs-flight-booker.html @@ -199,8 +199,8 @@

7GUIs Flight Booker - Preact Hooks

@@ -47,32 +47,38 @@ -
+
+ {#if departingError} +

{departingError}

+ {/if}
-
+
+ {#if returningError} +

{returningError}

+ {/if}
diff --git a/lib/date.js b/lib/date.js index 880520b..dd09a7b 100644 --- a/lib/date.js +++ b/lib/date.js @@ -9,7 +9,7 @@ export function today() { ].join("-"); } -const validDate = /^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$/; +const validDate = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/; /** * @param {string} date diff --git a/tests/apps/7GUIs-flight-booker.js b/tests/apps/7GUIs-flight-booker.js index c5a1125..a45b7f4 100644 --- a/tests/apps/7GUIs-flight-booker.js +++ b/tests/apps/7GUIs-flight-booker.js @@ -1,4 +1,4 @@ -import { getAppHtml, toHtmlString, appSel } from "../util"; +import { getAppHtml, toHtmlString, appSel, backspaceInput } from "../util"; /** * @param {string} frameworkName @@ -10,6 +10,12 @@ export default function run(frameworkName, appSetup) { const departingSel = appSel("#departing-date"); const returningSel = appSel("#returning-date"); const bookSel = appSel("button"); + const departingErrorSel = appSel( + ".form-group.has-error #departing-date+.form-input-hint" + ); + const returningErrorSel = appSel( + ".form-group.has-error #returning-date+.form-input-hint" + ); const oneWayType = "one-way"; const returnType = "return"; @@ -34,7 +40,7 @@ export default function run(frameworkName, appSetup) { - +
@@ -94,21 +100,48 @@ export default function run(frameworkName, appSetup) { expect(isReturnDisabled).toEqual(true); }); - it.skip("disables the book button if the return flight input is strictly before the departing flight", async () => { - // TODO: Interacting with date controls in Chrome is bad. Change these to text fields - + it("disables the book button if the return flight input is strictly before the departing flight", async () => { await page.select(tripTypeSel, returnType); let isReturnDisabled = await page.$eval(returningSel, el => el.disabled); expect(isReturnDisabled).toEqual(false); - await page.type(returningSel, "07/10/2018"); + await backspaceInput(returningSel); + await page.type(returningSel, "2018/07/10"); const returnDate = await page.$eval(returningSel, el => el.value); let isBookDisabled = await page.$eval(bookSel, el => el.disabled); - expect(returnDate).toEqual("07/10/2018"); + expect(returnDate).toEqual("2018/07/10"); expect(isBookDisabled).toEqual(true); }); + it("displays an error message and disables book button if the departing date is invalid", async () => { + let errorContainer = await page.$(departingErrorSel); + expect(errorContainer).toBe(null); + + await page.type(departingSel, "a"); + let errorMsg = await page.$eval(departingErrorSel, e => e.textContent); + let isBookDisabled = await page.$eval(bookSel, el => el.disabled); + + expect(isBookDisabled).toBe(true); + expect(errorMsg).toMatch(/YYYY-MM-DD/); + }); + + it("displays an error message and disables book button if the returning date is invalid", async () => { + await page.select(tripTypeSel, returnType); + let isReturnDisabled = await page.$eval(returningSel, el => el.disabled); + expect(isReturnDisabled).toEqual(false); + + let errorContainer = await page.$(departingErrorSel); + expect(errorContainer).toBe(null); + + await page.type(returningSel, "a"); + let errorMsg = await page.$eval(returningErrorSel, e => e.textContent); + let isBookDisabled = await page.$eval(bookSel, el => el.disabled); + + expect(isBookDisabled).toBe(true); + expect(errorMsg).toMatch(/YYYY-MM-DD/); + }); + it("booking a one-way flight displays the correct message", async () => { const dialogPromise = new Promise((resolve, reject) => { /** diff --git a/tests/lib/date.test.js b/tests/lib/date.test.js index bb2a14c..03f4ba7 100644 --- a/tests/lib/date.test.js +++ b/tests/lib/date.test.js @@ -10,9 +10,6 @@ describe("date lib", () => { describe("validateDate", () => { it("does not throw errors on valid date formats", () => { expect(() => validateDate("2018-09-12")).not.toThrowError(); - expect(() => validateDate("2019-1-12")).not.toThrowError(); - expect(() => validateDate("2018-09-2")).not.toThrowError(); - expect(() => validateDate("2019-1-2")).not.toThrowError(); expect(() => validateDate("2019-02-28")).not.toThrowError(); expect(() => validateDate("2024-02-29")).not.toThrowError(); }); @@ -31,6 +28,9 @@ describe("date lib", () => { expect(() => validateDate("123-09-01")).toThrowError(/YYYY-MM-DD/); expect(() => validateDate("12-09-01")).toThrowError(/YYYY-MM-DD/); expect(() => validateDate("1-09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("2019-1-12")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("2018-09-2")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("2019-1-2")).toThrowError(/YYYY-MM-DD/); expect(() => validateDate("12345-09-01")).toThrowError(/YYYY-MM-DD/); expect(() => validateDate("a1234-09-01")).toThrowError(/YYYY-MM-DD/); expect(() => validateDate("1a234-09-01")).toThrowError(/YYYY-MM-DD/);