add description of percentiles graph for screenreaders

fixes CNVS-31803

test plan:
  - take a quiz with several students
    and get different scores
  - go to the quiz statistics page
  - with a screenreader go to the chart
    showing the breakdown of scores
    by percentile
  - you get a description of the bars
    in the screenreader (X students in
    percentile Y)

Change-Id: I100577687058d27a9921773e81edc64b3cf1cb87
Reviewed-on: https://gerrit.instructure.com/90642
Reviewed-by: Ryan Taylor <rtaylor@instructure.com>
Tested-by: Jenkins
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Nathan Rogowski <nathan@instructure.com>
This commit is contained in:
Michael Nomitch 2016-09-16 17:30:35 -05:00 committed by Mike Nomitch
parent e749d81ff3
commit 55d22fb710
4 changed files with 40 additions and 12 deletions

View File

@ -14,7 +14,7 @@ define(function(require) {
},
render: function() {
return React.DOM.svg({ className: "chart" });
return React.DOM.div({ref: 'wrapper'}, {}, React.DOM.svg({ className: "chart", ref: 'chart'}));
},
removeChart: function() {
@ -29,10 +29,10 @@ define(function(require) {
return svg.append('title').text(title);
},
addDescription: function(svg, description) {
return svg.append('text')
.attr('fill', 'transparent')
.attr('font-size', '0px')
addDescription: function(holder, description) {
return holder.append('text')
.attr('tabindex', '0')
.attr('class', 'screenreader-only')
.text(description);
},

View File

@ -70,7 +70,9 @@ define(function(require) {
.append('g');
this.title = ChartMixin.addTitle(svg, '');
this.description = ChartMixin.addDescription(svg, '');
const descriptionHolder = (this.refs.wrapper && d3.select(this.refs.wrapper.getDOMNode())) || svg
this.description = ChartMixin.addDescription(descriptionHolder, '');
svg.append('g')
.attr('class', 'x axis')
@ -99,13 +101,27 @@ define(function(require) {
var data = this.chartData = this.calculateChartData(props);
var avgScore = props.scoreAverage / props.pointsPossible * 100.0;
labelOptions = this.calculateStudentStatistics(avgScore, data);
var textForScreenreaders = I18n.t('audible_chart_description',
'%{above_average} students scored above or at the average, and %{below_average} below. ', {
above_average: labelOptions.aboveAverage,
below_average: labelOptions.belowAverage
})
data.forEach(function (datum, i) {
if (datum !== 0) {
textForScreenreaders += I18n.t({
one: "1 student in percentile %{percentile}. ",
other: "%{count} students in percentile %{percentile}. "
},{
count: datum,
percentile: i + ''
}
)
}
})
this.title.text(I18n.t('chart_title', 'Score percentiles chart'));
this.description.text(I18n.t('audible_chart_description',
'%{above_average} students scored above or at the average, and %{below_average} below.', {
above_average: labelOptions.aboveAverage,
below_average: labelOptions.belowAverage
}));
this.description.text(textForScreenreaders);
this.renderBars(this.barContainer, props);
},

View File

@ -40,6 +40,18 @@ define(function(require) {
expect(findAll('rect.bar').length).toEqual(101);
});
it('should add a description each bar', function() {
setProps({
scores: {
1: 1,]
62: 2
}
});
var summaryText = find('#summary-statistics').innerText;
expect(summaryText).toContain('2 students in percentile 62');
});
it('bar height should be based on score frequency', function(done) {
setProps({
scores: {

View File

@ -14,7 +14,7 @@
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-plugin-add-module-exports": "0.2.1",
"babel-polyfill": "6.9.1",
"babel-polyfill": "6.13.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-1": "^6.5.0",