Skip to content

Commit 111b822

Browse files
committed
feat: add e2e tests
1 parent 6d5ed92 commit 111b822

File tree

10 files changed

+215
-22
lines changed

10 files changed

+215
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
e2e/foo.spec.ts
12
*.report.html
23
tsconfig.tsbuildinfo
34
public/sw.js*

__tests__/parse.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,21 @@ describe("isEquals", () => {
168168
expectIsEquals("null", '"null"', false);
169169
});
170170
});
171+
172+
describe("parse errors", () => {
173+
test("addition ,", () => {
174+
const tree = parseJSON(
175+
`{
176+
"foo": [
177+
"first",
178+
"second",
179+
],
180+
"bar": 3
181+
}`,
182+
{ format: true },
183+
);
184+
185+
expect(tree.hasError()).toEqual(true);
186+
expect(tree.errors?.map((e) => e.context)).toEqual([['...second", ', "]", ', "bar...']]);
187+
});
188+
});

e2e/helpers/getEditor.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

e2e/helpers/utils.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { expect, type Locator, type Page } from "@playwright/test";
2+
import fs from "fs";
3+
import path from "path";
4+
5+
interface Options {
6+
goto?: boolean;
7+
rightEditor?: boolean;
8+
}
9+
10+
export async function getEditor(page: Page, options?: Options) {
11+
if (options?.goto) {
12+
await page.goto("/editor");
13+
}
14+
15+
const id = `#${options?.rightEditor ? "right" : "left"}-panel`;
16+
const editor = await page.locator(id).locator(".view-lines");
17+
await expect(editor).toBeVisible();
18+
return editor;
19+
}
20+
21+
export function getFilePath(name: string) {
22+
return path.join(process.cwd(), "__tests__/fixtures/", name);
23+
}
24+
25+
export async function getDownloadText(page: Page, downloadFn: () => void) {
26+
const downloadPromise = page.waitForEvent("download");
27+
await downloadFn();
28+
const download = await downloadPromise;
29+
const filePath = await download.path();
30+
const content = await fs.readFileSync(filePath, "utf8");
31+
return content;
32+
}
33+
34+
export function getBackgroundColor(locator: Locator) {
35+
return locator.evaluate((el) => window.getComputedStyle(el).getPropertyValue("background-color"));
36+
}
37+
38+
export function getGraphNode(page: Page, id: string) {
39+
return page.getByTestId(`rf__node-${id}`);
40+
}

e2e/tests/commands.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { test, expect } from "@playwright/test";
2+
import { getEditor } from "../helpers/utils";
3+
4+
test("Search command", async ({ page }) => {
5+
const editor = await getEditor(page, { goto: true });
6+
await expect(editor).toContainText("Aidan Gillen");
7+
});

e2e/tests/home.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test, expect } from "@playwright/test";
2-
import { getEditor } from "../helpers/getEditor";
2+
import { getEditor } from "../helpers/utils";
33

44
test("go to editor", async ({ page }) => {
55
await page.goto("/");

e2e/tests/sidenav.spec.ts

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,102 @@
1-
import { test } from "@playwright/test";
1+
import { test, expect } from "@playwright/test";
2+
import { getEditor, getBackgroundColor, getDownloadText, getFilePath } from "../helpers/utils";
23

3-
test("sidenav", async ({ page }) => {
4+
test("click logo", async ({ page }) => {
45
await page.goto("/editor");
6+
await page.getByRole("link", { name: /JSON For You/ }).click();
7+
await expect(page.getByRole("link", { name: "Try it now" })).toBeVisible();
8+
});
9+
10+
test("click log in", async ({ page }) => {
11+
await page.goto("/editor");
12+
await page.getByRole("button", { name: "Log in" }).click();
13+
await expect(page.locator("text=Login with Google")).toBeVisible();
14+
});
15+
16+
test("import JSON file", async ({ page }) => {
17+
const editor = await getEditor(page, { goto: true });
18+
19+
await page.getByRole("button", { name: "Import" }).click();
20+
await page
21+
.locator("div")
22+
.filter({ hasText: /^Click here to select file or drop a file right here$/ })
23+
.setInputFiles(getFilePath("nest.txt"));
24+
25+
await expect(editor).toContainText('"ccc"');
26+
});
27+
28+
test("import CSV file without header", async ({ page }) => {
29+
const editor = await getEditor(page, { goto: true });
30+
31+
await page.getByRole("button", { name: "Import" }).click();
32+
await page.locator("button").filter({ hasText: "JSON" }).click();
33+
await page.getByLabel("CSV").click();
34+
await page.getByText("File contains header").click();
35+
await page
36+
.locator("div")
37+
.filter({ hasText: /^Click here to select file or drop a file right here$/ })
38+
.setInputFiles(getFilePath("region_and_currency.csv"));
39+
40+
await expect(editor).toContainText(/\[\s*"Region",/);
41+
});
42+
43+
test("export JSON file", async ({ page }) => {
44+
await getEditor(page, { goto: true });
45+
await page.getByRole("button", { name: "Export" }).click();
46+
const content = await getDownloadText(page, async () => await page.getByRole("button", { name: "Download" }).click());
47+
await expect(content).toContain("Aidan Gillen");
48+
});
49+
50+
test("export CSV file with preview", async ({ page }) => {
51+
const editor = await getEditor(page, { goto: true });
52+
53+
// import CSV file with header
54+
await page.getByRole("button", { name: "Import" }).click();
55+
await page.locator("button").filter({ hasText: "JSON" }).click();
56+
await page.getByLabel("CSV").click();
57+
await page
58+
.locator("div")
59+
.filter({ hasText: /^Click here to select file or drop a file right here$/ })
60+
.setInputFiles(getFilePath("region_and_currency.csv"));
61+
await expect(editor).toContainText('"Region":');
62+
63+
await page.getByRole("button", { name: "Export" }).click();
64+
await page.locator("button").filter({ hasText: "JSON" }).click();
65+
await page.getByLabel("CSV").click();
66+
67+
// preview CSV file
68+
await page.getByRole("button", { name: "Preview" }).click();
69+
const rightEditor = await getEditor(page, { rightEditor: true });
70+
await expect(rightEditor).toContainText("Region,Region Code,Currency");
71+
72+
// download CSV file
73+
const content = await getDownloadText(page, async () => await page.getByRole("button", { name: "Download" }).click());
74+
await expect(content).toContain("Region,Region Code,Currency");
75+
});
76+
77+
test("toggle buttons", async ({ page }) => {
78+
const editor = await getEditor(page, { goto: true });
79+
80+
const testBtn = async (name: string) => {
81+
const btn = await page.getByRole("button", { name });
82+
await expect(btn).toBeVisible();
83+
84+
await editor.click();
85+
const color1 = await getBackgroundColor(btn);
86+
87+
await btn.click();
88+
await editor.click();
89+
const color2 = await getBackgroundColor(btn);
90+
91+
await btn.click();
92+
await editor.click();
93+
const color3 = await getBackgroundColor(btn);
94+
95+
await expect(color1).not.toEqual(color2);
96+
await expect(color2).not.toEqual(color3);
97+
};
98+
99+
await testBtn("Auto Format");
100+
await testBtn("Nested Parse");
101+
await testBtn("Auto Sort");
5102
});

e2e/tests/statusbar.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { test, expect, type Page } from "@playwright/test";
2+
import { getEditor } from "../helpers/utils";
3+
4+
function getJsonPaths(page: Page) {
5+
return page.getByTestId("statusbar").getByLabel("breadcrumb").getByRole("listitem", { includeHidden: false });
6+
}
7+
8+
test("display cursor JSON path", async ({ page }) => {
9+
const editor = await getEditor(page, { goto: true });
10+
11+
await expect(editor).toContainText("The Wire");
12+
await page.getByText("The Wire").nth(0).click();
13+
14+
{
15+
const pathElements = await getJsonPaths(page);
16+
await expect(pathElements).toHaveText(["Aidan Gillen", "array", "1"]);
17+
18+
await pathElements.nth(0).click();
19+
await expect(pathElements).toHaveText(["Aidan Gillen"]);
20+
}
21+
22+
{
23+
await page.getByText("string").nth(0).click();
24+
const pathElements = await getJsonPaths(page);
25+
await expect(pathElements).toHaveText(["Aidan Gillen", "string"]);
26+
}
27+
});
28+
29+
test("display validation errors", async ({ page }) => {
30+
const editor = await getEditor(page, { goto: true });
31+
32+
await expect(editor).toContainText("The Wire");
33+
await page.getByText("The Wire").nth(0).click();
34+
await page.keyboard.press("End");
35+
await page.keyboard.press(",");
36+
await expect(page.getByTestId("statusbar")).toHaveText('Ln 6, col 5 parsing error:...Wire", ], "string...');
37+
});

e2e/tests/tutorial.spec.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { test, expect } from "@playwright/test";
2-
import { getEditor } from "../helpers/getEditor";
2+
import { getEditor, getGraphNode } from "../helpers/utils";
33

44
test("tutorial data", async ({ page }) => {
5-
await page.goto("/editor");
6-
const editor = await getEditor(page);
7-
await expect(editor).toContainText("Aidan Gillen");
5+
{
6+
const editor = await getEditor(page, { goto: true });
7+
await expect(editor).toContainText("Aidan Gillen");
8+
}
89

910
// assert graph view has nodes.
10-
await expect(page.getByTestId("rf__node-$")).toBeVisible();
11-
await expect(page.getByTestId("rf__node-$/Alexander%20Skarsgard")).toBeVisible();
12-
await expect(page.getByTestId("rf__node-$/Aidan%20Gillen/array")).toBeVisible();
11+
await expect(getGraphNode(page, "$")).toBeVisible();
12+
await expect(getGraphNode(page, "$/Alexander%20Skarsgard")).toBeVisible();
13+
await expect(getGraphNode(page, "$/Aidan%20Gillen/array")).toBeVisible();
1314

14-
const nd = await page.getByTestId("rf__node-$/Aidan%20Gillen");
15+
const nd = await getGraphNode(page, "$/Aidan%20Gillen");
1516
await expect(nd).toBeVisible();
1617
await nd.click();
1718

@@ -23,9 +24,8 @@ test("tutorial data", async ({ page }) => {
2324

2425
// no tutorial data when reentry.
2526
{
26-
await page.reload();
27-
const editor = await getEditor(page);
27+
const editor = await getEditor(page, { goto: true });
2828
await expect(editor).toHaveText("");
29-
await expect(page.getByTestId("rf__node-$")).toBeHidden();
29+
await expect(getGraphNode(page, "$")).toBeHidden();
3030
}
3131
});

src/containers/editor/StatusBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { useShallow } from "zustand/react/shallow";
1919

2020
export default function StatusBar() {
2121
return (
22-
<div className="w-full min-h-fit h-statusbar px-4 py-1 flex text-xs gap-4">
22+
<div data-testid="statusbar" className="w-full min-h-fit h-statusbar px-4 py-1 flex text-xs gap-4">
2323
<JsonPath />
2424
<ParseErrorMsg kind="main" />
2525
<div className="ml-auto" />

0 commit comments

Comments
 (0)