feat(js): m11 pong capstone (model, rules, view, app, page) and polling smoke test

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas Winther
2026-10-28 23:59:25 +01:00
co-authored by Claude Sonnet 5.5
parent fd7c5f2acf
commit 1d1d918805
16 changed files with 3090 additions and 3 deletions
+151
View File
@@ -0,0 +1,151 @@
{
"function": "pongKey",
"cases": [
{
"name": "ArrowUp-down-presses-up",
"args": [
true,
"ArrowUp"
],
"expected": {
"tag": "Press",
"key": "Up"
}
},
{
"name": "ArrowUp-up-releases-up",
"args": [
false,
"ArrowUp"
],
"expected": {
"tag": "Release",
"key": "Up"
}
},
{
"name": "w-down-presses-up",
"args": [
true,
"w"
],
"expected": {
"tag": "Press",
"key": "Up"
}
},
{
"name": "w-up-releases-up",
"args": [
false,
"w"
],
"expected": {
"tag": "Release",
"key": "Up"
}
},
{
"name": "ArrowDown-down-presses-down",
"args": [
true,
"ArrowDown"
],
"expected": {
"tag": "Press",
"key": "Down"
}
},
{
"name": "ArrowDown-up-releases-down",
"args": [
false,
"ArrowDown"
],
"expected": {
"tag": "Release",
"key": "Down"
}
},
{
"name": "s-down-presses-down",
"args": [
true,
"s"
],
"expected": {
"tag": "Press",
"key": "Down"
}
},
{
"name": "s-up-releases-down",
"args": [
false,
"s"
],
"expected": {
"tag": "Release",
"key": "Down"
}
},
{
"name": "r-down-restarts",
"args": [
true,
"r"
],
"expected": {
"tag": "Restart"
}
},
{
"name": "r-up-does-nothing",
"args": [
false,
"r"
],
"expected": null
},
{
"name": "other-key-down-is-ignored",
"args": [
true,
"x"
],
"expected": null
},
{
"name": "other-key-up-is-ignored",
"args": [
false,
"x"
],
"expected": null
},
{
"name": "space-is-ignored",
"args": [
true,
" "
],
"expected": null
},
{
"name": "constructor-is-not-a-key",
"args": [
true,
"constructor"
],
"expected": null
},
{
"name": "toString-is-not-a-key",
"args": [
false,
"toString"
],
"expected": null
}
]
}
File diff suppressed because it is too large Load Diff
+325
View File
@@ -0,0 +1,325 @@
{
"function": "pongView",
"cases": [
{
"name": "new-match",
"args": [
{
"ball": {
"x": 40,
"y": 25
},
"vel": {
"dx": 1,
"dy": 1
},
"player": 21,
"cpu": 21,
"held": {
"up": false,
"down": false
},
"score": {
"player": 0,
"cpu": 0
},
"status": "Playing",
"seed": 0,
"frame": 0
}
],
"expected": [
{
"tag": "Rect",
"x": 0,
"y": 0,
"w": 640,
"h": 400,
"color": "#111111"
},
{
"tag": "Rect",
"x": 16,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 616,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 320,
"y": 200,
"w": 8,
"h": 8,
"color": "#ffeb3b"
},
{
"tag": "Text",
"x": 320,
"y": 30,
"text": "0 0",
"color": "#ffffff",
"size": 24,
"align": "center"
}
]
},
{
"name": "paddles-and-ball-move-with-the-state",
"args": [
{
"ball": {
"x": 10,
"y": 5
},
"vel": {
"dx": 1,
"dy": 1
},
"player": 0,
"cpu": 42,
"held": {
"up": false,
"down": false
},
"score": {
"player": 3,
"cpu": 2
},
"status": "Playing",
"seed": 0,
"frame": 0
}
],
"expected": [
{
"tag": "Rect",
"x": 0,
"y": 0,
"w": 640,
"h": 400,
"color": "#111111"
},
{
"tag": "Rect",
"x": 16,
"y": 0,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 616,
"y": 336,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 80,
"y": 40,
"w": 8,
"h": 8,
"color": "#ffeb3b"
},
{
"tag": "Text",
"x": 320,
"y": 30,
"text": "3 2",
"color": "#ffffff",
"size": 24,
"align": "center"
}
]
},
{
"name": "player-wins",
"args": [
{
"ball": {
"x": 40,
"y": 25
},
"vel": {
"dx": 1,
"dy": 1
},
"player": 21,
"cpu": 21,
"held": {
"up": false,
"down": false
},
"score": {
"player": 5,
"cpu": 3
},
"status": "Over",
"seed": 0,
"frame": 0
}
],
"expected": [
{
"tag": "Rect",
"x": 0,
"y": 0,
"w": 640,
"h": 400,
"color": "#111111"
},
{
"tag": "Rect",
"x": 16,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 616,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 320,
"y": 200,
"w": 8,
"h": 8,
"color": "#ffeb3b"
},
{
"tag": "Text",
"x": 320,
"y": 30,
"text": "5 3",
"color": "#ffffff",
"size": 24,
"align": "center"
},
{
"tag": "Text",
"x": 320,
"y": 200,
"text": "You Win!",
"color": "#ffffff",
"size": 32,
"align": "center"
},
{
"tag": "Text",
"x": 320,
"y": 230,
"text": "Press R to restart",
"color": "#ffffff",
"size": 16,
"align": "center"
}
]
},
{
"name": "cpu-wins",
"args": [
{
"ball": {
"x": 40,
"y": 25
},
"vel": {
"dx": 1,
"dy": 1
},
"player": 21,
"cpu": 21,
"held": {
"up": false,
"down": false
},
"score": {
"player": 2,
"cpu": 5
},
"status": "Over",
"seed": 0,
"frame": 0
}
],
"expected": [
{
"tag": "Rect",
"x": 0,
"y": 0,
"w": 640,
"h": 400,
"color": "#111111"
},
{
"tag": "Rect",
"x": 16,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 616,
"y": 168,
"w": 8,
"h": 64,
"color": "#ffffff"
},
{
"tag": "Rect",
"x": 320,
"y": 200,
"w": 8,
"h": 8,
"color": "#ffeb3b"
},
{
"tag": "Text",
"x": 320,
"y": 30,
"text": "2 5",
"color": "#ffffff",
"size": 24,
"align": "center"
},
{
"tag": "Text",
"x": 320,
"y": 200,
"text": "CPU Wins",
"color": "#ffffff",
"size": 32,
"align": "center"
},
{
"tag": "Text",
"x": 320,
"y": 230,
"text": "Press R to restart",
"color": "#ffffff",
"size": 16,
"align": "center"
}
]
}
]
}