Skip to content

Commit 84fdbb9

Browse files
authored
Tests landing page (#1797)
* test: added tests for landing page and yml file to run them * test: added yml file for frontend landing page tests * fix: lint check fix
1 parent d1bce06 commit 84fdbb9

File tree

14 files changed

+682
-18
lines changed

14 files changed

+682
-18
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Landing Page | ENV
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
environment:
7+
description: "Choose environment"
8+
required: true
9+
type: choice
10+
options:
11+
- hoodi.staging
12+
- mainnet.staging
13+
tests_ref:
14+
description: "Git ref (branch/tag/SHA) to run tests from"
15+
required: true
16+
default: "main"
17+
type: string
18+
19+
jobs:
20+
run-landing-page-tests:
21+
name: Landing Page • ${{ inputs.environment }} • ${{ inputs.tests_ref }}
22+
runs-on: ubuntu-latest
23+
24+
env:
25+
ENV: ${{ inputs.environment }}
26+
27+
steps:
28+
- name: Checkout code (tests ref)
29+
uses: actions/checkout@v4
30+
with:
31+
# This controls which branch/tag/SHA your tests run against.
32+
ref: ${{ inputs.tests_ref }}
33+
34+
- name: Setup Node.js
35+
uses: actions/setup-node@v4
36+
with:
37+
node-version: 22
38+
cache: npm
39+
40+
- name: Install dependencies
41+
run: npm ci
42+
43+
- name: Install Playwright browsers
44+
run: npx playwright install --with-deps
45+
46+
# Keep your IF/ELSE block; run with HTML reporter for CI
47+
- name: Run Playwright (@landing-page)
48+
run: |
49+
if [ "${ENV}" = "hoodi.staging" ]; then
50+
ENV=hoodi.staging npx playwright test --config=tests/playwright.config.ts --grep @landing-page --reporter=html
51+
else
52+
ENV=mainnet.staging npx playwright test --config=tests/playwright.config.ts --grep @landing-page --reporter=html
53+
fi
54+
55+
- name: Upload Playwright report (HTML)
56+
if: always()
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: playwright-report-${{ inputs.environment }}-${{ inputs.tests_ref }}
60+
path: playwright-report
61+
retention-days: 7

frontend/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ server.key
3939

4040
/test-results
4141
/tests/results
42+
/tests/.env.*

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
"preview": "nuxt preview",
6060
"test:e2e": "npx playwright test --config=tests/playwright.config.ts",
6161
"test:e2e:ui": "npm run test:e2e -- --ui",
62+
"tests-landing-page-hoodi": "ENV=hoodi.staging npx playwright test --config=tests/playwright.config.ts --grep @landing-page --ui",
63+
"tests-landing-page-mainnet": "ENV=mainnet.staging npx playwright test --config=tests/playwright.config.ts --grep @landing-page --ui",
6264
"typecheck": "npx nuxi typecheck",
6365
"validate": "npm run lint:fix && npm run typecheck"
6466
},

frontend/tests/page-object/login.page.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const LoginPage = {
55
errorEmail: (page: Page) => page.locator('text=Please provide a valid email address.'),
66
errorInvalidPassword: (page: Page) => page.locator('text=Please enter your password.'),
77
errorPasswordMaxLength: (page: Page) => page.locator('text=Please provide at least 5 characters.'),
8-
loginBtn: (page: Page) => page.getByRole('button', { name: 'Log in' }),
8+
loginBtn: (page: Page) => page.getByRole('button', { name: 'Login' }),
99
password: (page: Page) => page.getByLabel('Password'),
1010
toastMessageCannotLogin: (page: Page) => page.locator('text=Cannot log in: your email or your password is unknown.'),
1111
}
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
import path from 'path'
2-
import { fileURLToPath } from 'node:url'
32
import dotenv from 'dotenv'
43
import {
54
defineConfig, devices,
65
} from '@playwright/test'
7-
import type { ConfigOptions } from '@nuxt/test-utils/playwright'
86

9-
dotenv.config({ path: path.resolve(process.cwd(), '.env') })
7+
const envName = process.env.ENV || 'local'
8+
const envFile = `.env.${envName}`
9+
dotenv.config({ path: path.resolve(process.cwd(), 'tests', envFile) })
1010

11-
export default defineConfig<ConfigOptions>({
11+
console.log(`✅ Running Playwright with environment: ${envName}`)
12+
console.log(`📄 Loaded env file: ${envFile}`)
13+
console.log(`🌍 Base URL: ${process.env.URL}`)
14+
15+
export default defineConfig({
1216
outputDir: './results',
1317
projects: [ {
1418
name: 'chromium',
1519
use: {
16-
...devices['Desktop Chrome'], channel: 'chromium',
20+
...devices['Desktop Chrome'],
21+
channel: 'chromium',
1722
},
1823
} ],
19-
testMatch: '**/*.spec.ts',
20-
timeout: 300000,
24+
retries: 3,
25+
testMatch: [ '**/*.spec.ts' ],
26+
timeout: 20000,
2127
use: {
22-
baseURL: process.env.NUXT_PUBLIC_DOMAIN,
28+
baseURL: process.env.URL,
2329
ignoreHTTPSErrors: true,
24-
nuxt: {
25-
rootDir: fileURLToPath(new URL('.', import.meta.url)),
26-
},
2730
},
2831
})
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import {
2+
expect, goto, test,
3+
} from '../../../utils/helpers'
4+
5+
test.describe('Verify section Explorer', {
6+
tag: '@landing-page',
7+
}, () => {
8+
test.beforeEach(async ({ page }) => await goto(page, '/products#stacking-hub', 'networkidle'))
9+
10+
test('verify Landing Page is opened', async ({ page }) => {
11+
await expect(page.getByText('Explore Transactions & Validator Staking on')).toBeVisible()
12+
await expect(page.getByLabel('Explore Transactions &').getByText('ETH')).toBeVisible()
13+
})
14+
15+
test('check footer contains all nececcary sections', async ({ page }) => {
16+
await expect(page.getByRole('link', { name: 'Beaconchain Homepage By' })).toBeVisible()
17+
await expect(page.getByRole('heading', { name: 'Services' })).toBeVisible()
18+
await expect(page.getByRole('heading', { name: 'Resources' })).toBeVisible()
19+
await expect(page.getByRole('heading', { name: 'Links' })).toBeVisible()
20+
await expect(page.getByRole('contentinfo').getByRole('link', {
21+
exact: true, name: 'API',
22+
})).toBeVisible()
23+
await expect(page.getByRole('contentinfo').getByRole('link', { name: 'StakingHub' })).toBeVisible()
24+
await expect(page.getByRole('contentinfo').getByRole('link', {
25+
exact: true, name: 'Explorer',
26+
})).toBeVisible()
27+
await expect(page.getByRole('link', { name: 'Advertise' })).toBeVisible()
28+
await expect(page.getByRole('link', { name: 'beaconcha.in Premium' })).toBeVisible()
29+
await expect(page.getByRole('link', { name: 'Swag Shop' })).toBeVisible()
30+
await expect(page.getByRole('link', { name: 'API Pricing' })).toBeVisible()
31+
await expect(page.getByRole('link', { name: 'Contact Sales' })).toBeVisible()
32+
await expect(page.getByRole('link', { name: 'Site Status' })).toBeVisible()
33+
await expect(page.getByRole('link', { name: 'Go to our Discord server' })).toBeVisible()
34+
await expect(page.getByRole('link', { name: 'Go to our X profile' })).toBeVisible()
35+
await expect(page.getByRole('link', { name: 'Check out our GitHub' })).toBeVisible()
36+
await expect(page.getByText('Follow us on social media to find out the latest updates on our progress.')).toBeVisible()
37+
})
38+
39+
test('check user can click on each link provided in Services section', async ({ page }) => {
40+
await page.getByRole('contentinfo').getByRole('link', {
41+
exact: true, name: 'API',
42+
}).click()
43+
await expect(page).toHaveURL(/https:\/\/docs\.beaconcha\.in\/login\?redirect=(?:%2[Ff]|\/)(?:&[^#]*)?$/)
44+
await page.goBack()
45+
46+
await page.getByRole('contentinfo').getByRole('link', {
47+
exact: true, name: 'StakingHub',
48+
}).click()
49+
await expect(page).toHaveURL(/\/dashboard$/i)
50+
await page.goBack()
51+
52+
await page.getByRole('contentinfo').getByRole('link', {
53+
exact: true, name: 'Explorer',
54+
}).click()
55+
await expect(page).toHaveURL(/\/$/i)
56+
await page.goBack()
57+
})
58+
59+
test('check user can click on each link provided in Resources section', async ({ page }) => {
60+
await page.getByRole('link', { name: 'Advertise' }).click()
61+
await expect(page).toHaveURL(/\/advertisewithus$/i)
62+
await page.goBack()
63+
64+
await page.getByRole('link', { name: 'beaconcha.in Premium' }).click()
65+
await expect(page).toHaveURL(/\/premium$/i)
66+
await page.goBack()
67+
68+
await page.getByRole('link', { name: 'Swag Shop' }).click()
69+
await expect(page).toHaveURL(/https:\/\/shop\.beaconcha\.in\/#!\/?/i)
70+
await page.goBack()
71+
72+
await page.getByRole('link', { name: 'API Pricing' }).click()
73+
await expect(page).toHaveURL(/\/products\/pricing$/i)
74+
await page.goBack()
75+
76+
await page.getByRole('link', { name: 'Contact Sales' }).click()
77+
await expect(page).toHaveURL(/\/contact-sales$/i)
78+
await page.goBack()
79+
80+
await page.getByRole('link', { name: 'Site Status' }).click()
81+
await expect(page).toHaveURL(/https:\/\/status\.beaconcha\.in\/?/i)
82+
await page.goBack()
83+
})
84+
85+
test('check user can click on each link provided in Links section', async ({ page }) => {
86+
await page.getByRole('link', { name: 'Go to our Discord server' }).click()
87+
await expect(page).toHaveURL(/https:\/\/discord\.com\/invite\/nVGbBnvvnA/i)
88+
await page.goBack()
89+
90+
await page.getByRole('link', { name: 'Go to our X profile' }).click()
91+
await expect(page).toHaveURL(/https:\/\/x\.com\/beaconcha_in\/?/i)
92+
await page.goBack()
93+
94+
await page.getByRole('link', { name: 'Check out our GitHub' }).click()
95+
await expect(page).toHaveURL(/https:\/\/github\.com\/gobitfly/i)
96+
await page.goBack()
97+
})
98+
99+
test('check Imprint, Terms, Privacy section', async ({ page }) => {
100+
await page.getByRole('link', { name: 'Imprint' }).click()
101+
await expect(page).toHaveURL(/https:\/\/beaconcha\.in\/imprint$/i)
102+
await expect(page.getByRole('heading', { name: 'Imprint' })).toBeVisible()
103+
await page.goBack()
104+
105+
await page.getByRole('link', { name: 'Terms' }).click()
106+
await expect(page).toHaveURL(/https:\/\/storage\.googleapis\.com\/legal\.beaconcha\.in\/tos\.pdf$/i)
107+
await page.goBack()
108+
109+
await page.getByRole('link', { name: 'Privacy' }).click()
110+
await expect(page).toHaveURL(/https:\/\/storage\.googleapis\.com\/legal\.beaconcha\.in\/privacy\.pdf$/i)
111+
await page.goBack()
112+
113+
await expect(page.getByText('© 2025 beaconcha.in. All rights reserved')).toBeVisible()
114+
})
115+
})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {
2+
expect, goto, test,
3+
} from '../../../utils/helpers'
4+
import { LoginPage } from '../../../page-object/login.page'
5+
6+
const email = process.env.USER_EMAIL!
7+
const password = process.env.USER_PASSWORD!
8+
test.describe(
9+
'Dashboard Tests Unauthorized User',
10+
{
11+
tag: '@landing-page',
12+
},
13+
() => {
14+
test.beforeEach(
15+
async ({ page }) =>
16+
await goto(page, '/products#stacking-hub', 'networkidle'),
17+
)
18+
19+
test('verify Landing Page is opened', async ({ page }) => {
20+
await expect(
21+
page.getByText('Seamless access to blockchain data on'),
22+
).toBeVisible()
23+
})
24+
25+
test('verify Login Button is visible', async ({ page }) => {
26+
await expect(page.getByRole('button', { name: 'Log in' })).toBeVisible()
27+
})
28+
29+
test('click on Login Button and verify user redirects to Sign In page', async ({
30+
page,
31+
}) => {
32+
const loginBtn = page.getByRole('button', { name: 'Log in' })
33+
await loginBtn.focus()
34+
await page.keyboard.press('Enter')
35+
await expect(page.getByRole('heading', { name: 'Sign in to beaconcha.in' })).toBeVisible()
36+
await LoginPage.email(page).fill(email)
37+
await LoginPage.password(page).fill(password)
38+
await page.waitForLoadState('networkidle')
39+
await LoginPage.loginBtn(page).click()
40+
await expect(page).toHaveURL('/products#stacking-hub')
41+
await expect(page.getByText('Seamless access to blockchain data on')).toBeVisible()
42+
await expect(page.getByRole('button', { name: 'Open user menu' })).toBeVisible()
43+
const userMenuBtn = page.getByRole('button', { name: 'Open user menu' })
44+
await userMenuBtn.focus()
45+
await page.keyboard.press('Enter')
46+
await expect(page).toHaveURL('/user/settings')
47+
await expect(page.getByText('Account Settings')).toBeVisible()
48+
})
49+
},
50+
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {
2+
expect, goto, test,
3+
} from '../../../utils/helpers'
4+
5+
test.describe('Dashboard Tests Unauthorized User', {
6+
tag: '@landing-page',
7+
}, () => {
8+
test.beforeEach(async ({ page }) => await goto(page, '/products#stacking-hub', 'networkidle'))
9+
10+
test('verify Landing Page is opened', async ({ page }) => {
11+
await expect(page.getByText('Seamless access to blockchain data on')).toBeVisible()
12+
})
13+
14+
test('verify three fragment Links exist (API, Stakinghub, Explorer)', async ({ page }) => {
15+
await expect(page.getByRole('navigation').getByRole('link', { name: 'API' })).toBeVisible()
16+
await expect(page.getByRole('navigation').getByRole('link', { name: 'StakingHub' })).toBeVisible()
17+
await expect(page.getByRole('navigation').getByRole('link', { name: 'Explorer' })).toBeVisible()
18+
await page.getByRole('link', {
19+
exact: true, name: 'Beaconchain Homepage',
20+
}).click()
21+
await expect(page).toHaveURL('/')
22+
})
23+
})

0 commit comments

Comments
 (0)