Skip to content

Commit 94097b0

Browse files
committed
solution
1 parent 8c50e3e commit 94097b0

File tree

5 files changed

+157
-24
lines changed

5 files changed

+157
-24
lines changed

.github/workflows/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
"type": "module",
33
"devDependencies": {
44
"jsdom": "^20.0.2",
5+
<<<<<<< Updated upstream
56
"uvu": "^0.5.6",
67
"puppeteer": "^19.7.2"
8+
=======
9+
"uvu": "^0.5.6"
10+
>>>>>>> Stashed changes
711
}
812
}

.github/workflows/test.js

+111
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<<<<<<< Updated upstream
12
import { setTimeout } from "timers/promises";
23
import { test } from "uvu";
34
import * as assert from "uvu/assert";
@@ -102,6 +103,116 @@ test("Solved Issue #4: make table look prettier", async (context) => {
102103
return window.getComputedStyle(table).getPropertyValue("border-color");
103104
});
104105
assert.is(tableBorderColor, "rgb(173, 216, 230)");
106+
=======
107+
import { JSDOM } from "jsdom";
108+
import { setTimeout } from "timers/promises";
109+
import { test } from "uvu";
110+
import * as assert from "uvu/assert";
111+
let filePath = "./src/index.html";
112+
113+
// Helpers
114+
115+
const hasAllClasses = (dom, id, classes) =>
116+
classes.every((val) => dom.window.document.getElementById(id).getAttribute("class").split(" ").includes(val));
117+
118+
// Tests
119+
120+
test("Nav Buttons Don't Work (Desktop & Mobile)", async () => {
121+
const dom = await JSDOM.fromFile(filePath, {
122+
runScripts: "dangerously",
123+
resources: "usable",
124+
});
125+
await setTimeout(10);
126+
assert.is(dom.window.document.getElementById("nav-logo").getAttribute("href"), "#header");
127+
assert.is(dom.window.document.getElementById("nav-challenges").getAttribute("href"), "#challenges");
128+
assert.is(dom.window.document.getElementById("nav-signup").getAttribute("href"), "#signup");
129+
assert.is(dom.window.document.getElementById("mobile-nav-challenges").getAttribute("href"), "#challenges");
130+
assert.is(dom.window.document.getElementById("mobile-nav-signup").getAttribute("href"), "#signup");
131+
});
132+
133+
test("Desktop Nav Is Visible on Mobile", async () => {
134+
const dom = await JSDOM.fromFile(filePath, {
135+
runScripts: "dangerously",
136+
resources: "usable",
137+
});
138+
await setTimeout(10);
139+
assert.ok(hasAllClasses(dom, "nav-challenges", ["hide-small"]));
140+
assert.ok(hasAllClasses(dom, "nav-signup", ["hide-small"]));
141+
});
142+
143+
test("Invert Banner Image Colors", async () => {
144+
const dom = await JSDOM.fromFile(filePath, {
145+
runScripts: "dangerously",
146+
resources: "usable",
147+
});
148+
await setTimeout(150);
149+
let banner = dom.window.document.getElementById("jumbo-image");
150+
assert.ok(["invert(1)", "invert(100%)"].includes(dom.window.getComputedStyle(banner)._values["filter"]));
151+
});
152+
153+
test("Tiles Need to be 2x2 Grid", async () => {
154+
const dom = await JSDOM.fromFile(filePath, {
155+
runScripts: "dangerously",
156+
resources: "usable",
157+
});
158+
await setTimeout(10);
159+
let grid = dom.window.document.getElementById("challenge-grid");
160+
assert.ok(
161+
["repeat(2,1fr)", "1fr1fr", "50%50%"].includes(
162+
dom.window.getComputedStyle(grid)._values["grid-template-columns"].replace(/\s/g, "")
163+
)
164+
);
165+
});
166+
167+
test("Improve Errors on Signup Form Validation (Empty Email)", async () => {
168+
const dom = await JSDOM.fromFile(filePath, {
169+
runScripts: "dangerously",
170+
resources: "usable",
171+
});
172+
await setTimeout(150); // Need to wait for script to load
173+
174+
// simulate empty email signup
175+
dom.window.document.querySelector("button").dispatchEvent(new dom.window.MouseEvent("click"));
176+
177+
assert.is(dom.window.document.getElementById("success-message").hidden, true);
178+
assert.is(dom.window.document.getElementById("empty-error-message").hidden, false);
179+
assert.is(dom.window.document.getElementById("taken-error-message").hidden, true);
180+
});
181+
182+
test("Improve Errors on Signup Form Validation (Taken Email)", async () => {
183+
const dom = await JSDOM.fromFile(filePath, {
184+
runScripts: "dangerously",
185+
resources: "usable",
186+
});
187+
await setTimeout(150); // Need to wait for script to load
188+
189+
dom.window.document.getElementById("email").value = "[email protected]";
190+
dom.window.document.querySelector("button").dispatchEvent(new dom.window.MouseEvent("click"));
191+
192+
assert.is(dom.window.document.getElementById("success-message").hidden, true);
193+
assert.is(dom.window.document.getElementById("empty-error-message").hidden, true);
194+
assert.is(dom.window.document.getElementById("taken-error-message").hidden, false);
195+
});
196+
197+
test("Improve Errors on Signup Form Validation (Repeat Email)", async () => {
198+
const dom = await JSDOM.fromFile(filePath, {
199+
runScripts: "dangerously",
200+
resources: "usable",
201+
});
202+
await setTimeout(150); // Need to wait for script to load
203+
204+
dom.window.document.getElementById("email").value = "[email protected]";
205+
dom.window.document.querySelector("button").dispatchEvent(new dom.window.MouseEvent("click"));
206+
207+
assert.is(dom.window.document.getElementById("success-message").hidden, false);
208+
assert.is(dom.window.document.getElementById("empty-error-message").hidden, true);
209+
assert.is(dom.window.document.getElementById("taken-error-message").hidden, true);
210+
211+
dom.window.document.querySelector("button").dispatchEvent(new dom.window.MouseEvent("click"));
212+
assert.is(dom.window.document.getElementById("success-message").hidden, true);
213+
assert.is(dom.window.document.getElementById("empty-error-message").hidden, true);
214+
assert.is(dom.window.document.getElementById("taken-error-message").hidden, false);
215+
>>>>>>> Stashed changes
105216
});
106217

107218
test.run();

src/constants.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ export const COMPANIES_API_PATH = "/companies";
77

88
export const COMPANIES_TABLE_HEADERS = ["Company Name", "Status", "Created At", "Revenue YTD", "Account Executive"];
99

10-
export const COMPANY_NAME_FIELD_NAME = "company_name";
10+
export const COMPANY_NAME_FIELD_NAME = "name";
1111
export const STATUS_FIELD_NAME = "status";
1212
export const CREATED_AT_FIELD_NAME = "created_at";
1313
export const REVENUE_YTD_FIELD_NAME = "revenue_ytd";
14-
export const ACCOUNT_EXECUTIVE_FIELD_NAME = "account_executive";
14+
export const ACCOUNT_EXECUTIVE_FIELD_NAME = "account_executive";

src/ui.js

+21-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
1-
import {fetchCompanies} from "./api";
1+
import { fetchCompanies } from "./api";
22
import {
33
ACCOUNT_EXECUTIVE_FIELD_NAME,
44
COMPANIES_TABLE_HEADERS,
55
COMPANY_NAME_FIELD_NAME,
66
CREATED_AT_FIELD_NAME,
77
REVENUE_YTD_FIELD_NAME,
8-
STATUS_FIELD_NAME
8+
STATUS_FIELD_NAME,
99
} from "./constants";
1010

11+
const formatDate = (d) => {
12+
const date = new Date(d);
13+
const hours = date.getHours();
14+
const minutes = date.getMinutes();
15+
const timeString = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
16+
return timeString;
17+
};
18+
19+
const formatCurrency = (amount) => {
20+
const formattedNumber = amount.toLocaleString("en-US").replace(/,/g, " ");
21+
return formattedNumber;
22+
};
23+
1124
export const makeTable = async () => {
1225
const companies = await fetchCompanies();
1326
// Print result of api call to the developer console
@@ -20,13 +33,13 @@ export const makeTable = async () => {
2033
companiesToDisplay.push(COMPANIES_TABLE_HEADERS);
2134

2235
// Here we simply rearrange company fields in the order in which we want to display them in UI
23-
companies.map(company => {
36+
companies.map((company) => {
2437
const row = [];
2538
row.push(
2639
company[COMPANY_NAME_FIELD_NAME],
2740
company[STATUS_FIELD_NAME],
28-
company[CREATED_AT_FIELD_NAME],
29-
company[REVENUE_YTD_FIELD_NAME],
41+
formatDate(company[CREATED_AT_FIELD_NAME]),
42+
formatCurrency(company[REVENUE_YTD_FIELD_NAME]),
3043
company[ACCOUNT_EXECUTIVE_FIELD_NAME]
3144
);
3245
companiesToDisplay.push(row);
@@ -36,12 +49,12 @@ export const makeTable = async () => {
3649
const table = document.createElement("table");
3750
document.body.appendChild(table); // Drew the main table node on the document
3851

39-
companiesToDisplay.forEach(row => {
52+
companiesToDisplay.forEach((row) => {
4053
const tr = table.insertRow(); //Create a new row
4154

42-
row.forEach(column => {
55+
row.forEach((column) => {
4356
const td = tr.insertCell();
4457
td.innerText = column; // Take string from placeholder variable and append it to <tr> node
4558
});
4659
});
47-
};
60+
};

styles.css

+19-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
table {
2-
/*
2+
/*
33
A table-layout value of fixed is generally a good idea to set on your table, as it makes the table behave a bit more predictably by default.
44
Normally, table columns tend to be sized according to how much content they contain, which produces some strange results.
55
With table-layout: fixed, you can size your columns according to the width of their headings, and then deal with their content as appropriate.
@@ -9,37 +9,42 @@ table {
99
We've coupled this with a width of 100%, meaning that the table will fill any container it is put in, and be nicely
1010
responsive (although it would still need some more work to get it looking good on narrow screen widths).
1111
*/
12-
table-layout: fixed;
13-
width: 100%;
14-
/*
12+
table-layout: fixed;
13+
width: 100%;
14+
/*
1515
A border-collapse value of collapse is standard best practice for any table styling effort.
1616
By default, when you set borders on table elements, they will look pretty ugly.
1717
*/
18-
border-collapse: collapse;
19-
border: 3px solid purple;
18+
border-collapse: collapse;
19+
border: 3px solid lightblue;
20+
}
21+
22+
tbody tr:first-child {
23+
background-color: lightblue;
2024
}
2125

2226
thead th:nth-child(1) {
23-
width: 30%;
27+
width: 30%;
2428
}
2529

2630
thead th:nth-child(2) {
27-
width: 20%;
31+
width: 20%;
2832
}
2933

3034
thead th:nth-child(3) {
31-
width: 15%;
35+
width: 15%;
3236
}
3337

3438
thead th:nth-child(4) {
35-
width: 35%;
39+
width: 35%;
3640
}
3741

38-
th, td {
39-
padding: 20px;
42+
th,
43+
td {
44+
padding: 20px;
4045
}
4146

4247
/* nth-child is a pretty neat thing to use and is widely applicable in real-life projects. Reader is highly encouraged to do more reading on this. */
4348
tr:nth-child(1) {
44-
font-weight: bold;
45-
}
49+
font-weight: bold;
50+
}

0 commit comments

Comments
 (0)