Skip to content

Commit 9735b8b

Browse files
committed
mock http api
1 parent b64843f commit 9735b8b

File tree

10 files changed

+172
-10
lines changed

10 files changed

+172
-10
lines changed

buildScripts/generateMockData.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* This script generates mock data for local development.
2+
This way you don't have to point to an actual API,
3+
but you can enjoy realistic, but randomized data,
4+
and rapid page loads due to local, static data.
5+
*/
6+
7+
/* eslint-disable no-console */
8+
9+
import jsf from 'json-schema-faker';
10+
import {schema} from './mockDataSchema';
11+
import fs from 'fs';
12+
import chalk from 'chalk';
13+
14+
const json = JSON.stringify(jsf(schema));
15+
16+
fs.writeFile("./src/api/db.json", json, function (err) {
17+
if (err) {
18+
return console.log(chalk.red(err));
19+
} else {
20+
console.log(chalk.green("Mock data generated."));
21+
}
22+
});

buildScripts/mockDataSchema.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export const schema = {
2+
"type": "object",
3+
"properties": {
4+
"users": {
5+
"type": "array",
6+
"minItems": 3,
7+
"maxItems": 5,
8+
"items": {
9+
"type": "object",
10+
"properties": {
11+
"id": {
12+
"type": "number",
13+
"unique": true,
14+
"minimum": 1
15+
},
16+
"firstName": {
17+
"type": "string",
18+
"faker": "name.firstName"
19+
},
20+
"lastName": {
21+
"type": "string",
22+
"faker": "name.lastName",
23+
},
24+
"email": {
25+
"type": "string",
26+
"faker": "internet.email",
27+
}
28+
},
29+
required: ['id', 'firstName', 'lastName', 'email']
30+
}
31+
}
32+
},
33+
required: ['users']
34+
};

buildScripts/srcServer.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ app.get('/', function (req, res) {
1818
res.sendFile(path.join(__dirname, '../src/index.html'));
1919
});
2020

21+
app.get('/users', function (req,res) {
22+
// Hard coding for simplicity. Pretend this hits a real database
23+
res.json([
24+
{"id": 1, "firstName":"Bob","lastName":"Smith","email":"bob@gmail.com"},
25+
{"id": 2, "firstName":"Tammy","lastName":"Norton","email":"tnorton@yahoo.com"},
26+
{"id": 3, "firstName":"Tina","lastName":"Lee","email":"lee.tina@gmail.com"}
27+
])
28+
});
29+
2130
app.listen(port, function (err) {
2231
if (err) {
2332
console.log(err);

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@
44
"description": "JavaScript development environment",
55
"scripts": {
66
"prestart": "babel-node buildScripts/startMessage.js",
7-
"start": "npm-run-all --parallel security-check open:src lint:watch test:watch",
7+
"start": "npm-run-all --parallel security-check open:src lint:watch test:watch start-mockapi",
88
"open:src": "babel-node buildScripts/srcServer.js",
99
"lint": "esw webpack.config.*, src, buildScripts --color",
1010
"lint:watch": "npm run lint -- --watch",
1111
"security-check": "nsp check",
1212
"localtunnel": "lt --port 3000",
1313
"share": "npm-run-all --parallel open:src localtunnel",
1414
"test": "mocha --reporter progress buildScripts/testSetup.js \"src/**/*.test.js\"",
15-
"test:watch": "npm run test -- --watch"
15+
"test:watch": "npm run test -- --watch",
16+
"generate-mock-data": "babel-node buildScripts/generateMockData",
17+
"prestart-mockapi": "npm run generate-mock-data",
18+
"start-mockapi": "json-server --watch src/api/db.json --port 3001"
1619
},
1720
"author": "kildem",
1821
"license": "MIT",
1922
"dependencies": {
20-
"whatwg-fetch": "1.0.0"
23+
"whatwg-fetch": "^2.0.3"
2124
},
2225
"devDependencies": {
2326
"babel-cli": "^6.24.0",

src/api/baseUrl.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default function getBaseUrl() {
2+
const inDevelopment = window.location.hostname === 'localhost';
3+
return inDevelopment ? 'http://localhost:3001/' : '/';
4+
//return getQueryStringParameterByName('useMockApi') ? 'http://localhost:3001/' : 'https://mysterious-dawn-16770.herokuapp.com/';
5+
}
6+
7+
function getQueryStringParameterByName(name, url) {
8+
if (!url) url = window.location.href;
9+
name = name.replace(/[\[\]]/g, "\\$&");
10+
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
11+
results = regex.exec(url);
12+
if (!results) return null;
13+
if (!results[2]) return '';
14+
return decodeURIComponent(results[2].replace(/\+/g, " "));
15+
}

src/api/db.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"users": [
3+
{
4+
"id": 55379073,
5+
"firstName": "Einar",
6+
"lastName": "Sawayn",
7+
"email": "Jesse_Spinka@gmail.com"
8+
}
9+
]
10+
}

src/api/userApi.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import 'whatwg-fetch';
2+
import getBaseUrl from './baseUrl';
3+
4+
const baseUrl = getBaseUrl();
5+
6+
export function getUsers() {
7+
return get('users');
8+
}
9+
10+
export function deleteUser(id) {
11+
return del(`users/${id}`);
12+
}
13+
14+
function get(url) {
15+
return fetch(baseUrl + url).then(onSuccess, onError);
16+
}
17+
18+
// Can't call func delete since reserved word.
19+
function del(url) {
20+
const request = new Request(baseUrl + url, {
21+
method: 'DELETE'
22+
});
23+
return fetch(request).then(onSuccess, onError);
24+
}
25+
26+
function onSuccess(resp) {
27+
return resp.json();
28+
}
29+
30+
function onError(error) {
31+
console.log(error); // eslint-disable-line no-console
32+
}

src/index.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@
55
<title>Title</title>
66
</head>
77
<body>
8-
<h1>Hello!</h1>
8+
<h1>Users</h1>
9+
<table>
10+
<thead>
11+
<th>&nbsp;</th>
12+
<th>Id</th>
13+
<th>First Name</th>
14+
<th>Last Name</th>
15+
<th>Email</th>
16+
</thead>
17+
<tbody id="users"></tbody>
18+
</table>
919
<script src="bundle.js"></script>
1020
</body>
1121
</html>

src/index.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
1-
import numeral from 'numeral';
21
import './index.css';
2+
import {getUsers, deleteUser} from './api/userApi';
33

4-
const courseValue = numeral(1000).format('$0,0.00');
5-
debugger;
6-
console.log(`I would pay ${courseValue} for this awesom course!`);
4+
// Populate table of users via API call.
5+
getUsers().then(result => {
6+
let usersBody = "";
7+
8+
result.forEach(user => {
9+
usersBody+= `<tr>
10+
<td><a href="#" data-id="${user.id}" class="deleteUser">Delete</a></td>
11+
<td>${user.id}</td>
12+
<td>${user.firstName}</td>
13+
<td>${user.lastName}</td>
14+
<td>${user.email}</td>
15+
</tr>`
16+
});
17+
global.document.getElementById('users').innerHTML = usersBody;
18+
19+
const deleteLinks = global.document.getElementsByClassName('deleteUser');
20+
21+
// Must use array.from to create a real array from a DOM collection
22+
// getElementsByClassname only returns an "array like" object
23+
Array.from(deleteLinks, link => {
24+
link.onclick = function(event) {
25+
const element = event.target;
26+
event.preventDefault();
27+
deleteUser(element.attributes["data-id"].value);
28+
const row = element.parentNode.parentNode;
29+
row.parentNode.removeChild(row);
30+
};
31+
});
32+
33+
});

src/index.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ describe('test', () => {
99
});
1010

1111
describe('index.html', () => {
12-
it('shouldj say hello', (done) => {
12+
it('should have h1 says Users', (done) => {
1313
const index = fs.readFileSync('./src/index.html', 'utf-8');
1414
jsdom.env(index, function (err, window) {
1515
const h1 = window.document.getElementsByTagName('h1')[0];
16-
expect(h1.innerHTML).to.equal("Hello!");
16+
expect(h1.innerHTML).to.equal("Users");
1717
done();
1818
window.close();
1919
})

0 commit comments

Comments
 (0)