Skip to content

Commit de9944d

Browse files
committed
Add automated route and frontend coverage
1 parent 549b93d commit de9944d

File tree

11 files changed

+428
-20
lines changed

11 files changed

+428
-20
lines changed

.forgejo/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ jobs:
3333
run: cargo build
3434

3535
- name: Run tests
36-
run: cargo test
36+
run: |
37+
cargo test
38+
node --test tests/*.test.js
3739
3840
- name: Verify package contents
3941
run: ./scripts/verify-package.sh

.forgejo/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ jobs:
2929
run: cargo build --release
3030

3131
- name: Run tests
32-
run: cargo test
32+
run: |
33+
cargo test
34+
node --test tests/*.test.js
3335
3436
create-release:
3537
name: Create Release

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ jobs:
4747
run: cargo build
4848

4949
- name: Run tests
50-
run: cargo test
50+
run: |
51+
cargo test
52+
node --test tests/*.test.js
5153
5254
- name: Verify package contents
5355
run: ./scripts/verify-package.sh

.github/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ jobs:
4848
run: cargo build --release
4949

5050
- name: Run tests
51-
run: cargo test
51+
run: |
52+
cargo test
53+
node --test tests/*.test.js
5254
5355
create-release:
5456
name: Create GitHub Release

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ include_dir = "0.7"
2424

2525
[dev-dependencies]
2626
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
27-
tower = "0.5"
27+
tower = { version = "0.5", features = ["util"] }

Makefile

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ VERSIONED_CSS := static/sf/sf.$(VERSION).css
2727
VERSIONED_JS := static/sf/sf.$(VERSION).js
2828

2929
# ============== Phony Targets ==============
30-
.PHONY: banner help assets build build-release test test-quick test-doc test-unit test-one \
30+
.PHONY: banner help assets build build-release test test-quick test-doc test-unit test-frontend test-one \
3131
lint fmt fmt-check clippy ci-local pre-release version package-verify \
3232
bump-patch bump-minor bump-major bump-dry demo-serve \
3333
publish-dry publish clean watch
@@ -84,6 +84,7 @@ test: banner
8484
@printf "$(CYAN)$(BOLD)╚══════════════════════════════════════╝$(RESET)\n\n"
8585
@printf "$(ARROW) $(BOLD)Running all tests...$(RESET)\n"
8686
@cargo test && \
87+
node --test tests/*.test.js && \
8788
printf "\n$(GREEN)$(CHECK) All tests passed$(RESET)\n\n" || \
8889
(printf "\n$(RED)$(CROSS) Tests failed$(RESET)\n\n" && exit 1)
8990

@@ -99,6 +100,10 @@ test-quick: banner
99100
@cargo test --lib --quiet && \
100101
printf "$(GREEN)$(CHECK) Unit tests passed$(RESET)\n\n" || \
101102
(printf "$(RED)$(CROSS) Unit tests failed$(RESET)\n\n" && exit 1)
103+
@printf "$(PROGRESS) Running frontend tests...\n"
104+
@node --test tests/*.test.js && \
105+
printf "$(GREEN)$(CHECK) Frontend tests passed$(RESET)\n\n" || \
106+
(printf "$(RED)$(CROSS) Frontend tests failed$(RESET)\n\n" && exit 1)
102107

103108
test-doc:
104109
@printf "$(PROGRESS) Running doctests...\n"
@@ -112,6 +117,12 @@ test-unit:
112117
printf "$(GREEN)$(CHECK) Unit tests passed$(RESET)\n" || \
113118
(printf "$(RED)$(CROSS) Unit tests failed$(RESET)\n" && exit 1)
114119

120+
test-frontend:
121+
@printf "$(PROGRESS) Running frontend tests...\n"
122+
@node --test tests/*.test.js && \
123+
printf "$(GREEN)$(CHECK) Frontend tests passed$(RESET)\n" || \
124+
(printf "$(RED)$(CROSS) Frontend tests failed$(RESET)\n" && exit 1)
125+
115126
test-one:
116127
@printf "$(PROGRESS) Running test: $(YELLOW)$(TEST)$(RESET)\n"
117128
@RUST_LOG=info cargo test $(TEST) -- --nocapture
@@ -155,8 +166,10 @@ ci-local: banner
155166
@$(MAKE) clippy --no-print-directory
156167
@printf "$(PROGRESS) Step 5/6: Doctests...\n"
157168
@cargo test --doc --quiet && printf "$(GREEN)$(CHECK) Doctests passed$(RESET)\n"
158-
@printf "$(PROGRESS) Step 6/6: Unit tests...\n"
169+
@printf "$(PROGRESS) Step 6/7: Unit tests...\n"
159170
@cargo test --lib --quiet && printf "$(GREEN)$(CHECK) Unit tests passed$(RESET)\n"
171+
@printf "$(PROGRESS) Step 7/7: Frontend tests...\n"
172+
@node --test tests/*.test.js && printf "$(GREEN)$(CHECK) Frontend tests passed$(RESET)\n"
160173
@printf "\n$(GREEN)$(BOLD)╔══════════════════════════════════════════════════════════╗$(RESET)\n"
161174
@printf "$(GREEN)$(BOLD)$(CHECK) CI SIMULATION PASSED ║$(RESET)\n"
162175
@printf "$(GREEN)$(BOLD)╚══════════════════════════════════════════════════════════╝$(RESET)\n\n"
@@ -196,7 +209,7 @@ pre-release: banner
196209
@$(MAKE) fmt-check --no-print-directory
197210
@$(MAKE) clippy --no-print-directory
198211
@printf "$(PROGRESS) Running full test suite...\n"
199-
@cargo test --quiet && printf "$(GREEN)$(CHECK) All tests passed$(RESET)\n"
212+
@cargo test --quiet && node --test tests/*.test.js && printf "$(GREEN)$(CHECK) All tests passed$(RESET)\n"
200213
@printf "$(PROGRESS) Dry-run publish...\n"
201214
@cargo publish --dry-run 2>&1 | tail -1
202215
@printf "$(PROGRESS) Verifying packaged contents...\n"
@@ -273,6 +286,7 @@ help: banner
273286
@/bin/echo -e " $(GREEN)make test-quick$(RESET) - Run doctests + unit tests (fast)"
274287
@/bin/echo -e " $(GREEN)make test-doc$(RESET) - Run doctests only"
275288
@/bin/echo -e " $(GREEN)make test-unit$(RESET) - Run unit tests only"
289+
@/bin/echo -e " $(GREEN)make test-frontend$(RESET) - Run frontend Node tests"
276290
@/bin/echo -e " $(GREEN)make test-one TEST=name$(RESET) - Run specific test with output"
277291
@/bin/echo -e ""
278292
@/bin/echo -e "$(CYAN)$(BOLD)Lint & Format:$(RESET)"

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ Every backend element has a corresponding UI element. The library grows
5353
alongside the solver. When you scaffold a new SolverForge project with
5454
`solverforge new`, it's already wired in.
5555

56+
## Testing
57+
58+
Repository coverage now includes the embedded Rust asset routes plus Node-based
59+
frontend tests for backend adapters, solver lifecycle transitions, and core
60+
component rendering. Use `make test` for the full suite, `make test-quick` for
61+
Rust doctests and unit tests plus frontend coverage, or `make test-frontend`
62+
when you only want the JavaScript suite.
63+
5664
## Quick Start
5765

5866
```html

src/lib.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,93 @@ mod tests {
192192

193193
assert_eq!(missing_resp.status(), StatusCode::NOT_FOUND);
194194
}
195+
196+
#[tokio::test]
197+
async fn serves_top_level_assets_with_short_cache_and_expected_mime() {
198+
let response = routes()
199+
.oneshot(
200+
Request::builder()
201+
.uri("/sf/sf.css")
202+
.body(Body::empty())
203+
.unwrap(),
204+
)
205+
.await
206+
.unwrap();
207+
208+
assert_eq!(response.status(), StatusCode::OK);
209+
assert_eq!(
210+
response.headers().get(header::CONTENT_TYPE).unwrap(),
211+
"text/css; charset=utf-8"
212+
);
213+
assert_eq!(
214+
response.headers().get(header::CACHE_CONTROL).unwrap(),
215+
"public, max-age=3600"
216+
);
217+
218+
let body = to_bytes(response.into_body(), usize::MAX).await.unwrap();
219+
let css = String::from_utf8(body.to_vec()).unwrap();
220+
assert!(css.contains("--sf-emerald-50"));
221+
assert!(css.contains(".sf-gantt-split"));
222+
}
223+
224+
#[tokio::test]
225+
async fn serves_immutable_assets_with_long_cache_and_expected_mime() {
226+
let image = routes()
227+
.oneshot(
228+
Request::builder()
229+
.method(Method::GET)
230+
.uri("/sf/img/ouroboros.svg")
231+
.body(Body::empty())
232+
.unwrap(),
233+
)
234+
.await
235+
.unwrap();
236+
237+
assert_eq!(image.status(), StatusCode::OK);
238+
assert_eq!(
239+
image.headers().get(header::CONTENT_TYPE).unwrap(),
240+
"image/svg+xml"
241+
);
242+
assert_eq!(
243+
image.headers().get(header::CACHE_CONTROL).unwrap(),
244+
"public, max-age=31536000, immutable"
245+
);
246+
247+
let vendor = routes()
248+
.oneshot(
249+
Request::builder()
250+
.method(Method::GET)
251+
.uri("/sf/vendor/frappe-gantt/frappe-gantt.min.js")
252+
.body(Body::empty())
253+
.unwrap(),
254+
)
255+
.await
256+
.unwrap();
257+
258+
assert_eq!(vendor.status(), StatusCode::OK);
259+
assert_eq!(
260+
vendor.headers().get(header::CONTENT_TYPE).unwrap(),
261+
"application/javascript; charset=utf-8"
262+
);
263+
assert_eq!(
264+
vendor.headers().get(header::CACHE_CONTROL).unwrap(),
265+
"public, max-age=31536000, immutable"
266+
);
267+
}
268+
269+
#[tokio::test]
270+
async fn returns_not_found_for_missing_assets() {
271+
let response = routes()
272+
.oneshot(
273+
Request::builder()
274+
.method(Method::GET)
275+
.uri("/sf/does-not-exist.js")
276+
.body(Body::empty())
277+
.unwrap(),
278+
)
279+
.await
280+
.unwrap();
281+
282+
assert_eq!(response.status(), StatusCode::NOT_FOUND);
283+
}
195284
}

0 commit comments

Comments
 (0)