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
192 changes: 192 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
name: Test Suite

on:
push:
branches: [stage, master]
pull_request:
branches: [stage]

env:
NODE_VERSION: '20'

jobs:
# Build job - creates artifact for E2E tests
build:
name: Build
runs-on: ubuntu-latest

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build application
run: yarn build

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: build-dist
path: dist/
retention-days: 1

# Unit and Component Tests with Vitest (runs in parallel with build)
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Run unit tests with coverage
run: yarn test:coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
flags: unit-tests
name: unit-tests-coverage
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 30

# E2E Tests with Playwright - parallelized by browser
e2e-tests:
name: E2E Tests (${{ matrix.browser }})
runs-on: ubuntu-latest
needs: build

strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Install Playwright browser
run: npx playwright install --with-deps ${{ matrix.browser }}

- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build-dist
path: dist/

- name: Run E2E tests
run: npx playwright test tests/e2e/ --project=${{ matrix.browser }}

- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-${{ matrix.browser }}
path: playwright-report/
retention-days: 30

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.browser }}
path: test-results/
retention-days: 30

# Accessibility Tests
a11y-tests:
name: Accessibility Tests
runs-on: ubuntu-latest
needs: build

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build-dist
path: dist/

- name: Run accessibility tests
run: npx playwright test tests/a11y/ --project=chromium --workers=4

- name: Upload a11y report
uses: actions/upload-artifact@v4
if: always()
with:
name: a11y-report
path: playwright-report/
retention-days: 30

# Summary job to ensure all tests pass
test-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [unit-tests, e2e-tests, a11y-tests]
if: always()

steps:
- name: Check test results
run: |
if [[ "${{ needs.unit-tests.result }}" != "success" ]]; then
echo "Unit tests failed"
exit 1
fi
if [[ "${{ needs.e2e-tests.result }}" != "success" ]]; then
echo "E2E tests failed"
exit 1
fi
if [[ "${{ needs.a11y-tests.result }}" != "success" ]]; then
echo "Accessibility tests failed"
exit 1
fi
echo "All tests passed!"
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ coverage
/cypress/videos/
/cypress/screenshots/

# Playwright
/playwright-report/
/test-results/
/playwright/.cache/

# Serena MCP
.serena/

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand All @@ -26,3 +34,4 @@ coverage
*.njsproj
*.sln
*.sw?
.serena/
65 changes: 65 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Development
yarn dev # Start dev server
yarn build # Production build
yarn build --mode stage # Stage build

# Package management (use yarn, not npm)
yarn install
```

No linting, formatting, or test scripts are configured.

## Architecture

### Multi-Site Single Codebase

This Vue 3 application serves multiple sites from one codebase, determined by hostname at runtime:

| Site | Hostname Pattern | App Component | Routes |
|------|------------------|---------------|--------|
| Main Sabbath School | default | `App.vue` | `routes` |
| ABSG | `VITE_APP_SSPM_ABSG_HOST` | `ABSGApp.vue` | `absgroutes` |
| InVerse | `VITE_APP_SSPM_INVERSE_HOST` | `InVerseApp.vue` | `inverseroutes` |
| AIJ Babies/Beginner | `VITE_APP_AIJ_*_HOST` | `App.vue` (with AIJ headers) | `routes` |

Site detection happens in `src/main.js` (app selection) and `src/router/index.js` (route selection).

### API Layer

Four Axios instances in `src/main.js`:
- `$api` / `$apiResources` - Unauthenticated requests
- `$apiAuth` / `$apiAuthResources` - Authenticated with `x-ss-auth-access-token` header

Auth interceptors automatically refresh tokens on 401 responses via `/auth/refresh`.

### Key Patterns

**Vue Composition API**: All components use `<script setup>` syntax with Vue 3 Composition API.

**Pinia Stores**: State management with persisted state (`pinia-plugin-persistedstate`). Stores in `src/stores/`.

**Resource Blocks**: Content rendered via modular block components in `src/components/Resources/Blocks/`. The `Block.vue` wrapper handles dynamic block type rendering.

**Theme System**: TailwindCSS variants (`theme-light`, `theme-sepia`, `theme-dark`) controlled via `.theme.theme--{variant}` parent class.

**RTL Support**: Automatic RTL direction for Arabic (`ar`), Persian (`fa`), Hebrew (`he`) based on language store.

### Directory Layout

- `src/views/` - Route-level views, with `ABSG/` and `InVerse/` subdirectories for site-specific views
- `src/components/` - Shared components, with site-specific subdirectories
- `src/plugins/` - Vue plugins: Bible (verse lookup), Highlighter (text annotation), ContextMenu

## Deployment

- **stage branch** → `sabbath-school-stage.adventech.io` (uses `.env.stage`)
- **master branch** → `sabbath-school.adventech.io` (uses `.env.production`)

Builds deploy to S3 with CloudFront invalidation.
Loading