From 94de6721b98f9e315b5918c5286f5194076a21ab Mon Sep 17 00:00:00 2001 From: mcarman Date: Tue, 7 Dec 2021 13:33:02 +0000 Subject: [PATCH] testing tools --- tools/Rest.http | 3 + tools/apiServer.js | 112 ++++++++++++++++++++++ tools/createMockDb.js | 16 ++++ tools/db.json | 1 + tools/mockData.js | 214 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 346 insertions(+) create mode 100644 tools/Rest.http create mode 100644 tools/apiServer.js create mode 100644 tools/createMockDb.js create mode 100644 tools/db.json create mode 100644 tools/mockData.js diff --git a/tools/Rest.http b/tools/Rest.http new file mode 100644 index 0000000..2179824 --- /dev/null +++ b/tools/Rest.http @@ -0,0 +1,3 @@ +@API_URL = "http://vapor.prelub.com/api/v1.0" + +GET {{API_URL}}/users diff --git a/tools/apiServer.js b/tools/apiServer.js new file mode 100644 index 0000000..2eabf07 --- /dev/null +++ b/tools/apiServer.js @@ -0,0 +1,112 @@ +/* +This uses json-server, but with the module approach: https://github.com/typicode/json-server#module +Downside: You can't pass the json-server command line options. +Instead, can override some defaults by passing a config object to jsonServer.defaults(); +You have to check the source code to set some items. +Examples: +Validation/Customization: https://github.com/typicode/json-server/issues/266 +Delay: https://github.com/typicode/json-server/issues/534 +ID: https://github.com/typicode/json-server/issues/613#issuecomment-325393041 +Relevant source code: https://github.com/typicode/json-server/blob/master/src/cli/run.js +*/ + +/* eslint-disable no-console */ +const jsonServer = require("json-server"); +const server = jsonServer.create(); +const path = require("path"); +const router = jsonServer.router(path.join(__dirname, "db.json")); + +// Can pass a limited number of options to this to override (some) defaults. See https://github.com/typicode/json-server#api +const middlewares = jsonServer.defaults({ + // Display json-server's built in homepage when json-server starts. + static: "node_modules/json-server/dist", +}); + +// Set default middlewares (logger, static, cors and no-cache) +server.use(middlewares); + +// To handle POST, PUT and PATCH you need to use a body-parser. Using JSON Server's bodyParser +server.use(jsonServer.bodyParser); + +// Simulate delay on all requests +server.use(function (req, res, next) { + setTimeout(next, 0); +}); + +// Declaring custom routes below. Add custom routes before JSON Server router + +// Add createdAt to all POSTS +server.use((req, res, next) => { + if (req.method === "POST") { + req.body.createdAt = Date.now(); + } + // Continue to JSON Server router + next(); +}); + +server.post("/courses/", function (req, res, next) { + const error = validateCourse(req.body); + if (error) { + res.status(400).send(error); + } else { + req.body.slug = createSlug(req.body.title); // Generate a slug for new courses. + next(); + } +}); + +server.post("/users/", function (req, res, next) { + const error = validateUser(req.body); + if (error) { + res.status(400).send(error); + } else { + req.body.slug = createSlug(req.body.title); // Generate a slug for new users. + next(); + } +}); + +/*********************************************** + * bpapiServerSnipppet at the above this line * + * There will be 2 tab stops that need changed * + *********************************************** + */ +// Use default router +server.use(router); + +// Start server +const port = 3001; +server.listen(port, () => { + console.log(`JSON Server is running on port ${port}`); +}); + +// Centralized logic + +// Returns a URL friendly slug +function createSlug(value) { + return value + .replace(/[^a-z0-9_]+/gi, "-") + .replace(/^-|-$/g, "") + .toLowerCase(); +} + +function validateCourse(course) { + if (!course.title) return "Title is required."; + if (!course.authorId) return "Author is required."; + if (!course.category) return "Category is required."; + return ""; +} + +function validateUser(user) { + if (!user.firstname) return "First name is required."; + if (!user.lastname) return "Last name is required."; + if (!user.username) return "Username is required."; + if (!user.password) return "Password is required."; + if (!user.emil) return "Email is required."; + if (!user.isactive) return "Is active is required."; + return ""; +} + +/*********************************************** + * bpapiServerValidation at the above this line* + * There will be 2 tab stops that need changed * + *********************************************** + */ diff --git a/tools/createMockDb.js b/tools/createMockDb.js new file mode 100644 index 0000000..6d055b1 --- /dev/null +++ b/tools/createMockDb.js @@ -0,0 +1,16 @@ +/* eslint-disable no-console */ +const fs = require("fs"); +const path = require("path"); +const mockData = require("./mockData"); + +const { courses, authors, users /* , Add aditional models here */ } = mockData; +const data = JSON.stringify({ + courses, + authors, + users /* , Add additional models here */, +}); +const filepath = path.join(__dirname, "db.json"); + +fs.writeFile(filepath, data, function (err) { + err ? console.log(err) : console.log("Mock DB created."); +}); diff --git a/tools/db.json b/tools/db.json new file mode 100644 index 0000000..1b7c417 --- /dev/null +++ b/tools/db.json @@ -0,0 +1 @@ +{"courses":[{"id":1,"title":"Securing React Apps with Auth0","slug":"react-auth0-authentication-security","authorId":1,"category":"JavaScript"},{"id":2,"title":"React: The Big Picture","slug":"react-big-picture","authorId":1,"category":"JavaScript"},{"id":3,"title":"Creating Reusable React Components","slug":"react-creating-reusable-components","authorId":1,"category":"JavaScript"},{"id":4,"title":"Building a JavaScript Development Environment","slug":"javascript-development-environment","authorId":1,"category":"JavaScript"},{"id":5,"title":"Building Applications with React and Redux","slug":"react-redux-react-router-es6","authorId":1,"category":"JavaScript"},{"id":6,"title":"Building Applications in React and Flux","slug":"react-flux-building-applications","authorId":1,"category":"JavaScript"},{"id":7,"title":"Clean Code: Writing Code for Humans","slug":"writing-clean-code-humans","authorId":1,"category":"Software Practices"},{"id":8,"title":"Architecting Applications for the Real World","slug":"architecting-applications-dotnet","authorId":1,"category":"Software Architecture"},{"id":9,"title":"Becoming an Outlier: Reprogramming the Developer Mind","slug":"career-reboot-for-developer-mind","authorId":1,"category":"Career"},{"id":10,"title":"Web Component Fundamentals","slug":"web-components-shadow-dom","authorId":1,"category":"HTML5"}],"authors":[{"id":1,"name":"Cory House"},{"id":2,"name":"Scott Allen"},{"id":3,"name":"Dan Wahlin"}],"users":[{"firstname":"George","email":"ghorensky@rpmindustries.com","lastname":"Horensky","username":"ghorensky","password":"ghorensky","isactive":true,"id":2},{"firstname":"George","email":"gwilhelm@rpmindustries.com","lastname":"Wilhelm","username":"gwilhelm","password":"gwilhelm","isactive":true,"id":3},{"firstname":"John","email":"jmccosby@rpmindustries.com","lastname":"McCosby","username":"jmccosby","password":"jmccosby","isactive":true,"id":4},{"firstname":"John","email":"jzwicker@rpmindustries.com","lastname":"Zwicker","username":"jzwicker","password":"jzwicker","isactive":true,"id":5},{"firstname":"Bill","email":"bryckman@rpmindustries.com","lastname":"Ryckman","username":"bryckman","password":"bryckman","isactive":true,"id":6},{"firstname":"Justin","email":"jkieffer@rpmindustries.com","lastname":"Kieffer","username":"jkieffer","password":"jkieffer","isactive":true,"id":7},{"firstname":"Patrick","email":"pbuono@rpmindustries.com","lastname":"Buono","username":"pbuono","password":"pbuono","isactive":false,"id":8},{"firstname":"Josh","email":"jmorgan@rpmindustries.com","lastname":"Morgan","username":"jmorgan","password":"jmorgan","isactive":true,"id":9},{"firstname":"Anthony","email":"aguzzi@rpmindustries.com","lastname":"Guzzi","username":"aguzzi","password":"aguzzi","isactive":false,"id":10},{"firstname":"Art","email":"aschrage@rpmindustries.com","lastname":"Schrage","username":"aschrage","password":"ascharge","isactive":false,"id":11}]} \ No newline at end of file diff --git a/tools/mockData.js b/tools/mockData.js new file mode 100644 index 0000000..5688e4e --- /dev/null +++ b/tools/mockData.js @@ -0,0 +1,214 @@ +const courses = [ + { + id: 1, + title: "Securing React Apps with Auth0", + slug: "react-auth0-authentication-security", + authorId: 1, + category: "JavaScript", + }, + { + id: 2, + title: "React: The Big Picture", + slug: "react-big-picture", + authorId: 1, + category: "JavaScript", + }, + { + id: 3, + title: "Creating Reusable React Components", + slug: "react-creating-reusable-components", + authorId: 1, + category: "JavaScript", + }, + { + id: 4, + title: "Building a JavaScript Development Environment", + slug: "javascript-development-environment", + authorId: 1, + category: "JavaScript", + }, + { + id: 5, + title: "Building Applications with React and Redux", + slug: "react-redux-react-router-es6", + authorId: 1, + category: "JavaScript", + }, + { + id: 6, + title: "Building Applications in React and Flux", + slug: "react-flux-building-applications", + authorId: 1, + category: "JavaScript", + }, + { + id: 7, + title: "Clean Code: Writing Code for Humans", + slug: "writing-clean-code-humans", + authorId: 1, + category: "Software Practices", + }, + { + id: 8, + title: "Architecting Applications for the Real World", + slug: "architecting-applications-dotnet", + authorId: 1, + category: "Software Architecture", + }, + { + id: 9, + title: "Becoming an Outlier: Reprogramming the Developer Mind", + slug: "career-reboot-for-developer-mind", + authorId: 1, + category: "Career", + }, + { + id: 10, + title: "Web Component Fundamentals", + slug: "web-components-shadow-dom", + authorId: 1, + category: "HTML5", + }, +]; + +const authors = [ + { id: 1, name: "Cory House" }, + { id: 2, name: "Scott Allen" }, + { id: 3, name: "Dan Wahlin" }, +]; + +const users = [ + { + firstname: "George", + email: "ghorensky@rpmindustries.com", + lastname: "Horensky", + username: "ghorensky", + password: "ghorensky", + isactive: true, + id: 2, + }, + { + firstname: "George", + email: "gwilhelm@rpmindustries.com", + lastname: "Wilhelm", + username: "gwilhelm", + password: "gwilhelm", + isactive: true, + id: 3, + }, + { + firstname: "John", + email: "jmccosby@rpmindustries.com", + lastname: "McCosby", + username: "jmccosby", + password: "jmccosby", + isactive: true, + id: 4, + }, + { + firstname: "John", + email: "jzwicker@rpmindustries.com", + lastname: "Zwicker", + username: "jzwicker", + password: "jzwicker", + isactive: true, + id: 5, + }, + { + firstname: "Bill", + email: "bryckman@rpmindustries.com", + lastname: "Ryckman", + username: "bryckman", + password: "bryckman", + isactive: true, + id: 6, + }, + { + firstname: "Justin", + email: "jkieffer@rpmindustries.com", + lastname: "Kieffer", + username: "jkieffer", + password: "jkieffer", + isactive: true, + id: 7, + }, + { + firstname: "Patrick", + email: "pbuono@rpmindustries.com", + lastname: "Buono", + username: "pbuono", + password: "pbuono", + isactive: false, + id: 8, + }, + { + firstname: "Josh", + email: "jmorgan@rpmindustries.com", + lastname: "Morgan", + username: "jmorgan", + password: "jmorgan", + isactive: true, + id: 9, + }, + { + firstname: "Anthony", + email: "aguzzi@rpmindustries.com", + lastname: "Guzzi", + username: "aguzzi", + password: "aguzzi", + isactive: false, + id: 10, + }, + { + firstname: "Art", + email: "aschrage@rpmindustries.com", + lastname: "Schrage", + username: "aschrage", + password: "ascharge", + isactive: false, + id: 11, + }, +]; + +//TODO +/****************************************** + * Add new databodels above these comments* + * const model = [ object ] * + * bpmockDataNewObject * + * bpmockDataNewObjectLine * + * **************************************** + */ + +const newUser = { + firstname: "", + email: "", + lastname: "", + username: "", + password: "", + isactive: true, + id: null, +}; + +const newCourse = { + id: null, + title: "", + authorId: null, + category: "", +}; + +//TODO +/******************************************************** + * Add newmodel constants above this block of comments * + * ****************************************************** + */ + +// Using CommonJS style export so we can consume via Node (without using Babel-node) +module.exports = { + newCourse, + newUser, + /** Add newObject construct reference here */ + courses, + authors, + users, + /** Add objects(list) reference here */ +};