karma-web: static HTML karma board served at karma.devtronic.pro
All checks were successful
ci / check (push) Successful in 43s

This commit is contained in:
Jean Chevronnet 2026-07-29 23:27:39 +00:00
parent e801b04d6e
commit 9a3393153a
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
6 changed files with 339 additions and 1 deletions

60
tests/karma_web.rs Normal file
View file

@ -0,0 +1,60 @@
use rustbot::karma_web::{parse_board, render};
#[test]
fn parses_flat_number_format() {
let b = parse_board("libera", r#"{"romaka":2}"#);
assert_eq!(b.rows.len(), 1);
assert_eq!(b.rows[0].thing, "romaka");
assert_eq!(b.rows[0].count, 2);
assert!(b.rows[0].reason.is_none());
}
#[test]
fn parses_object_format_with_reason_and_by() {
let b = parse_board("t", r#"{"rust":{"n":5,"why":"clean PR","by":"alice"}}"#);
assert_eq!(b.rows[0].count, 5);
assert_eq!(b.rows[0].reason.as_deref(), Some("clean PR"));
assert_eq!(b.rows[0].by.as_deref(), Some("alice"));
}
#[test]
fn sorts_descending_by_count() {
let b = parse_board("t", r#"{"a":1,"b":9,"c":-3}"#);
let order: Vec<&str> = b.rows.iter().map(|r| r.thing.as_str()).collect();
assert_eq!(order, vec!["b", "a", "c"]);
}
#[test]
fn renders_scores_and_reason() {
let b = parse_board(
"libera",
r#"{"rust":{"n":5,"why":"clean PR","by":"alice"}}"#,
);
let html = render(&[b], 0);
assert!(html.contains("libera"), "{html}");
assert!(html.contains(">rust<"), "{html}");
assert!(html.contains(">+5<"), "{html}");
assert!(html.contains("clean PR"), "{html}");
assert!(html.contains("alice"), "{html}");
}
#[test]
fn escapes_untrusted_irc_input() {
let b = parse_board(
"t",
r#"{"<script>":{"n":1,"why":"\"><img src=x>","by":"a&b"}}"#,
);
let html = render(&[b], 0);
// the page legitimately has its own <script> block; what matters is that the
// untrusted nick/reason are escaped and never emit a live tag of their own.
assert!(!html.contains("<img"), "raw img tag leaked: {html}");
assert!(html.contains("&lt;script&gt;"), "{html}");
assert!(html.contains("a&amp;b"), "{html}");
}
#[test]
fn empty_shows_instructions() {
let html = render(&[], 0);
assert!(html.contains("no karma yet"), "{html}");
assert!(html.contains("nick++"), "{html}");
}