Files
gold_land_user/e2e/smart-shop.spec.ts
T
safavimohadeseh78andCursor c53a67831d
Frontend CI / unit (test, type-check, build) (push) Successful in 7m21s
Frontend CI / browser E2E (frontend + pinned backend) (push) Successful in 11m38s
feat: complete the thirteen-stage learning experience and E2E journey
Play levels 7-13 in the app and pin E2E to the local thirteen-stage backend commit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 19:42:04 +03:30

136 lines
6.8 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { fetchMe, registerViaUi, uniqueUsername } from './helpers/auth'
async function completePrior(page: import('@playwright/test').Page, headers: { authorization: string }) {
const lessons: Record<number, Array<Record<string, unknown>>> = {
1: [
{ questionId: 'money-q1', answerId: 'option-a' },
{ questionId: 'money-q2', answerId: 'true' },
{ questionId: 'money-q3', answerId: 'option-a' },
{ questionId: 'money-q4', answerId: 'true' },
{ questionId: 'money-q5', answerId: 'option-b' },
],
2: [
{ questionId: 'saving-q1', answerId: 'option-b' },
{ questionId: 'saving-q2', answerId: 'true' },
{ questionId: 'saving-q3', answerId: 'option-a' },
{ questionId: 'saving-q4', answerId: 'true' },
{ questionId: 'saving-q5', answerId: 'option-a' },
],
3: [
{ questionId: 'needs-q1', answerId: 'option-a' },
{ questionId: 'needs-q2', answerId: 'true' },
{ questionId: 'needs-q3', orderedItemIds: ['water', 'food', 'medicine', 'shoes', 'toy', 'crown'] },
{ questionId: 'needs-q4', answerId: 'option-a' },
{ questionId: 'needs-q5', answerId: 'true' },
],
4: [
{ questionId: 'gold-q1', answerId: 'option-a' },
{ questionId: 'gold-q2', answerId: 'true' },
{ questionId: 'gold-q3', answerId: 'option-a' },
{ questionId: 'gold-q4', answerId: 'false' },
{ questionId: 'gold-q5', answerId: 'option-b' },
],
5: [
{ questionId: 'market-q1', answerId: 'option-a' },
{ questionId: 'market-q2', answerId: 'false' },
{ questionId: 'market-q3', answerId: 'option-a' },
{ questionId: 'market-q4', answerId: 'true' },
{ questionId: 'market-q5', answerId: 'option-b' },
],
6: [
{ questionId: 'inflation-q1', answerId: 'option-b' },
{ questionId: 'inflation-q2', answerId: 'true' },
{ questionId: 'inflation-q3', answerId: 'option-a' },
{ questionId: 'inflation-q4', answerId: 'false' },
{ questionId: 'inflation-q5', answerId: 'option-b' },
],
}
for (let levelId = 1; levelId <= 6; levelId += 1) {
expect((await page.request.post(`/api/gold-land/levels/${levelId}/start`, { headers })).ok()).toBeTruthy()
expect((await page.request.post(`/api/gold-land/levels/${levelId}/complete`, { headers, data: { answers: lessons[levelId] } })).ok()).toBeTruthy()
}
const posts: Array<[string, unknown]> = [
['7', { answers: [
{ questionId: 'initial', allocations: { transport: 20, food: 25, savings: 20, fun: 0 } },
{ questionId: 'final', allocations: { transport: 30, food: 25, savings: 20, fun: 0 } },
] }],
['8', { answers: [
{ questionId: 'q-loss', answerId: 'b' },
{ questionId: 'q-certain', answerId: 'no' },
{ questionId: 'q-need', answerId: 'keep' },
{ questionId: 'q-compare', answerId: 'range' },
{ questionId: 'q-promise', answerId: 'check' },
] }],
['9', { answers: [
{ questionId: 'portfolio', holdings: { sun: 40, rain: 30, wind: 30 } },
{ questionId: 'q-one', answerId: 'depend' },
{ questionId: 'q-loss', answerId: 'no' },
{ questionId: 'q-name', answerId: 'no' },
{ questionId: 'q-best', answerId: 'no' },
{ questionId: 'q-approach', answerId: 'balanced' },
] }],
['10', { answers: [
{ questionId: 'compound-q1', answerId: 'on-balance' },
{ questionId: 'compound-q2', answerId: '121' },
{ questionId: 'compound-q3', answerId: 'from-110' },
{ questionId: 'compound-q4', answerId: 'compound' },
{ questionId: 'compound-q5', answerId: 'false' },
] }],
]
for (const [levelId, data] of posts) {
expect((await page.request.post(`/api/gold-land/levels/${levelId}/start`, { headers })).ok()).toBeTruthy()
expect((await page.request.post(`/api/gold-land/levels/${levelId}/complete`, { headers, data })).ok()).toBeTruthy()
}
}
async function answerShop(page: import('@playwright/test').Page) {
const picks = [
['دفتر ۶۰برگ، ۴۰ سکه، تحویل ۵ سکه', 'نیاز را برآورده می‌کند و هزینه نهایی‌اش بین گزینه‌های مناسب کمتر است'],
['مداد با قیمت نهایی ۲۸، بدون تخفیف', 'برای کالای یکسان، مبلغ نهایی پرداختی مهم است؛ درصد تخفیف به‌تنهایی کافی نیست'],
['فعلاً نخر و اندازه و هزینه نهایی را بپرس، با کمک بزرگسال قابل اعتماد', 'اطلاعات لازم برای تصمیم و مقایسه هنوز کامل نیست'],
]
for (let index = 0; index < picks.length; index += 1) {
if (index === 2) await expect(page.getByText('نامشخص').first()).toBeVisible()
await page.getByText(picks[index]![0]!, { exact: true }).click()
await page.getByText(picks[index]![1]!, { exact: true }).click()
await page.getByRole('button', { name: index === picks.length - 1 ? 'مرور انتخاب‌ها' : 'مأموریت بعد' }).click()
}
}
test('smart shop from the map', async ({ page }) => {
const user = uniqueUsername('shop')
await registerViaUi(page, user, 'pass1234', 'خرید')
const token = await page.evaluate(() => localStorage.getItem('gold-land-auth-token'))
await completePrior(page, { authorization: `Bearer ${token}` })
await page.goto('/map')
await page.getByRole('button', { name: 'مرحله 11: خرید هوشمند' }).click()
await page.getByRole('button', { name: 'شروع بازی' }).click()
await page.getByRole('button', { name: 'شروع خریدها' }).click()
await expect(page.getByText('بودجه:')).toBeVisible()
await expect(page.getByText('جمع نهایی: ۴۵ سکه')).toBeVisible()
await answerShop(page)
const before = await fetchMe(page)
await page.getByRole('button', { name: 'ثبت نتیجه' }).click()
await expect(page.getByText('پاداش:')).toBeVisible()
await page.getByRole('button', { name: 'بازگشت به نقشه' }).click()
await page.reload()
const after = await fetchMe(page)
expect(after.progress.mapLevels.find((level) => level.id === 11)?.stars).toBe(3)
expect(after.user.coins).toBe(before.user.coins + 18 + 9)
await page.getByRole('button', { name: 'مرحله 11: خرید هوشمند' }).click()
await page.getByRole('button', { name: 'مرور مجدد' }).click()
await page.getByRole('button', { name: 'شروع خریدها' }).click()
await answerShop(page)
const replayBefore = await fetchMe(page)
await page.getByRole('button', { name: 'ثبت نتیجه' }).click()
await expect(page.getByText('پاداش تازه‌ای اضافه نشد')).toBeVisible()
const replayAfter = await fetchMe(page)
expect(replayAfter.user.coins).toBe(replayBefore.user.coins)
await page.goto('/map')
await expect(page.getByRole('button', { name: 'مرحله 13: آزمون قلعه' })).toBeDisabled()
})