Skip to content

Commit 10e628a

Browse files
author
Nguyen Son
committed
test: stabilize portfolio chatbot smoke
1 parent 1219cf3 commit 10e628a

4 files changed

Lines changed: 54 additions & 17 deletions

File tree

frontend/e2e/portfolio-cta-smoke.spec.ts

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ declare global {
77
}
88
}
99

10-
const CUSTOMER_EMAIL = process.env.TEST_USER_EMAIL || "customer@example.com";
10+
const CUSTOMER_EMAIL =
11+
process.env.TEST_USER_EMAIL || `portfolio-e2e-${Date.now()}@example.com`;
1112
const CUSTOMER_PASSWORD =
12-
process.env.TEST_USER_PASSWORD || "E2ETestDemoCustomerPasswordForBookStore123!";
13+
process.env.TEST_USER_PASSWORD ||
14+
"E2ETestDemoCustomerPasswordForBookStore123!";
1315
const API_URL = process.env.API_URL || "http://localhost:3001/api";
16+
let customerAccountSeeded = false;
1417

1518
function escapeRegExp(value: string) {
1619
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -49,6 +52,32 @@ async function installBrowserActionSpies(page: Page) {
4952
});
5053
}
5154

55+
async function ensureCustomerAccount(page: Page) {
56+
if (customerAccountSeeded) {
57+
return;
58+
}
59+
60+
const response = await page
61+
.context()
62+
.request.post(`${API_URL}/auth/register`, {
63+
data: {
64+
email: CUSTOMER_EMAIL,
65+
password: CUSTOMER_PASSWORD,
66+
firstName: "Portfolio",
67+
lastName: "Customer",
68+
phoneNumber: "0901231234",
69+
},
70+
});
71+
72+
if (!response.ok() && ![400, 409].includes(response.status())) {
73+
throw new Error(
74+
`Unable to prepare the portfolio customer account. Status: ${response.status()}`,
75+
);
76+
}
77+
78+
customerAccountSeeded = true;
79+
}
80+
5281
async function expectImageLoaded(image: Locator) {
5382
await image.scrollIntoViewIfNeeded();
5483
await expect(image).toBeVisible({ timeout: 15000 });
@@ -93,6 +122,7 @@ async function getFlashSaleCard(page: Page, index = 0) {
93122
}
94123

95124
async function login(page: Page) {
125+
await ensureCustomerAccount(page);
96126
await page.waitForLoadState("networkidle");
97127

98128
let loginSucceeded = false;
@@ -108,7 +138,7 @@ async function login(page: Page) {
108138
);
109139
});
110140

111-
await page.locator('button[type="submit"]').click();
141+
await page.getByTestId("login-submit").click();
112142

113143
const loginResponse = await loginResponsePromise;
114144
if (loginResponse.ok()) {
@@ -381,20 +411,17 @@ test.describe("Portfolio CTA smoke", () => {
381411
expect(openCalls[0]?.[0]).toContain("mailto:contact@bookstore.com");
382412

383413
await page.getByTestId("chatbot-launcher").click();
384-
await expect(page.getByTestId("chatbot-login-cta")).toBeVisible();
385414
await expect(page.getByTestId("chatbot-status-badge")).toBeVisible();
415+
await expect(page.getByText(/demo|portfolio/i)).toBeVisible();
386416

387-
await Promise.all([
388-
page.waitForURL(/\/login\?redirect=%2F$/),
389-
page.getByTestId("chatbot-login-cta").click(),
390-
]);
391-
392-
await login(page);
393-
await expect(page).toHaveURL(/\/$/);
394-
395-
await page.getByTestId("chatbot-launcher").click();
396-
await expect(page.getByTestId("chatbot-status-badge")).toContainText(
397-
/grok|d phòng|fallback|degraded/i,
398-
);
417+
await page
418+
.getByTestId("chatbot-message-input")
419+
.fill("Có coupon nào đang dùng được không?");
420+
await page.getByTestId("chatbot-send-message").click();
421+
await expect(
422+
page
423+
.getByTestId("chatbot-assistant-message")
424+
.filter({ hasText: /Khuyến mãi|Promotions/i }),
425+
).toBeVisible({ timeout: 10000 });
399426
});
400427
});

frontend/src/app/login/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ function LoginContent() {
297297

298298
<button
299299
type="submit"
300+
data-testid="login-submit"
300301
disabled={isLoading}
301302
className="w-full h-12 flex items-center justify-center gap-2 bg-red-600 hover:bg-red-700 disabled:bg-red-400 text-white font-semibold rounded-md transition-colors disabled:cursor-not-allowed"
302303
>

frontend/src/components/chatbot/ChatInput.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export function ChatInput({
4646
<div className="flex items-end gap-2">
4747
<div className="relative flex-1">
4848
<textarea
49+
data-testid="chatbot-message-input"
50+
aria-label={placeholder}
4951
value={message}
5052
onChange={(e) => setMessage(e.target.value)}
5153
onKeyDown={handleKeyDown}
@@ -72,6 +74,8 @@ export function ChatInput({
7274

7375
<Button
7476
type="submit"
77+
data-testid="chatbot-send-message"
78+
aria-label="Send message"
7579
size="icon"
7680
disabled={!message.trim() || isTyping || disabled}
7781
className={cn(

frontend/src/components/chatbot/ChatMessage.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,12 @@ export function ChatMessage({
194194
};
195195

196196
return (
197-
<div className={cn("flex items-start gap-3", isUser && "flex-row-reverse")}>
197+
<div
198+
data-testid={
199+
isUser ? "chatbot-user-message" : "chatbot-assistant-message"
200+
}
201+
className={cn("flex items-start gap-3", isUser && "flex-row-reverse")}
202+
>
198203
{isUser ? (
199204
<div className="w-8 h-8 rounded-full bg-black flex items-center justify-center shadow-[rgba(0,0,0,0.4)_0px_0px_1px,rgba(0,0,0,0.04)_0px_4px_4px] shrink-0">
200205
<span className="text-white text-xs font-medium">B</span>

0 commit comments

Comments
 (0)