Skip to content

Commit e58cc05

Browse files
Basic E2E test
1 parent a670a1c commit e58cc05

11 files changed

Lines changed: 278 additions & 8 deletions

File tree

.github/workflows/e2e.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
on: [ push, pull_request ]
3+
4+
jobs:
5+
e2e:
6+
strategy:
7+
matrix:
8+
os: [ ubuntu-latest, windows-latest, macos-latest ]
9+
runs-on: ${{ matrix.os }}
10+
permissions:
11+
contents: read
12+
steps:
13+
- name: Check out repo
14+
uses: actions/checkout@v4
15+
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v5
18+
with:
19+
enable-cache: true
20+
version: "latest"
21+
22+
- name: Set up Python
23+
run: uv python install 3.14
24+
25+
- name: Install dependencies
26+
run: uv sync
27+
28+
- name: Run tests with pytest
29+
run: uv run pytest

.github/workflows/lint.yaml

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,26 @@ jobs:
77
permissions:
88
contents: read
99
steps:
10-
- uses: actions/checkout@v4
11-
- uses: actions/setup-python@v5
12-
with: { python-version: "3.14" }
13-
- uses: astral-sh/setup-uv@v5
14-
- run: uv sync
15-
- run: uv run ruff check .
16-
- run: uv run ruff format --check .
17-
- run: uv run mypy .
10+
- name: Check out repo
11+
uses: actions/checkout@v4
12+
13+
- name: Install uv
14+
uses: astral-sh/setup-uv@v5
15+
with:
16+
enable-cache: true
17+
version: "latest"
18+
19+
- name: Set up Python
20+
run: uv python install 3.14
21+
22+
- name: Install dependencies
23+
run: uv sync
24+
25+
- name: Run ruff linter check
26+
run: uv run ruff check .
27+
28+
- name: Run ruff format check
29+
run: uv run ruff format --check .
30+
31+
- name: Run mypy check
32+
run: uv run mypy .

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ packages = ["src/mkcd2app"]
2828
dev = [
2929
"mypy>=2.3.0",
3030
"pre-commit>=4.6.1",
31+
"pytest>=9.1.1",
32+
"pytest-timeout>=2.4.0",
3133
"ruff>=0.16.0",
3234
"types-pyyaml>=6.0.12.20260724",
3335
]

tests/e2e/test_statics.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import shutil
2+
import subprocess
3+
import time
4+
from collections.abc import Generator
5+
from pathlib import Path
6+
7+
import pytest
8+
9+
10+
def run_build(config_path: Path) -> subprocess.CompletedProcess[str]:
11+
return subprocess.run(
12+
["mkcd2app", "build", str(config_path)],
13+
capture_output=True,
14+
text=True,
15+
timeout=300,
16+
check=True,
17+
)
18+
19+
20+
def run_empty_game_build() -> subprocess.CompletedProcess[str]:
21+
yaml_path = Path.cwd() / "tests" / "fixtures" / "empty_game_build_to_statics.yaml"
22+
return run_build(yaml_path)
23+
24+
25+
@pytest.fixture(scope="module")
26+
def empty_game_build_to_statics() -> Generator[None]:
27+
run_empty_game_build()
28+
29+
yield
30+
31+
dir_path = Path.cwd() / "examples" / "testing" / "empty_game_build"
32+
shutil.rmtree(dir_path)
33+
34+
35+
def test_empty_game_build_to_statics_static(empty_game_build_to_statics: None) -> None:
36+
build_dir = Path("examples/testing/empty_game_build")
37+
static_dist = build_dir / "empty-game-website-filled-built" / "dist"
38+
39+
# check for index.html and assets dir
40+
assert (static_dist / "index.html").is_file(), "expected index.html file present"
41+
assert (static_dist / "assets").is_dir(), "expected assets directory present"
42+
# ensure nonzero amount of css and js files
43+
css_files = list((static_dist / "assets").glob("*.css"))
44+
js_files = list((static_dist / "assets").glob("*.js"))
45+
assert css_files, "expected css files present"
46+
assert js_files, "expected js files present"
47+
48+
49+
def test_empty_game_build_to_statics_static_singlefile(
50+
empty_game_build_to_statics: None,
51+
) -> None:
52+
build_dir = Path("examples/testing/empty_game_build")
53+
static_singlefile_dist = (
54+
build_dir / "empty-game-website-filled-singlefile-built" / "dist"
55+
)
56+
57+
# ensure no other files or directories are present in the dist
58+
items = list(static_singlefile_dist.iterdir())
59+
assert len(items) == 1, (
60+
f"expected only index.html in {static_singlefile_dist}, found: {[p.name for p in items]}"
61+
)
62+
only = items[0]
63+
assert only.is_file(), "expected only index.html present"
64+
assert only.name == "index.html", "expected only index.html present"
65+
66+
67+
def test_empty_game_build_to_statics_second_build_caches(
68+
empty_game_build_to_statics: None,
69+
) -> None:
70+
start_time = time.monotonic()
71+
run_empty_game_build() # this should do nothing file wise, all hit caches
72+
end_time = time.monotonic()
73+
elapsed_time = end_time - start_time
74+
75+
assert elapsed_time < 5, (
76+
f"expected second build to all hit cache and take less than 5s, took {elapsed_time}s"
77+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

tests/fixtures/empty_game/assets.json

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<xml xmlns="https://developers.google.com/blockly/xml"><variables></variables><block type="pxt-on-start" x="0" y="0"></block></xml>

tests/fixtures/empty_game/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

tests/fixtures/empty_game/pxt.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "test",
3+
"description": "",
4+
"dependencies": {
5+
"device": "*"
6+
},
7+
"files": [
8+
"main.blocks",
9+
"main.ts",
10+
"README.md",
11+
"assets.json"
12+
],
13+
"targetVersions": {
14+
"branch": "stable4.0",
15+
"tag": "v4.0.14",
16+
"commits": "https://github.com/microsoft/pxt-arcade/commits/a33ec9537bc6c5fada2a3b02aac57a4bc9a10803",
17+
"target": "4.0.14",
18+
"pxt": "12.2.34"
19+
},
20+
"preferredEditor": "blocksprj"
21+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Example configuration file for MakeCode Arcade to App to compile to static
2+
# HTML, CSS, and JS files
3+
4+
# Config version (single number, incremented if breaking change to schema is
5+
# made)
6+
version: 1
7+
8+
project:
9+
name: Empty Game
10+
path_friendly_name: empty-game
11+
description: "Empty game used for E2E testing"
12+
author: Cyrus Yiu
13+
version: 0.0.1
14+
# This is what the window title will be
15+
# This will also be used for the executable file name for Electron outputs
16+
# You can use {NAME} or {VERSION} or {AUTHOR} to substitute the correct
17+
# values
18+
title: "{NAME} v{VERSION}"
19+
20+
inputs:
21+
# Can be share_link, github, or path
22+
code:
23+
type: path
24+
value: "tests/fixtures/empty_game"
25+
26+
assets: {}
27+
# Icon is optional but highly recommended, it will be used as the favicon
28+
# and app icon
29+
# icon:
30+
# Can be url or path
31+
# type: url
32+
# value: https://raw.githubusercontent.com/UnsignedArduino/MakeCode-Arcade-to-App/refs/heads/main/examples/Racers%20icon.png
33+
34+
# icon:
35+
# type: path
36+
# value: "./examples/Racers icon.png"
37+
38+
# Path where the build process will take place
39+
build_dir: "./examples/testing/empty_game_build"
40+
41+
# You can have multiple outputs
42+
# Currently available options are static, static-singlefile, electron, and
43+
# tauri
44+
outputs:
45+
- type: static
46+
- type: static-singlefile
47+
# - type: electron
48+
# window:
49+
# width: 640
50+
# height: 480
51+
# - type: tauri
52+
# identifier: com.unsignedarduino.racers
53+
# window:
54+
# width: 640
55+
# height: 480

0 commit comments

Comments
 (0)