mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-13 03:10:49 +01:00
Moves the standalone React 19 + Vite 8 + TypeScript 6 game from ~/Downloads/reverse/reverse-survivors into reverse_survivors/, so it is version-controlled, indexed, and covered by CI instead of sitting untracked outside any repository. - Relocates the project's nested .github/workflows/ci.yml to the repository root as .github/workflows/reverse-survivors-ci.yml. GitHub only reads workflows from the root, so the nested copy would have been inert — same treatment billsplit received. The workflow is path-scoped to reverse_survivors/** and runs npm ci / check / build on Node 22. - Sets cache-dependency-path on actions/setup-node, since defaults.run.working-directory applies only to run: steps and not to actions; without it the npm cache looks for a lockfile at the root. - Keeps npm and the existing package-lock.json. TypeScript stays pinned at 6.0.3 deliberately: typescript-eslint 8.65 caps its peer range at <6.1.0 and TS 7 drops the JS compiler API that typed linting needs. - Adds a reverse_survivors/ row to the Repository Layout table in README.md and CLAUDE.md. Verified in place: npm ci, npm run check (95 tests, 100% statements / branches / functions / lines), npm run build, and a dev-server smoke check serving /src/main.tsx. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { createInitialState, makeEnemy } from '../core/sim'
|
|
import type { GameState } from '../core/types'
|
|
import { makeCtxStub } from '../test/harness'
|
|
import { draw } from './draw'
|
|
|
|
const fresh = (): GameState => createInitialState(1)
|
|
|
|
// Empty state baseline: ritual circle + survivor halo + body + hp ring.
|
|
const BASE = { beginPath: 4, arc: 4, fill: 2, stroke: 2, fillRect: 1 }
|
|
|
|
describe('draw', () => {
|
|
it('paints the empty arena baseline', () => {
|
|
const ctx = makeCtxStub()
|
|
draw(ctx, fresh())
|
|
expect(ctx.fillRect).toHaveBeenCalledTimes(BASE.fillRect)
|
|
expect(ctx.beginPath).toHaveBeenCalledTimes(BASE.beginPath)
|
|
expect(ctx.arc).toHaveBeenCalledTimes(BASE.arc)
|
|
expect(ctx.fill).toHaveBeenCalledTimes(BASE.fill)
|
|
expect(ctx.stroke).toHaveBeenCalledTimes(BASE.stroke)
|
|
})
|
|
|
|
it('paints projectiles from both sides', () => {
|
|
const ctx = makeCtxStub()
|
|
const s = fresh()
|
|
s.projectiles.push(
|
|
{ id: 1, from: 'survivor', pos: { x: 10, y: 10 }, vel: { x: 0, y: 0 }, radius: 4, damage: 1, ttl: 1 },
|
|
{ id: 2, from: 'enemy', pos: { x: 20, y: 20 }, vel: { x: 0, y: 0 }, radius: 5, damage: 1, ttl: 1 },
|
|
)
|
|
draw(ctx, s)
|
|
expect(ctx.fill).toHaveBeenCalledTimes(BASE.fill + 2)
|
|
expect(ctx.arc).toHaveBeenCalledTimes(BASE.arc + 2)
|
|
})
|
|
|
|
it('a fresh grunt gets a body but no ring and no hp arc', () => {
|
|
const ctx = makeCtxStub()
|
|
const s = fresh()
|
|
makeEnemy(s, 'rusher', { x: 100, y: 100 })
|
|
draw(ctx, s)
|
|
expect(ctx.fill).toHaveBeenCalledTimes(BASE.fill + 1)
|
|
expect(ctx.stroke).toHaveBeenCalledTimes(BASE.stroke)
|
|
})
|
|
|
|
it('a damaged enemy shows an hp arc', () => {
|
|
const ctx = makeCtxStub()
|
|
const s = fresh()
|
|
const tank = makeEnemy(s, 'tank', { x: 100, y: 100 })
|
|
tank.hp = 60
|
|
draw(ctx, s)
|
|
expect(ctx.fill).toHaveBeenCalledTimes(BASE.fill + 1)
|
|
expect(ctx.stroke).toHaveBeenCalledTimes(BASE.stroke + 1)
|
|
})
|
|
|
|
it('bosses wear a blood ring', () => {
|
|
const ctx = makeCtxStub()
|
|
const s = fresh()
|
|
makeEnemy(s, 'colossus', { x: 100, y: 100 })
|
|
draw(ctx, s)
|
|
expect(ctx.fill).toHaveBeenCalledTimes(BASE.fill + 1)
|
|
expect(ctx.stroke).toHaveBeenCalledTimes(BASE.stroke + 1)
|
|
expect(ctx.arc).toHaveBeenCalledTimes(BASE.arc + 2)
|
|
})
|
|
})
|