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
16 changes: 16 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"permissions": {
"allow": [
"Bash(npm test:*)",
"Bash(npm run test:coverage:*)",
"Bash(npx eslint:*)",
"Bash(npm run lint)",
"Bash(grep:*)",
"Bash(npm run lint:*)",
"Bash(ls:*)",
"Bash(find:*)",
"Bash(npm run test:*)"
],
"deny": []
}
}
39 changes: 32 additions & 7 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ on:
branches: [ "main" ]

jobs:
build:

test:
name: Test & Coverage
runs-on: ubuntu-latest

strategy:
Expand All @@ -20,12 +20,37 @@ jobs:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

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

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v4.0.1
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test

- name: Install dependencies
run: npm ci

- name: Run linting
run: npm run lint

- name: Run TypeScript check
run: npx tsc --noEmit

- name: Run tests with coverage
run: npm run test:coverage

- name: Upload coverage to GitHub
uses: actions/upload-artifact@v4.3.1
if: success() || failure()
with:
name: coverage-report
path: coverage/

- name: Comment coverage on PR
if: github.event_name == 'pull_request'
uses: romeovs/lcov-reporter-action@v0.3.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lcov-file: ./coverage/lcov.info
54 changes: 54 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Workflow for all pull requests and feature branches
# Runs lighter checks for faster feedback on development branches

name: PR Checks

on:
pull_request:
branches: [ "*" ]
push:
branches-ignore: [ "main", "beta" ]

jobs:
lint-and-test:
name: Lint & Test
runs-on: ubuntu-latest

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

- name: Use Node.js 18.x
uses: actions/setup-node@v4.0.1
with:
node-version: 18.x
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linting
run: npm run lint

- name: Run TypeScript check
run: npx tsc --noEmit

- name: Run tests
run: npm test

- name: Check coverage thresholds
run: npm run test:coverage
continue-on-error: true

- name: Generate coverage summary
if: always()
run: |
if [ -f coverage/coverage-summary.json ]; then
echo "## Test Coverage Summary" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Percentage |" >> $GITHUB_STEP_SUMMARY
echo "|--------|------------|" >> $GITHUB_STEP_SUMMARY
echo "| Statements | $(cat coverage/coverage-summary.json | jq -r '.total.statements.pct')% |" >> $GITHUB_STEP_SUMMARY
echo "| Branches | $(cat coverage/coverage-summary.json | jq -r '.total.branches.pct')% |" >> $GITHUB_STEP_SUMMARY
echo "| Functions | $(cat coverage/coverage-summary.json | jq -r '.total.functions.pct')% |" >> $GITHUB_STEP_SUMMARY
echo "| Lines | $(cat coverage/coverage-summary.json | jq -r '.total.lines.pct')% |" >> $GITHUB_STEP_SUMMARY
fi
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,7 @@ yarn-error.*
# typescript
*.tsbuildinfo

# test coverage
coverage/

# @end expo-cli
115 changes: 115 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# CLAUDE.md

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

## Project Overview

ScorePad with Rounds is a React Native app built with Expo SDK 52 for tracking game scores with round-by-round history. The app is cross-platform (iOS, Android, Web) and uses TypeScript throughout.

## Development Commands

### Setup

```bash
nvm use # Use correct Node version
npx react-native-clean-project # Clean project if needed
npx expo prebuild # Generate native code
```

### Development

```bash
npm run dev # Start development server with APP_VARIANT=development
npm start # Standard expo start with dev client
npm run android # Run on Android
npm run ios # Run on iOS
```

### Testing and Linting

```bash
npm run test # Run all tests with Jest
npm run test:watch # Run tests in watch mode
npm run lint # Run ESLint and TypeScript checks
```

### Building

```bash
# Development builds
npx eas build --profile development-simulator --platform ios --local
npx eas build --profile development-simulator --platform android --local

# Preview builds
npx eas build --platform ios --profile preview --local
npx eas build --platform android --profile preview --local

# Production builds (remember to bump version in app.config.js)
npx expo-doctor
npx expo prebuild
npx eas build --platform ios
npx eas build --platform android
```

## Architecture

### State Management

- **Redux Toolkit** with RTK Query for state management
- **Redux Persist** for data persistence with platform-specific storage:
- iOS: iCloud storage via custom `iCloudStorage` utility
- Android/Web: AsyncStorage
- Three main slices:
- `GamesSlice`: Game entities with rounds, players, and metadata
- `PlayersSlice`: Player entities with scores per round
- `SettingsSlice`: App settings and preferences

### Navigation

- **React Navigation v6** with native stack navigator
- Main screens: List (Home), Game, Settings, Share, EditPlayer, Onboarding, AppInfo
- Custom headers for each screen using dedicated header components

### Key Components Structure

- `src/components/`: Reusable UI components organized by feature
- `PlayerTiles/AdditionTile/`: Complex score display with animations
- `Sheets/`: Bottom sheet modals with context providers
- `Headers/`: Custom navigation headers
- `Interactions/`: Touch interaction handling (HalfTap, Swipe)
- `src/screens/`: Main screen components
- `redux/`: State management with typed hooks and selectors

### Platform-Specific Features

- App variants for development/preview/production with different bundle IDs
- Firebase Analytics and Crashlytics integration
- iCloud document storage on iOS
- Gesture handling with react-native-gesture-handler and react-native-reanimated

### Testing

- Jest with React Native Testing Library
- Custom mocks for Firebase, AsyncStorage, and react-native-video
- Test files co-located with source files using `.test.ts(x)` suffix

## Code Style

- ESLint with TypeScript rules, import ordering, and Prettier integration
- Single quotes, semicolons required
- Alphabetical import ordering with React imports first
- No disabled tests, imports organized by type (builtin, external, internal, etc.)

## Firebase Integration

- Analytics can be disabled via `EXPO_PUBLIC_FIREBASE_ANALYTICS=false`
- Debug mode available with simulator flags:
- Analytics: `-FIRAnalyticsDebugEnabled`
- Crashlytics: `-FIRDebugEnabled`

## Development Notes

- Use `npx expo start --dev-client` for development with React DevTools
- Android development requires JDK 17
- Version bumping required in `app.config.js` for production builds
- EAS CLI used for building and submitting to stores
84 changes: 81 additions & 3 deletions Contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ Use a development build from above, then: `npx expo start --dev-client`

## Publish

Apple: `eas submit -p ios` or `eas submit -p ios --non-interactive`
Apple: `npx eas submit -p ios` or `npx eas submit -p ios --non-interactive`

Android: `eas submit -p android --changes-not-sent-for-review`
Android: `npx eas submit -p android --changes-not-sent-for-review`

## Debug

Expand All @@ -81,4 +81,82 @@ Then use the dev client to launch React Dev Tools or debug JS remotely.

### EAS

Debug eas config settings: `eas config --platform=ios --profile=development`
Debug eas config settings: `npx eas config --platform=ios --profile=development`

## Testing

### Run Tests

```zsh
# Run tests once
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test -- --watch
```

### Coverage Requirements

- **Statements**: 24% minimum
- **Branches**: 18% minimum
- **Functions**: 20% minimum
- **Lines**: 25% minimum

Coverage reports are generated in the `coverage/` directory and include:
- Text summary (console output)
- HTML report (`coverage/lcov-report/index.html`)
- LCOV format for CI integration

### Writing Tests

- Use React Native Testing Library for component tests
- Mock external dependencies (react-native-reanimated, navigation, etc.)
- Follow existing test patterns in the codebase
- Ensure tests are deterministic and don't rely on timers

## Code Quality

### Linting

```zsh
# Run ESLint and TypeScript checks
npm run lint

# Auto-fix linting issues where possible
npx eslint . --fix
```

### CI/CD

The project uses GitHub Actions for continuous integration:

#### Main Workflow (`node.yml`)
- Runs on push to `main` and all pull requests to `main`
- Executes linting, TypeScript checks, and full test suite with coverage
- Uploads coverage reports as GitHub artifacts
- Posts coverage summaries on pull requests

#### PR Checks (`pr-checks.yml`)
- Runs on all feature branches and pull requests
- Provides faster feedback with basic linting and testing
- Shows coverage summary in GitHub Actions summary

#### Quality Gates
- All tests must pass
- Code must pass ESLint rules
- TypeScript compilation must succeed
- Coverage thresholds must be met
- No merge to main without passing CI

### Pre-commit Checklist

Before creating a pull request:

1. Run `npm run lint` and fix any issues
2. Run `npm run test:coverage` and ensure all tests pass
3. Verify coverage hasn't decreased significantly
4. Test the app functionality manually
5. Update tests for any new features or bug fixes
25 changes: 24 additions & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,30 @@ const config: Config = {
],
moduleNameMapper: {
'^react-native-video$': '__mocks__/react-native-video.js'
}
},
collectCoverage: true,
coverageDirectory: 'coverage',
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'redux/**/*.{ts,tsx}',
'!src/**/*.test.{ts,tsx}',
'!redux/**/*.test.{ts,tsx}',
'!src/**/*.d.ts',
'!src/**/index.{ts,tsx}',
'!coverage/**',
'!node_modules/**',
'!**/__mocks__/**',
'!**/vendor/**',
],
coverageReporters: ['text', 'lcov', 'html', 'json-summary'],
coverageThreshold: {
global: {
branches: 18,
functions: 20,
lines: 25,
statements: 24,
},
},
};

export default config;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"dev": "APP_VARIANT=development expo start",
"lint": "eslint . ; tsc",
"test": "jest --silent",
"test:watch": "jest --watch"
"test:watch": "jest --watch",
"test:coverage": "jest --coverage --silent",
"test:coverage-summary": "jest --coverage --coverageReporters=text-summary --silent"
},
"dependencies": {
"@babel/plugin-transform-react-jsx": "^7.22.5",
Expand Down
Loading
Loading