Skip to content

Commit 80114ec

Browse files
authored
Add: Add test for homepage (#118)
* Add: Add test for homepage * Fix test * update code * fix test * chore: remove screenshots and ignore tech/screenshots * add our-products link
1 parent a8fe3b1 commit 80114ec

File tree

8 files changed

+722
-62
lines changed

8 files changed

+722
-62
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ playwright/.cache/
4545
.test-results/
4646
/test-results/
4747
**/test-results/
48-
.ms-playwright/
48+
.ms-playwright/
49+
/screenshots/

app/[lang]/(hyperjump)/components/location.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function Location({ lang, location }: LocationProps) {
2626
const { address, duns, email, imageUrl, mapsUrl, title } = location;
2727

2828
return (
29-
<GridItemsContainer>
29+
<GridItemsContainer id="location">
3030
<GridItemsTitle title={mainOurLocation(lang)} layout="vertical" />
3131
<div className="mt-8 mb-6 grid w-full grid-cols-1 overflow-hidden rounded shadow-lg lg:grid-cols-4">
3232
<div className="relative col-span-1 overflow-hidden p-6 text-white">

e2e/homepage.spec.ts

Lines changed: 204 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,209 @@
11
import { test, expect } from "@playwright/test";
22

3-
const languages = ["en", "id"];
3+
const URL = "http://localhost:3000";
44

5-
for (const lang of languages) {
6-
test(`Homepage (${lang}) should load sections`, async ({ page }) => {
7-
await page.goto(`/${lang}`);
5+
test.describe("Homepage", () => {
6+
test("Branding: should display hyperjump logo correctly in navbar and footer", async ({
7+
page
8+
}) => {
9+
await page.goto(URL);
810

9-
await expect(page.locator("#hero")).toBeVisible({ timeout: 10000 });
10-
await expect(page.locator("#services")).toBeVisible({ timeout: 10000 });
11-
await expect(page.locator("#case-studies")).toBeVisible({ timeout: 10000 });
12-
await expect(page.locator("#open-source")).toBeVisible({ timeout: 10000 });
13-
await expect(page.locator("#faqs")).toBeVisible({ timeout: 10000 });
11+
const navbarLogo = page
12+
.getByRole("link", { name: "Hyperjump Logo" })
13+
.first();
14+
await expect(navbarLogo).toBeVisible();
15+
await navbarLogo.click();
16+
await expect(page).toHaveURL(/\/(en|id)?\/?$/);
17+
18+
// Footer
19+
const footerLogo = page
20+
.getByRole("contentinfo")
21+
.getByRole("link", { name: "Hyperjump Logo" });
22+
await expect(footerLogo).toBeVisible();
23+
await footerLogo.click();
24+
await expect(page).toHaveURL(/\/(en|id)?\/?$/);
25+
});
26+
27+
test("SEO: meta title and description should exist and match expected content", async ({
28+
page
29+
}) => {
30+
await page.goto(URL);
31+
32+
const title = await page.title();
33+
const description = await page
34+
.locator('meta[name="description"]')
35+
.getAttribute("content");
36+
37+
expect(title.length).toBeGreaterThan(10);
38+
expect(description?.length).toBeGreaterThan(20);
39+
});
40+
41+
// Test Structure / UI Sections
42+
test("Hero Section: should display hero title, subtitle, and CTA button correctly", async ({
43+
page
44+
}) => {
45+
await page.goto(URL);
46+
47+
// Hero title and subtitle
48+
const heroHeading = page.getByRole("heading", {
49+
name: "Your partner in building"
50+
});
51+
await expect(heroHeading).toBeVisible();
52+
53+
const heroSubtitle = page.getByText("We help organizations deliver");
54+
await expect(heroSubtitle).toBeVisible();
55+
56+
// Partner logos
57+
const partnerLogos = [
58+
"Amman Mineral Internasional",
59+
"Bank Tabungan Negara",
60+
"Eka Mas Republik",
61+
"Sinar Mas Digital Day",
62+
"Smartfren"
63+
];
64+
65+
for (const name of partnerLogos) {
66+
const logo = page.getByRole("img", { name });
67+
await expect(logo).toBeVisible();
68+
}
69+
});
70+
71+
test("Services Section: should display all service cards and links correctly", async ({
72+
page
73+
}) => {
74+
await page.goto(URL);
75+
76+
const servicesHeading = page.getByRole("heading", {
77+
name: "Services",
78+
exact: true
79+
});
80+
await expect(servicesHeading).toBeVisible();
81+
await expect(page.getByText("We offer expert technology")).toBeVisible();
82+
83+
// Service cards
84+
const services = [
85+
{ title: "Inference AI", desc: "Inference AIDesign, develop," },
86+
{ title: "ERP Implementation", desc: "ERP ImplementationStreamline" },
87+
{ title: "CTO-as-a-Service", desc: "CTO-as-a-ServiceFinding," },
88+
{ title: "Software as a Service", desc: "Software as a ServiceDeploy" },
89+
{ title: "Tech Due Diligence", desc: "Tech Due DiligenceVerify and" }
90+
];
91+
92+
for (const s of services) {
93+
await expect(page.getByText(s.desc)).toBeVisible();
94+
await expect(page.getByRole("img", { name: s.title })).toBeVisible();
95+
await expect(page.getByText(s.title, { exact: true })).toBeVisible();
96+
}
97+
98+
// View more link
99+
const viewMore = page
100+
.locator("#services")
101+
.getByRole("link", { name: "View More" });
102+
await expect(viewMore).toBeVisible();
103+
await expect(viewMore).toHaveAttribute("href", /services/i);
104+
});
105+
106+
test("Case Studies Section: should display case study items and links correctly", async ({
107+
page
108+
}) => {
109+
await page.goto(URL);
110+
111+
await page.locator("#case-studies").click();
112+
113+
const caseHeading = page.getByRole("heading", { name: "Case Studies" });
114+
await expect(caseHeading).toBeVisible();
115+
await expect(page.getByText("Discover how we successfully")).toBeVisible();
116+
117+
await expect(page.getByText("Transforming a Fisheries Tech")).toBeVisible();
118+
await expect(page.getByText("Elevating a Media-Tech")).toBeVisible();
119+
});
120+
121+
test("FAQ Section: should toggle FAQ items correctly on click", async ({
122+
page
123+
}) => {
124+
await page.goto(URL);
125+
126+
await page.locator("#faqs").click();
127+
128+
const faqHeading = page.getByRole("heading", {
129+
name: "Frequently asked questions"
130+
});
131+
await expect(faqHeading).toBeVisible();
132+
await expect(page.getByText("Find answers to commonly")).toBeVisible();
133+
134+
const faqQuestions = [
135+
"What is CTO as a Service (",
136+
"How do you approach ERP",
137+
"What does your tech due",
138+
"Why should we choose your"
139+
];
140+
141+
for (const question of faqQuestions) {
142+
const btn = page.getByRole("button", { name: question });
143+
await expect(btn).toBeVisible();
144+
await btn.click();
145+
}
146+
147+
await expect(page.getByText("We offer specialized")).toBeVisible();
14148
});
15-
}
149+
150+
// Responsive Design
151+
const devices = [
152+
{ name: "Mobile", width: 375, height: 812 },
153+
{ name: "Tablet", width: 768, height: 1024 },
154+
{ name: "Desktop", width: 1440, height: 900 },
155+
{ name: "Large Desktop", width: 1920, height: 1080 }
156+
];
157+
158+
for (const device of devices) {
159+
test.describe(`${device.name} Responsive Layout`, () => {
160+
test(`should display correctly on ${device.name}`, async ({
161+
browser
162+
}) => {
163+
const context = await browser.newContext({
164+
viewport: { width: device.width, height: device.height }
165+
});
166+
const page = await context.newPage();
167+
168+
await page.goto(URL, {
169+
waitUntil: "domcontentloaded"
170+
});
171+
172+
const hero = page.locator("#hero");
173+
const services = page.locator("#services");
174+
const caseStudies = page.locator("#case-studies");
175+
const openSource = page.locator("#open-source");
176+
const faq = page.locator("#faqs");
177+
const footer = page.locator("footer");
178+
179+
await expect(hero).toBeVisible();
180+
await expect(services).toBeVisible();
181+
await expect(caseStudies).toBeVisible();
182+
await expect(openSource).toBeVisible();
183+
await expect(faq).toBeVisible();
184+
await expect(footer).toBeVisible();
185+
186+
await page.evaluate(async () => {
187+
const delay = (ms: number) =>
188+
new Promise((res) => setTimeout(res, ms));
189+
const totalHeight = document.body.scrollHeight;
190+
const step = window.innerHeight / 2;
191+
for (let y = 0; y < totalHeight; y += step) {
192+
window.scrollTo({ top: y, behavior: "smooth" });
193+
await delay(200);
194+
}
195+
window.scrollTo({ top: totalHeight, behavior: "smooth" });
196+
});
197+
198+
await page.waitForTimeout(2000);
199+
200+
await page.screenshot({
201+
path: `screenshots/homepage-full-${device.name.toLowerCase()}.png`,
202+
fullPage: true
203+
});
204+
205+
await context.close();
206+
});
207+
});
208+
}
209+
});

e2e/language-switch.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { test, expect } from "@playwright/test";
2+
3+
test.describe("Footer - Language Picker", () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto("http://localhost:3000");
6+
});
7+
8+
test("should switch from EN to ID with smooth scroll and visible cursor", async ({
9+
page
10+
}) => {
11+
await page.mouse.move(300, 200);
12+
13+
await page.evaluate(async () => {
14+
window.scrollTo(0, 0);
15+
});
16+
17+
const totalHeight = await page.evaluate(() => document.body.scrollHeight);
18+
19+
for (let y = 0; y < totalHeight; y += 50) {
20+
await page.mouse.wheel(0, 50);
21+
await page.mouse.move(400, 200 + y * 0.02);
22+
await page.waitForTimeout(40);
23+
}
24+
25+
await page.waitForTimeout(800);
26+
27+
const footer = page.getByRole("contentinfo");
28+
await expect(footer).toBeVisible();
29+
30+
const languageSelect = footer.getByRole("combobox");
31+
await expect(languageSelect).toBeVisible();
32+
33+
const box = await languageSelect.boundingBox();
34+
if (box) {
35+
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
36+
await page.waitForTimeout(200);
37+
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
38+
}
39+
40+
await expect(languageSelect).toHaveValue("en");
41+
42+
await languageSelect.selectOption("id");
43+
44+
await page.waitForURL(/\/id(?:\/)?$/);
45+
await page.waitForTimeout(500);
46+
47+
const langAttr = await page.locator("html").getAttribute("lang");
48+
console.log("Detected lang:", langAttr);
49+
50+
const scrollBackHeight = await page.evaluate(
51+
() => document.body.scrollHeight
52+
);
53+
for (let y = scrollBackHeight; y > 0; y -= 50) {
54+
await page.mouse.wheel(0, -50);
55+
await page.mouse.move(400, 600 - y * 0.02);
56+
await page.waitForTimeout(40);
57+
}
58+
59+
const hero = page
60+
.locator("#hero, [data-testid='hero'], header, main section")
61+
.first();
62+
await expect(hero).toBeVisible();
63+
});
64+
});

0 commit comments

Comments
 (0)