ai_word_generator_test.php |
12 |
AI response parsing (words/legacy concepts wrappers, bare list, markdown code fence stripped, malformed/non-array JSON, hint falls back to definition, non-array entries skipped) and untrusted-input term validation (single alphabetic word accepted; empty, multi-word, and non-alphabetic terms rejected) — all via reflection, no real AI call |
attempts_history_service_test.php |
14 |
Own attempt history and current grade: empty with no finished rounds; excludes a still-pending reservation; rows shown most-recent-first while the grade calculation itself uses ascending order; the computed grade matches playerwords_calculate_user_grade() for the configured method; grade summary hidden for an ungraded activity; word text falls back from concept to the raw word; time used formatted as m:ss; the ranking-points column is shown, formatted to 2 decimals, when ranking is enabled, and omitted entirely when it is disabled. All-students report (get_all_history): every student’s finished attempts included with their name attached, most-recent-first by default; excludes anyone who can manage the activity, from both the report rows and the student filter dropdown; the studentid filter restricts to one student’s own rows; sorting only accepts allow-listed columns, falling back to date instead of erroring on an unknown key; pagination returns distinct slices of the full result set |
gameplay_service_test.php |
19 |
Letter feedback algorithm across 9 guess/target combinations (correct, absent, present, duplicate letters, pool exhaustion); score calculation for win, loss, and decimal grades under Binary mode; Linear mode for both the grade and the ranking-points calculation (full marks on both of the first two attempts, scaled proportionally from the third attempt onward, a positive non-zero share on the last allowed attempt, degenerates to full credit on every attempt when max_attempts is 2 or fewer, zero when not completed) |
hud_service_test.php |
22 |
Delegates to block_playerhud’s \block_playerhud\local\external_items API for every item operation, validating ownership against the caller’s own block instance instead of reading block_playerhud’s tables directly: block lookup across courses; whether the block_playerhud plugin itself is installed on the site (matches the real class_exists check); course availability (true with a block instance, false without one, ignores another course’s instance); item name resolution (empty for an item belonging to a different block instance); item list retrieval; consume items (insufficient funds, success, FIFO order, zero-quantity short-circuit, waived — not blocked — for an item belonging to a different block instance); grant items (inventory rows tagged source='playerwords' plus XP awarded, XP withheld when the caller flags the source as unbounded, zero-XP items never change XP either way, unknown item, foreign-instance item, and zero quantity are all no-ops) |
intro_service_test.php |
5 |
The site-wide “seen intro” user preference: false by default; flips true and stays true after marking it seen (idempotent); isolated per user — marking one user never affects another; the preference name is prefixed with the plugin’s Frankenstyle component, the contract both the Privacy Provider and db/uninstall.php’s prefix-based cleanup rely on |
ranking_service_test.php |
6 |
Empty ranking; score-descending ordering; top-5 truncation with an outsider row for a lower-ranked current user; SEPARATEGROUPS filters to the student’s own group; a still-pending reservation (round in progress or abandoned without finishing) is excluded from the ranking; a user who can manage the activity (editingteacher) never appears in the ranking, even with attempts of their own |
round_presenter_test.php |
35 |
Grid row rendering; cooldown text; feedback messages (forfeited/timed out/lost/won, varying by attempts used); ranking context; round result context (blank until finished, reveals on finish, cooldown reflects a later settings change); lobby PlayerHUD balance/cost (shown/hidden by round state, start disabled below the required quantity, enabled once the balance covers it), lobby timer info; round panel hint-button PlayerHUD balance/cost (shown/hidden by reveal state, hint disabled below the required quantity, enabled once the balance covers it), timer stays at zero before the round starts; grade-so-far summary (absent before finished, absent when ungraded, shows method and computed grade once finished, ignores a still-pending attempt); lobby grading-method info line (shown when relevant, hidden for a single-round activity, hidden when ungraded); the keyboard’s Ç key only appears once the activity’s own word pool needs it; rounds-played counter shown in the lobby and in the round result, using the infinity symbol for an unlimited activity and the configured limit otherwise; the PlayerHUD win-grant label is shown only on an actual win with an item configured, blank on a loss or when unconfigured |
round_service_test.php |
30 |
Round state transitions: word picked and round_started fired; guess submission (wrong, correct, out of attempts, after finish, length mismatch); forfeit; timeout (finishes once the deadline has passed, rejected before the deadline, rejected when the timer is disabled); new round; restriction notice (max rounds reached, unrestricted); count_rounds_played scoped to instance and user; cooldown computation (disabled, no attempts yet, expired, reflects a later settings change); recovers by picking a fresh word after the previous one was removed mid-round; start_round reserves an attempt row; finish_round completes the reservation instead of duplicating it; an abandoned round still counts towards max_rounds; the stale reservation is discarded when the word is removed mid-round; a won round grants the configured PlayerHUD item with XP when max_rounds is bounded, grants it without XP when unlimited, and a lost round never grants it; a round or hint cost pointing at a deleted item, or an item belonging to a different course, is waived rather than blocking the student forever; a cost pointing at a merely disabled (not deleted) item still blocks correctly when the balance is short — disabling is reversible, so the cost is never waived for it |
view_page_service_test.php |
16 |
Page-assembly branches: fresh lobby, picked word persists across calls, finished round computes a real cooldown, restriction notice shown when the round limit is reached; the toolbar’s help/attempt-history URLs are always present; the forfeit action is shown only during an active round; the help modal’s ranking tie-break explanation is hidden when the teacher has turned ranking off; the help modal’s PlayerHUD explanation appears as soon as any one of round cost, hint cost, or win grant is configured; the help modal always carries the review hint pointing back to the toolbar icon. Auto-show intro: true on a user’s very first page load of any activity and false from then on — including a different activity, proving the scope is site-wide rather than per-instance — surfaced identically on the fresh-lobby, finished-round, and restriction-notice branches. Word-pool status: whoever can manage the activity sees the active-word count even with no issues at all, and, only when the pool genuinely has one, a named inactive-word warning (outside the length range or containing an invalid character); a student sees neither |
word_normalizer_test.php |
16 |
Accent-insensitive normalisation across 8 diacritic combinations; is_valid_charset accepts letters only (including accented ones) and rejects digits, spaces, hyphens, an apostrophe, and an empty string, across 8 cases |
words_repository_test.php |
56 |
Word picking (empty pool, unapproved/too-short/too-long/non-letter exclusion, random mode, shared-sequence determinism and cycling, avoids the excluded word when an alternative exists, allows it back in when it is the only candidate); get_last_played_word_id (0 with no finished rounds, ignores a pending reservation); manual and AI word insertion; word_exists duplicate check (case-insensitive match, no match, scoped to instance, matches regardless of source, ignores the excluded word id when renaming); word lookup, update and delete scoped to the owning instance; bulk delete and approve; recent-words listing with glossary name join; glossary sync (multi-word concept splitting, configurable stopword filtering, hint update on resync without duplicating, orphan cleanup when an entry disappears, glossaryid = 0 covering every course glossary, skips a concept whose text already belongs to a manual/AI word without touching that word’s hint); the on-screen keyboard’s Ç key is only offered when an approved word actually contains one, scoped to its own activity and ignoring unapproved words. get_fragmented_concepts reports a glossary concept split into several sibling word rows, excludes a single-word concept, ignores manual/AI words even when one coincidentally shares its text with its own concept, and is scoped to its own instance. get_inactive_words is empty when nothing is wrong, reports a word outside the current length range and a word with an invalid character (each tagged with its reason), and ignores unapproved words. get_draw_counts is absent — not zero — for a word never drawn, sums every attempt regardless of outcome, and is scoped to its own instance. count_glossary_candidates (the same preview used before an activity even exists) counts only candidates within the requested range for one glossary; glossaryid = 0 covers every glossary in the course; two concepts tokenising into the same word are only counted once; a glossary id belonging to a different course is never counted, even though the id itself is real; a course with no glossaries at all counts zero without error |
| Subtotal |
231 |
|