Skip to content

Commit

Permalink
Adds assistive alert mock and test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
cayb0rg committed Aug 9, 2023
1 parent 2d4bd20 commit fc50e70
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 29 deletions.
30 changes: 15 additions & 15 deletions src/controllers/ctl-player.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ export const shuffleArray = array => {
return array
}

// helper function to update the aria-live status region
// angular binding does not cooperate well with aria-live, so we update the DOM element directly instead
export const assistiveAlert = ($scope, alert) => {
document.getElementById('assistive-alert').innerText = alert
}

export const getAllAnswerChoices = ($sce, _qset) => {
const answers = []
_qset.items.forEach(item => {
Expand Down Expand Up @@ -67,7 +61,8 @@ export const onMateriaStart = ($scope, $sce, instance, qset, version) => {
$scope.choices = getAllAnswerChoices($sce, _qset)
$scope.questionCount = _qset.items.length

$scope.questionsRemainingText = ($scope.questionCount - $scope.question.current - 1) + " questions remaining. Now on question " + ($scope.question.current + 2) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current + 1].questions[0].text
if ($scope.questionCount > 0)
$scope.questionsRemainingText = ($scope.questionCount - $scope.question.current - 1) + " questions remaining. Now on question " + ($scope.question.current + 2) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current + 1].questions[0].text

showNextQuestion($scope)
}
Expand Down Expand Up @@ -119,13 +114,13 @@ export const checkChoice = ($scope, value) => {
case 0:
$scope.question.correct[value] = 'Incorrect'
$scope.answers[value].options.feedback = _feedback || (curItem.options && curItem.options.feedback ? curItem.options.feedback : '')
assistiveAlert($scope, "Your selection was incorrect. " + _feedback)
$scope.assistiveAlert("Your selection was incorrect. " + _feedback)
break

case 100:
$scope.question.correct[value] = 'Correct!'
$scope.answers[value].options.feedback = _feedback || ''
assistiveAlert($scope, "Your selection was correct. " + _feedback)
$scope.assistiveAlert("Your selection was correct. " + _feedback)
break
}

Expand Down Expand Up @@ -175,7 +170,7 @@ export const closeIntro = ($scope, $timeout) => {
// make splash modal aria-hidden and focus status indicator
$scope.focusStatusButton = true
$timeout(() => {
assistiveAlert($scope, "Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current].questions[0].text)
$scope.assistiveAlert("Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current].questions[0].text)
// set this to false so we can trigger it in nextClicked
$scope.focusStatusButton = false
}, 1200)
Expand All @@ -185,7 +180,6 @@ export const toggleInstructions = $scope => {
$scope.instructionsOpen = !$scope.instructionsOpen

if (!$scope.instructionsOpen && $scope.prevFocus) {
console.log($scope.prevFocus)
$scope.prevFocus.focus()
$scope.prevFocus = null
}
Expand Down Expand Up @@ -246,13 +240,13 @@ export const ControllerThisOrThatPlayer = function($scope, $timeout, $sce) {
// Open the lightbox
if (val == 0 || val == 1)
{
assistiveAlert($scope, "Viewing image.")
$scope.assistiveAlert("Viewing image.")
$scope.lightboxTarget = val
}
// Close the lightbox
else
{
assistiveAlert($scope, "Closed image viewer.")
$scope.assistiveAlert("Closed image viewer.")
// If image for "this" option is currently open, focus "this" option's expand image button
if ($scope.lightboxTarget == 0)
{
Expand Down Expand Up @@ -295,11 +289,11 @@ export const ControllerThisOrThatPlayer = function($scope, $timeout, $sce) {
else if (event.key == 'q' || event.key == 'Q') {
if (!$scope.pressedQOnce)
{
assistiveAlert($scope, "Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current].questions[0].text)
$scope.assistiveAlert("Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ": " + _qset.items[$scope.question.current].questions[0].text)
$scope.pressedQOnce = true
}
else {
assistiveAlert($scope, "Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ":: " + _qset.items[$scope.question.current].questions[0].text)
$scope.assistiveAlert("Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ":: " + _qset.items[$scope.question.current].questions[0].text)
$scope.pressedQOnce = false
}
} else if (event.key == 'H' || event.key == 'h') {
Expand All @@ -326,5 +320,11 @@ export const ControllerThisOrThatPlayer = function($scope, $timeout, $sce) {
}
}

// helper function to update the aria-live status region
// angular binding does not cooperate well with aria-live, so we update the DOM element directly instead
$scope.assistiveAlert = (alert) => {
document.getElementById('assistive-alert').innerText = alert
}

Materia.Engine.start({ start: onMateriaStart.bind(null, $scope, $sce) })
}
39 changes: 25 additions & 14 deletions src/player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ describe('Player Controller', function() {
qset = widgetInfo.qset

require('./player')
const player = require('./controllers/ctl-player')
// load the required code
angular.mock.module('ThisOrThatEngine')
angular.module('ngAnimate', [])
Expand All @@ -70,9 +69,7 @@ describe('Player Controller', function() {

// mock scope
$scope = {
$apply: jest.fn(),
// mock assistive alert
assistiveAlert: jest.fn()
$apply: jest.fn()
}

// use angular mock to access angular modules
Expand Down Expand Up @@ -134,6 +131,7 @@ describe('Player Controller', function() {
expect($scope.gameState).toEqual(gameState)
$scope.closeIntro()
gameState.ingame = true
expect($scope.focusStatusButton).toBe(true)
expect($scope.gameState).toEqual(gameState)
})

Expand All @@ -149,6 +147,7 @@ describe('Player Controller', function() {

test('should check a "correct" answer choice', () => {
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

/*
answer choices are randomized, so to ensure
Expand All @@ -159,6 +158,7 @@ describe('Player Controller', function() {
$scope.checkChoice(0)

expect($scope.question.correct[0]).toEqual('Correct!')
expect($scope.assistiveAlert).toHaveBeenCalled()

expect($scope.question.selected).toEqual(true)
expect($scope.gameState.showNext).toEqual(true)
Expand All @@ -168,6 +168,7 @@ describe('Player Controller', function() {

test('should check an "incorrect" answer choice', () => {
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

/*
answer choices are randomized, so to ensure
Expand All @@ -186,6 +187,7 @@ describe('Player Controller', function() {

test('should not check a choice if selected', () => {
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

$scope.checkChoice(0)
expect($scope.question.selected).toEqual(true)
Expand All @@ -199,15 +201,18 @@ describe('Player Controller', function() {
//this one probably should not even be possible, but whatever
test('should send appropriate values to Score.submitQuestionForScoring based on qset version 0', () => {
publicMethods.start(widgetInfo, qset.data, 0)
$scope.assistiveAlert = jest.fn()
quickCheck()
})
test('should send appropriate values to Score.submitQuestionForScoring based on qset version 1', () => {
publicMethods.start(widgetInfo, qset.data, 1)
$scope.assistiveAlert = jest.fn()
quickCheck()
})

test('should send appropriate values to Score.submitQuestionForScoring based on qset version 2', () => {
publicMethods.start(widgetInfo, qset.data, 2)
$scope.assistiveAlert = jest.fn()

$scope.answers[0].value = 0
$scope.checkChoice(0)
Expand All @@ -226,6 +231,7 @@ describe('Player Controller', function() {
test('should handle an answer choice with no feedback', () => {
// pretend incorrect question has no feedback but correct question does
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()
delete qset.data.items[0].answers[0].options.feedback

$scope.answers[0].value = 0
Expand All @@ -243,6 +249,7 @@ describe('Player Controller', function() {
// pretend question has feedback inside items instead of individual answers

publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

delete qset.data.items[0].answers[0].options.feedback
delete qset.data.items[0].answers[1].options.feedback
Expand All @@ -259,6 +266,7 @@ describe('Player Controller', function() {

test('should update when next is clicked', () => {
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()
expect($scope.question.current).toBe(0)

quickSelect()
Expand All @@ -280,6 +288,7 @@ describe('Player Controller', function() {
})

test('should toggle lightbox modal', () => {
$scope.assistiveAlert = jest.fn()
// Mock setTimeout
jest.useFakeTimers()
jest.spyOn(global, 'setTimeout')
Expand All @@ -296,11 +305,9 @@ describe('Player Controller', function() {

// Open right expand image
$scope.setLightboxTarget(1)
expect($scope.assistiveAlertText).toBe("Viewing image.")
expect($scope.lightboxTarget).toBe(1)
// Test closing right expand
$scope.setLightboxTarget(-1)
expect($scope.assistiveAlertText).toBe("Closed image viewer.")
expect($scope.focusThatExpand).toBe(true)
// Run the setTimeout timer
jest.runAllTimers()
Expand All @@ -318,6 +325,7 @@ describe('Player Controller', function() {
test('should end the game when all questions are done', () => {
const numberQuestions = qset.data.items.length
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

for (let i = 0; i < numberQuestions; i++) {
quickSelect()
Expand All @@ -329,7 +337,7 @@ describe('Player Controller', function() {
endgame: true,
score: 0,
showNext: false,
splashText: "This or That"
splashText: "The End"
}

expect($scope.question.current).toBe(numberQuestions)
Expand All @@ -342,6 +350,7 @@ describe('Player Controller', function() {
test('should end the game when viewing scores', () => {
const numberQuestions = qset.data.items.length
publicMethods.start(widgetInfo, qset.data)
$scope.assistiveAlert = jest.fn()

for (let i = 0; i < numberQuestions; i++) {
quickSelect()
Expand Down Expand Up @@ -406,6 +415,7 @@ describe('Player Controller', function() {
}

test('should shuffle questions when necessary', () => {
$scope.assistiveAlert = jest.fn()
const numberQuestions = 20

//kind of a hack, but it'll do
Expand Down Expand Up @@ -434,23 +444,24 @@ describe('Player Controller', function() {
})

test('should not shuffle questions if there are none', () => {
global.Math.random = jest.fn()
global.Math.random = jest.fn(() => 0.1)
qset.data.items = []
qset.data.options = { randomizeOrder: true }
publicMethods.start(widgetInfo, qset.data)
expect(Math.random).not.toHaveBeenCalled()
})

test('should test key presses', () => {
$scope.assistiveAlert = jest.fn()
publicMethods.start(widgetInfo, qset.data)
$scope.gameState.ingame = false
// Start screen should not register key presses
$scope.selectChoice({key: 'a'})
expect($scope.selectedChoice).toBe(-1);
// Start screen should open instructions
$scope.selectChoice({key: 'Escape'})
$scope.selectChoice({key: 'H'})
expect($scope.instructionsOpen).toBe(true)
$scope.selectChoice({key: 'Escape'})
$scope.selectChoice({key: 'h'})
expect($scope.instructionsOpen).toBe(false)

// Enter game
Expand All @@ -467,13 +478,13 @@ describe('Player Controller', function() {
expect($scope.selectedChoice).toBe(1);
// Test question key
$scope.selectChoice({key: 'q'})
expect($scope.assistiveAlertText).toBe("Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ": " + qset.data.items[$scope.question.current].questions[0].text);
expect($scope.pressedQOnce).toBe(true)
$scope.selectChoice({key: 'Q'})
expect($scope.assistiveAlertText).toBe("Question " + ($scope.question.current + 1) + " of " + $scope.questionCount + ":: " + qset.data.items[$scope.question.current].questions[0].text);
expect($scope.pressedQOnce).toBe(false)
// Test help key
$scope.selectChoice({key: 'Escape'})
$scope.selectChoice({key: 'H'})
expect($scope.instructionsOpen).toBe(true)
$scope.selectChoice({key: 'Escape'})
$scope.selectChoice({key: 'h'})
expect($scope.instructionsOpen).toBe(false)

})
Expand Down

0 comments on commit fc50e70

Please sign in to comment.