Skip to content

Commit 7063af9

Browse files
committed
Add cypress test to verify downloading
Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
1 parent cc7abce commit 7063af9

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

cypress/e2e/download.cy.js

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
describe("Download Bundesliga data as JSON and CSV", () => {
2+
const LEAGUE = "Bundesliga";
3+
4+
const EXPECTED_JSON_FIELDS = [
5+
"uid",
6+
"name",
7+
"nameAscii",
8+
"club",
9+
"pictureUrl",
10+
"value",
11+
"sale_price",
12+
"position",
13+
"forecast",
14+
"total_points",
15+
"average_points",
16+
"last_match",
17+
"exists",
18+
"league",
19+
];
20+
21+
const EXPECTED_CSV_HEADERS = [
22+
"Playeruid",
23+
"Name",
24+
"Ascii Name",
25+
"Club",
26+
"Picture Url",
27+
"Value",
28+
"Sale Price",
29+
"Position",
30+
"Forecast",
31+
"Total Points",
32+
"Average Points",
33+
"Last Match Points",
34+
"Exists",
35+
"League",
36+
];
37+
38+
before(() => {
39+
cy.exec(
40+
"export APP_ENV=test; ts-node --project=./tsconfig2.json cypress/e2e/download1.ts",
41+
);
42+
});
43+
44+
it("downloads JSON and verifies format", () => {
45+
cy.visit("http://localhost:3000");
46+
cy.request({
47+
method: "GET",
48+
url: `/api/download`,
49+
qs: { type: "json", league: LEAGUE },
50+
failOnStatusCode: false,
51+
}).then((response) => {
52+
expect(response.status).to.eq(200);
53+
expect(response.headers["content-type"]).to.include("application/json");
54+
expect(response.headers["content-disposition"]).to.include(
55+
"filename=players.json",
56+
);
57+
58+
const data = response.body;
59+
expect(data).to.be.an("array");
60+
expect(data.length).to.be.greaterThan(0);
61+
62+
data.forEach((player, index) => {
63+
expect(player, `Player at index ${index}`).to.be.an("object");
64+
EXPECTED_JSON_FIELDS.forEach((field) => {
65+
expect(
66+
player,
67+
`Player at index ${index} should have field '${field}'`,
68+
).to.have.property(field);
69+
});
70+
expect(player.league).to.eq(LEAGUE);
71+
expect(player.uid).to.be.a("string");
72+
expect(player.name).to.be.a("string");
73+
expect(player.club).to.be.a("string");
74+
expect(player.value).to.be.a("number");
75+
expect(player.total_points).to.be.a("number");
76+
expect(player.average_points).to.be.a("number");
77+
expect(player.pictureUrl).to.include(
78+
encodeURIComponent("/api/picture/"),
79+
);
80+
});
81+
});
82+
});
83+
84+
it("downloads CSV and verifies format", () => {
85+
cy.visit("http://localhost:3000");
86+
cy.request({
87+
method: "GET",
88+
url: `/api/download`,
89+
qs: { type: "csv", league: LEAGUE },
90+
failOnStatusCode: false,
91+
}).then((response) => {
92+
expect(response.status).to.eq(200);
93+
expect(response.headers["content-type"]).to.include("application/csv");
94+
expect(response.headers["content-disposition"]).to.include(".csv");
95+
96+
const csvText = response.body;
97+
expect(csvText).to.be.a("string");
98+
expect(csvText.length).to.be.greaterThan(0);
99+
100+
const lines = csvText.trim().split("\n");
101+
expect(lines.length).to.be.greaterThan(
102+
1,
103+
"CSV should have header + data",
104+
);
105+
106+
const headerLine = lines[0];
107+
const headers = parseCSVLine(headerLine);
108+
109+
EXPECTED_CSV_HEADERS.forEach((expectedHeader) => {
110+
expect(
111+
headers,
112+
`CSV should contain header '${expectedHeader}'`,
113+
).to.include(expectedHeader);
114+
});
115+
});
116+
});
117+
118+
it("verifies JSON and CSV contain consistent data", () => {
119+
cy.request({
120+
method: "GET",
121+
url: `/api/download`,
122+
qs: { type: "json", league: LEAGUE },
123+
}).then((jsonResponse) => {
124+
cy.request({
125+
method: "GET",
126+
url: `/api/download`,
127+
qs: { type: "csv", league: LEAGUE },
128+
}).then((csvResponse) => {
129+
const jsonData = jsonResponse.body;
130+
const csvLines = csvResponse.body.trim().split("\n");
131+
const csvHeaders = parseCSVLine(csvLines[0]);
132+
const csvRows = csvLines.slice(1).map((line) => parseCSVLine(line));
133+
134+
expect(jsonData.length).to.eq(
135+
csvRows.length,
136+
"JSON and CSV should have same number of players",
137+
);
138+
139+
const uidIndex = csvHeaders.indexOf("Playeruid");
140+
const nameIndex = csvHeaders.indexOf("Name");
141+
expect(uidIndex).to.be.greaterThan(-1);
142+
expect(nameIndex).to.be.greaterThan(-1);
143+
144+
jsonData.forEach((player, index) => {
145+
const csvRow = csvRows[index];
146+
expect(csvRow[uidIndex]).to.eq(player.uid);
147+
expect(csvRow[nameIndex]).to.eq(player.name);
148+
});
149+
});
150+
});
151+
});
152+
});
153+
154+
function parseCSVLine(line) {
155+
const result = [];
156+
let current = "";
157+
let inQuotes = false;
158+
159+
for (let i = 0; i < line.length; i++) {
160+
const char = line[i];
161+
if (char === '"') {
162+
inQuotes = !inQuotes;
163+
} else if ((char === "," && !inQuotes) || char === "\r") {
164+
result.push(current.trim());
165+
current = "";
166+
} else {
167+
current += char;
168+
}
169+
}
170+
result.push(current.trim());
171+
return result;
172+
}

cypress/e2e/download1.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import db from "#database";
2+
import { updateData } from "#scripts/update";
3+
4+
run();
5+
// Seeds Bundesliga data for the download test
6+
async function run() {
7+
await db.deleteFrom("data").where("value1", "like", "locked%").execute();
8+
await updateData("", "./sample/data1.json");
9+
}

0 commit comments

Comments
 (0)