Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,52 @@ jobs:
run: npm run build
working-directory: frontend


frontend-e2e:
name: Frontend E2E
runs-on: ubuntu-latest
needs: frontend
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: package-lock.json

- name: Cache Playwright browser binaries
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
playwright-browsers-${{ runner.os }}-
- name: Install dependencies
run: npm ci

- name: Build frontend for E2E
run: npm run build
working-directory: frontend

- name: Install Playwright browsers
run: npx playwright install chromium
working-directory: frontend

- name: Run Playwright end-to-end tests
run: npm run test:e2e
working-directory: frontend

- name: Upload Playwright HTML report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-artifacts
path: frontend/playwright-report

backend:
name: Backend CI
runs-on: ubuntu-latest
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/pr-test-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
node-version: '20'
cache: 'npm'
cache-dependency-path: package-lock.json

- name: Cleanup workspace
run: rm -rf node_modules frontend/node_modules backend/node_modules

- name: Install dependencies
run: npm ci --include=optional

Expand Down
79 changes: 41 additions & 38 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Security Checks

on:
push:
branches: [ main, develop ]
branches: [main, develop]
pull_request:
branches: [ main ]
branches: [main]
schedule:
- cron: '0 2 * * 0'

Expand All @@ -14,28 +14,31 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.19.0'
cache: 'npm'

- name: Install dependencies
env:
HUSKY: 0
run: npm ci

- name: Run npm audit (production dependencies)
run: npm audit --omit=dev --audit-level=critical

- name: Check for known vulnerabilities in frontend (production dependencies)
run: npm audit --workspace=frontend --omit=dev --audit-level=critical

- name: Check for known vulnerabilities in backend (production dependencies)
run: npm audit --workspace=backend --omit=dev --audit-level=critical
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.19.0'
cache: 'npm'

- name: Cleanup workspace
run: rm -rf node_modules frontend/node_modules backend/node_modules

- name: Install dependencies
env:
HUSKY: 0
run: npm ci

- name: Run npm audit (production dependencies)
run: npm audit --omit=dev --audit-level=critical

- name: Check for known vulnerabilities in frontend (production dependencies)
run: npm audit --workspace=frontend --omit=dev --audit-level=critical

- name: Check for known vulnerabilities in backend (production dependencies)
run: npm audit --workspace=backend --omit=dev --audit-level=critical

codeql-analysis:
name: CodeQL Analysis
Expand All @@ -48,19 +51,19 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'typescript' ]
language: ['javascript', 'typescript']

steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}

- name: Autobuild
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
3 changes: 3 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# Playwright test artifacts
/playwright-report
35 changes: 35 additions & 0 deletions frontend/e2e/stream-lifecycle.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { test, expect } from '@playwright/test'

test.describe('FlowFi Playwright E2E', () => {
test('connects wallet and navigates to create stream page', async ({
page,
}) => {
await page.goto('/dashboard')

await expect(
page.locator('h2', { hasText: 'Connect a wallet' })
).toBeVisible()

// 1. Click Albedo to safely bypass Freighter extension timeouts in headless CI
await page.getByRole('button', { name: /Connect Albedo/i }).click()

// 2. Specifically target the button element to satisfy Playwright's strict mode
// and click it to open the dropdown menu.
await page.locator('button.wallet-chip').click()

// 3. Now the menu is open and Playwright can verify the disconnect button
await expect(
page.locator('button', { hasText: 'Disconnect Wallet' })
).toBeVisible()

// 4. Proceed with the rest of the flow
await page.getByRole('link', { name: /Create Stream/i }).click()

await expect(
page.locator('h1', { hasText: 'Create New Stream' })
).toBeVisible()
await expect(
page.locator('label', { hasText: 'Recipient Address' })
).toBeVisible()
})
})
6 changes: 5 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"lint": "eslint",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
"test:coverage": "vitest run --coverage",
"test:e2e": "playwright test",
"test:e2e:ci": "playwright test --reporter=html"
},
"dependencies": {
"@stellar/freighter-api": "^6.0.1",
Expand All @@ -24,7 +26,9 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.5",
"@playwright/test": "^1.56.0",
"@tailwindcss/postcss": "^4",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
Expand Down
32 changes: 32 additions & 0 deletions frontend/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './e2e',
timeout: 60_000,
expect: {
timeout: 5_000,
},
reporter: [['html', { open: 'never' }]],
use: {
baseURL: 'http://127.0.0.1:3000',
actionTimeout: 0,
navigationTimeout: 30_000,
trace: 'retain-on-failure',
video: 'retain-on-failure',
},
webServer: {
command: 'npm run start',
cwd: __dirname,
url: 'http://127.0.0.1:3000',
reuseExistingServer: false,
timeout: 120_000,
},
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
],
});
Loading
Loading