Skip to content

Add QTI viewer acceptance test infrastructure#14620

Open
rtibbles wants to merge 5 commits into
learningequality:developfrom
rtibbles:qti_fixture_acceptance_tests
Open

Add QTI viewer acceptance test infrastructure#14620
rtibbles wants to merge 5 commits into
learningequality:developfrom
rtibbles:qti_fixture_acceptance_tests

Conversation

@rtibbles
Copy link
Copy Markdown
Member

Summary

Adds acceptance-test infrastructure for the QTI viewer plugin — renderAssessmentItem harness plus fixture-driven specs for ChoiceInteraction and TextEntryInteraction. Adds fixtures for the remaining QTI interaction types (not yet covered by specs) so future tests can land incrementally.

Fixes a Vue 2 binding quirk in SimpleChoice and ChoiceInteraction where boolean false caused aria-selected and aria-multiselectable to be stripped from the DOM. Completes the intent of #14374 for the initial/unselected and single-cardinality cases — String() coercion keeps the attributes present in both states.

References

Reviewer guidance

Primary purpose of this PR is to establish the acceptance-test harness and spec style — future interaction specs (ExtendedText, Slider, etc.) will follow the smoke-vs-behaviour split used here, so worth confirming that shape is right before it becomes a pattern.

Only manual check needed: open the sandbox QTI viewer, inspect a qti-simple-choice and its ul[role="listbox"], and confirm aria-selected="false" / aria-multiselectable="false" are present on unselected items. ARIA state attributes require an explicit "false" string — they are enumerated, not boolean like HTML disabled/checked, so Vue 2's boolean-attribute handling incorrectly strips them. See Hidde de Vries on boolean attributes in HTML and ARIA.

AI usage

Both passes used Claude Code. First pass generated the initial acceptance-test harness, fixtures, and behavioural specs for ChoiceInteraction and TextEntryInteraction — prompted to establish Vue Testing Library infrastructure and conventions for QTI interaction components, with fixture-driven coverage of each behaviour. Second pass was a cleanup: I asked Claude to audit the branch against develop, which surfaced the Vue 2 boolean-ARIA stripping bug (completing #14374 for the unselected case), a getByRole('listbox') test bug on multi-interaction fixtures, test verbosity (155 cases, much of it redundant across fixtures), and some committed plan docs. I directed each fix, prompted for aggressive pruning after the first refactor pass (155 → 53 cases), and reviewed the absorbed history and final diff via local-review before pushing.

Spec and implementation plan for fixture-driven acceptance tests.
Shared renderAssessmentItem helper that renders AssessmentItem with
parsed fixture XML and mocked injectables (handlers, QTI_CONTEXT,
answerState, interactive).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added DEV: renderers HTML5 apps, videos, exercises, etc. DEV: frontend SIZE: medium labels Apr 19, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 19, 2026

@github-actions github-actions Bot added the DEV: dev-ops Continuous integration & deployment label Apr 19, 2026
Copy link
Copy Markdown
Member Author

@rtibbles rtibbles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of tweaks needed.

rtibbles and others added 4 commits April 21, 2026 11:01
20 behavioral fixtures covering single/multi select, maxChoices
enforcement, orientation, stacking, response processing templates,
shuffle, and SBAC items. Tests selection, deselection, keyboard
interaction, ARIA semantics, and answer state round-tripping.

182 tests total (with TextEntry). 69 fail pending PR learningequality#14374
(role=listbox, aria-multiselectable, maxChoices, shuffle.value).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7 behavioral fixtures covering string/float base types, pattern-mask,
composite (17 inputs), and adaptive items. Tests input type, typing,
answer state round-tripping, external reactivity, and non-interactive
mode.

12 tests fail pending PR learningequality#14374 (aria-label, autocomplete=off).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 5 new fixtures covering interaction types identified in the
1EdTech canonical examples gap analysis:

- associate-interaction-1: pair matching (country to capital)
- slider-interaction-1: numeric slider (boiling point)
- drawing-interaction-1: freehand drawing on image (file response)
- upload-interaction-1: file upload (essay submission)
- upload-composite-1: file upload combined with text entry

These scaffold future component development and acceptance tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JS test fixtures stored via git-lfs (e.g. the QTI items.js fixture bundle)
need to be resolved to their actual content before Jest runs; without
lfs: true on the checkout step the pointer file is parsed as JS and the
suite fails to load.
@rtibbles rtibbles force-pushed the qti_fixture_acceptance_tests branch from 83cc06a to ff2e21a Compare April 21, 2026 18:01
@rtibbles rtibbles marked this pull request as ready for review April 21, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DEV: dev-ops Continuous integration & deployment DEV: frontend DEV: renderers HTML5 apps, videos, exercises, etc. SIZE: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants