From a89fdbd9b4c16888c8415af2194c7c80bf9261e6 Mon Sep 17 00:00:00 2001 From: Andre Wiggins Date: Mon, 15 Jul 2019 16:52:32 -0700 Subject: [PATCH] Add date helper lib ...to support the next commit, which will use this lib in all flight booker implementations --- lib/Readme.md | 3 +++ lib/date.js | 52 ++++++++++++++++++++++++++++++++++++ package.json | 5 +++- tests/.babelrc | 19 -------------- tests/babelTransformer.js | 29 +++++++++++++++++++++ tests/lib/date.test.js | 55 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 143 insertions(+), 20 deletions(-) create mode 100644 lib/Readme.md create mode 100644 lib/date.js delete mode 100644 tests/.babelrc create mode 100644 tests/babelTransformer.js create mode 100644 tests/lib/date.test.js diff --git a/lib/Readme.md b/lib/Readme.md new file mode 100644 index 0000000..b3dd572 --- /dev/null +++ b/lib/Readme.md @@ -0,0 +1,3 @@ +# Lib + +This folder contains code shared across apps implemented by all the frameworks diff --git a/lib/date.js b/lib/date.js new file mode 100644 index 0000000..880520b --- /dev/null +++ b/lib/date.js @@ -0,0 +1,52 @@ +export function today() { + const fullDate = new Date(); + let month = fullDate.getMonth() + 1; + let date = fullDate.getDate(); + return [ + fullDate.getFullYear(), + month < 10 ? "0" + month : month, + date < 10 ? "0" + date : date + ].join("-"); +} + +const validDate = /^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$/; + +/** + * @param {string} date + */ +export function validateDate(date) { + if (date == null) { + throw new Error("Invalid date. Date must be in the format of YYYY-MM-DD"); + } + + const match = date.match(validDate); + if (match == null) { + throw new Error("Invalid date. Date must be in the format of YYYY-MM-DD"); + } + + const year = parseInt(match[1]); + const month = parseInt(match[2]); + const day = parseInt(match[3]); + + if (day < 1 || day > 31) { + throw new Error("Invalid date. Date must be between 1-31."); + } + + if (month < 1 || month > 12) { + throw new Error("Invalid month. Month must be between 1-12."); + } + + const parsedDate = new Date(date); + + if (day !== parsedDate.getUTCDate()) { + throw new Error("Invalid date. Date isn't correct."); + } + + if (month !== parsedDate.getUTCMonth() + 1) { + throw new Error("Invalid date. Month isn't correct."); + } + + if (year !== parsedDate.getUTCFullYear()) { + throw new Error("Invalid date. Year isn't correct."); + } +} diff --git a/package.json b/package.json index fecd5eb..07f73bb 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,9 @@ "rollup-plugin-visualizer": "^2.4.4" }, "jest": { - "preset": "jest-puppeteer" + "preset": "jest-puppeteer", + "transform": { + "^.+\\.[t|j]sx?$": "/tests/babelTransformer.js" + } } } diff --git a/tests/.babelrc b/tests/.babelrc deleted file mode 100644 index 79fb742..0000000 --- a/tests/.babelrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "node": "current" - } - } - ], - [ - "@babel/preset-react", - { - "pragma": "toHtmlString", - "pragmaFrag": "toHtmlString.Fragment" - } - ] - ] -} diff --git a/tests/babelTransformer.js b/tests/babelTransformer.js new file mode 100644 index 0000000..cd8cd84 --- /dev/null +++ b/tests/babelTransformer.js @@ -0,0 +1,29 @@ +const babelJest = require("babel-jest"); + +// By default, babel-jest looks for a babel.config.js to determine the configuration +// to use to run tests. We don't want to add a babel.config.js at the root of this project +// because not all subpackages (e.g. Svelte, Vue) use Babel and we wouldn't want the presence +// of this global babel config to mess with the building of these packages. However, we do +// want all of our test files to be run through Babel so instead of messing around with config +// files which didn't intuitively work (specifically the date.test.js file cuz it imports a file +// outside of the "tests" directory where we could put a babel config), we are manually specifying +// a Babel config here +module.exports = babelJest.createTransformer({ + presets: [ + [ + "@babel/preset-env", + { + targets: { + node: "current" + } + } + ], + [ + "@babel/preset-react", + { + pragma: "toHtmlString", + pragmaFrag: "toHtmlString.Fragment" + } + ] + ] +}); diff --git a/tests/lib/date.test.js b/tests/lib/date.test.js new file mode 100644 index 0000000..bb2a14c --- /dev/null +++ b/tests/lib/date.test.js @@ -0,0 +1,55 @@ +import { validateDate, today } from "../../lib/date"; + +describe("date lib", () => { + describe("today()", () => { + it("returns a valid date", () => { + expect(() => validateDate(today())).not.toThrow(); + }); + }); + + 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(); + }); + + it("throws helpful errors on invalid date formats", () => { + expect(() => validateDate(null)).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("-")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("--")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("---")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234--")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-09-")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("-09-")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("-09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234--01")).toThrowError(/YYYY-MM-DD/); + 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("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/); + expect(() => validateDate("12a34-09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("123a4-09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234a-09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-a09-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-0a9-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-09a-01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-09-a01")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-09-0a1")).toThrowError(/YYYY-MM-DD/); + expect(() => validateDate("1234-09-01a")).toThrowError(/YYYY-MM-DD/); + }); + + it("throws helpful errors on invalid dates", () => { + expect(() => validateDate("2019-12-32")).toThrowError(/Date/); + expect(() => validateDate("2019-4-31")).toThrowError(/Date/); + expect(() => validateDate("2019-02-29")).toThrowError(/Date/); + expect(() => validateDate("2019-13-01")).toThrowError(/Month/); + }); + }) +});