Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
6defd7ba
Commit
6defd7ba
authored
Aug 30, 2013
by
Sarina Canelake
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #790 from edx/unanswered-on-input
Unanswered on input
parents
b7e8af65
fe47dcb1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
177 additions
and
40 deletions
+177
-40
common/lib/capa/capa/templates/choicegroup.html
+2
-0
common/lib/capa/capa/templates/formulaequationinput.html
+1
-1
common/lib/capa/capa/templates/optioninput.html
+1
-1
common/lib/capa/capa/templates/textline.html
+1
-1
common/lib/capa/capa/tests/test_input_templates.py
+4
-4
common/lib/xmodule/xmodule/js/src/capa/display.coffee
+52
-0
common/static/js/capa/spec/formula_equation_preview_spec.js
+23
-20
common/static/js/capa/src/formula_equation_preview.js
+5
-3
lms/djangoapps/courseware/features/problems.feature
+69
-4
lms/djangoapps/courseware/features/problems.py
+17
-6
lms/djangoapps/courseware/features/problems_setup.py
+2
-0
No files found.
common/lib/capa/capa/templates/choicegroup.html
View file @
6defd7ba
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
% for choice_id, choice_description in choices:
% for choice_id, choice_description in choices:
<label
for=
"input_${id}_${choice_id}"
<label
for=
"input_${id}_${choice_id}"
##
If
the
student
has
selected
this
choice
...
%
if
input_type =
=
'
radio
'
and
(
(
isinstance
(
value
,
basestring
)
and
(
choice_id =
=
value
))
or
(
not
isinstance
(
value
,
basestring
)
and
choice_id
in
value
)
)
:
%
if
input_type =
=
'
radio
'
and
(
(
isinstance
(
value
,
basestring
)
and
(
choice_id =
=
value
))
or
(
not
isinstance
(
value
,
basestring
)
and
choice_id
in
value
)
)
:
<%
<%
if
status =
=
'
correct
'
:
if
status =
=
'
correct
'
:
...
@@ -32,6 +33,7 @@
...
@@ -32,6 +33,7 @@
% endif
% endif
>
>
<input
type=
"${input_type}"
name=
"input_${id}${name_array_suffix}"
id=
"input_${id}_${choice_id}"
aria-describedby=
"answer_${id}"
value=
"${choice_id}"
<input
type=
"${input_type}"
name=
"input_${id}${name_array_suffix}"
id=
"input_${id}_${choice_id}"
aria-describedby=
"answer_${id}"
value=
"${choice_id}"
##
If
the
student
selected
this
choice
...
%
if
input_type =
=
'
radio
'
and
(
(
isinstance
(
value
,
basestring
)
and
(
choice_id =
=
value
))
or
(
not
isinstance
(
value
,
basestring
)
and
choice_id
in
value
)
)
:
%
if
input_type =
=
'
radio
'
and
(
(
isinstance
(
value
,
basestring
)
and
(
choice_id =
=
value
))
or
(
not
isinstance
(
value
,
basestring
)
and
choice_id
in
value
)
)
:
checked=
"true"
checked=
"true"
%
elif
input_type
!=
'
radio
'
and
choice_id
in
value:
%
elif
input_type
!=
'
radio
'
and
choice_id
in
value:
...
...
common/lib/capa/capa/templates/formulaequationinput.html
View file @
6defd7ba
<section
id=
"formulaequationinput_${id}"
class=
"formulaequationinput"
>
<section
id=
"formulaequationinput_${id}"
class=
"
inputtype
formulaequationinput"
>
<div
class=
"${reported_status}"
id=
"status_${id}"
>
<div
class=
"${reported_status}"
id=
"status_${id}"
>
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
data-input-id=
"${id}"
value=
"${value|h}"
data-input-id=
"${id}"
value=
"${value|h}"
...
...
common/lib/capa/capa/templates/optioninput.html
View file @
6defd7ba
<form
class=
"option-input"
>
<form
class=
"
inputtype
option-input"
>
<select
name=
"input_${id}"
id=
"input_${id}"
aria-describedby=
"answer_${id}"
>
<select
name=
"input_${id}"
id=
"input_${id}"
aria-describedby=
"answer_${id}"
>
<option
value=
"option_${id}_dummy_default"
>
</option>
<option
value=
"option_${id}_dummy_default"
>
</option>
% for option_id, option_description in options:
% for option_id, option_description in options:
...
...
common/lib/capa/capa/templates/textline.html
View file @
6defd7ba
<
%
doinline =
"inline"
if
inline
else
""
%
>
<
%
doinline =
"inline"
if
inline
else
""
%
>
<section
id=
"inputtype_${id}"
class=
"${'text-input-dynamath' if do_math else ''} capa_inputtype ${doinline}"
>
<section
id=
"inputtype_${id}"
class=
"${'text-input-dynamath' if do_math else ''} capa_inputtype ${doinline}
textline
"
>
% if preprocessor is not None:
% if preprocessor is not None:
<div
class=
"text-input-dynamath_data"
data-preprocessor=
"${preprocessor['class_name']}"
/>
<div
class=
"text-input-dynamath_data"
data-preprocessor=
"${preprocessor['class_name']}"
/>
...
...
common/lib/capa/capa/tests/test_input_templates.py
View file @
6defd7ba
...
@@ -352,10 +352,10 @@ class TextlineTemplateTest(TemplateTestCase):
...
@@ -352,10 +352,10 @@ class TextlineTemplateTest(TemplateTestCase):
super
(
TextlineTemplateTest
,
self
)
.
setUp
()
super
(
TextlineTemplateTest
,
self
)
.
setUp
()
def
test_section_class
(
self
):
def
test_section_class
(
self
):
cases
=
[({},
' capa_inputtype '
),
cases
=
[({},
' capa_inputtype
textline
'
),
({
'do_math'
:
True
},
'text-input-dynamath capa_inputtype '
),
({
'do_math'
:
True
},
'text-input-dynamath capa_inputtype
textline
'
),
({
'inline'
:
True
},
' capa_inputtype inline'
),
({
'inline'
:
True
},
' capa_inputtype inline
textline
'
),
({
'do_math'
:
True
,
'inline'
:
True
},
'text-input-dynamath capa_inputtype inline'
),
]
({
'do_math'
:
True
,
'inline'
:
True
},
'text-input-dynamath capa_inputtype inline
textline
'
),
]
for
(
context
,
css_class
)
in
cases
:
for
(
context
,
css_class
)
in
cases
:
base_context
=
self
.
context
.
copy
()
base_context
=
self
.
context
.
copy
()
...
...
common/lib/xmodule/xmodule/js/src/capa/display.coffee
View file @
6defd7ba
...
@@ -25,6 +25,8 @@ class @Problem
...
@@ -25,6 +25,8 @@ class @Problem
@
$
(
'section.action button.show'
).
click
@
show
@
$
(
'section.action button.show'
).
click
@
show
@
$
(
'section.action input.save'
).
click
@
save
@
$
(
'section.action input.save'
).
click
@
save
@
bindResetCorrectness
()
# Collapsibles
# Collapsibles
Collapsible
.
setCollapsibles
(
@
el
)
Collapsible
.
setCollapsibles
(
@
el
)
...
@@ -370,6 +372,56 @@ class @Problem
...
@@ -370,6 +372,56 @@ class @Problem
element
.
CodeMirror
.
save
()
if
element
.
CodeMirror
.
save
element
.
CodeMirror
.
save
()
if
element
.
CodeMirror
.
save
@
answers
=
@
inputs
.
serialize
()
@
answers
=
@
inputs
.
serialize
()
bindResetCorrectness
:
->
# Loop through all input types
# Bind the reset functions at that scope.
$inputtypes
=
@
el
.
find
(
".capa_inputtype"
).
add
(
@
el
.
find
(
".inputtype"
))
$inputtypes
.
each
(
index
,
inputtype
)
=>
classes
=
$
(
inputtype
).
attr
(
'class'
).
split
(
' '
)
for
cls
in
classes
bindMethod
=
@
bindResetCorrectnessByInputtype
[
cls
]
if
bindMethod
?
bindMethod
(
inputtype
)
# Find all places where each input type displays its correct-ness
# Replace them with their original state--'unanswered'.
bindResetCorrectnessByInputtype
:
# These are run at the scope of the capa inputtype
# They should set handlers on each <input> to reset the whole.
formulaequationinput
:
(
element
)
->
$
(
element
).
find
(
'input'
).
on
'input'
,
->
$p
=
$
(
element
).
find
(
'p.status'
)
$p
.
text
gettext
(
"unanswered"
)
$p
.
parent
().
removeClass
().
addClass
"unanswered"
choicegroup
:
(
element
)
->
$element
=
$
(
element
)
id
=
(
$element
.
attr
(
'id'
).
match
/^inputtype_(.*)$/
)[
1
]
$element
.
find
(
'input'
).
on
'change'
,
->
$status
=
$
(
"#status_
#{
id
}
"
)
if
$status
[
0
]
# We found a status icon.
$status
.
removeClass
().
addClass
"unanswered"
$status
.
empty
().
css
'display'
,
'inline-block'
else
# Recreate the unanswered dot on left.
$
(
"<span>"
,
{
"class"
:
"unanswered"
,
"style"
:
"display: inline-block;"
,
"id"
:
"status_
#{
id
}
"
})
$element
.
find
(
"label"
).
removeClass
()
'option-input'
:
(
element
)
->
$select
=
$
(
element
).
find
(
'select'
)
id
=
(
$select
.
attr
(
'id'
).
match
/^input_(.*)$/
)[
1
]
$select
.
on
'change'
,
->
$status
=
$
(
"#status_
#{
id
}
"
)
.
removeClass
().
addClass
(
"unanswered"
)
.
find
(
'span'
).
text
(
gettext
(
'Status: unsubmitted'
))
textline
:
(
element
)
->
$
(
element
).
find
(
'input'
).
on
'input'
,
->
$p
=
$
(
element
).
find
(
'p.status'
)
$p
.
text
"unanswered"
$p
.
parent
().
removeClass
().
addClass
"unanswered"
inputtypeSetupMethods
:
inputtypeSetupMethods
:
'text-input-dynamath'
:
(
element
)
=>
'text-input-dynamath'
:
(
element
)
=>
...
...
common/static/js/capa/spec/formula_equation_preview_spec.js
View file @
6defd7ba
...
@@ -15,11 +15,14 @@ describe("Formula Equation Preview", function () {
...
@@ -15,11 +15,14 @@ describe("Formula Equation Preview", function () {
var
$fixture
=
this
.
$fixture
=
$
(
'
\
var
$fixture
=
this
.
$fixture
=
$
(
'
\
<section class="problems-wrapper" data-url="THE_URL">
\
<section class="problems-wrapper" data-url="THE_URL">
\
<section class="formulaequationinput">
\
<section class="formulaequationinput">
\
<input type="text" id="input_THE_ID" data-input-id="THE_ID"
\
<div class="INITIAL_STATUS" id="status_THE_ID">
\
value="prefilled_value"/>
\
<input type="text" id="input_THE_ID" data-input-id="THE_ID"
\
<div id="input_THE_ID_preview" class="equation">
\
value="PREFILLED_VALUE"/>
\
\
[
\
]
\
<p class="status">INITIAL_STATUS</p>
\
<img class="loading" style="visibility:hidden"/>
\
<div id="input_THE_ID_preview" class="equation">
\
\
[
\
]
\
<img class="loading" style="visibility:hidden"/>
\
</div>
\
</div>
\
</div>
\
</section>
\
</section>
\
</section>'
);
</section>'
);
...
@@ -62,10 +65,10 @@ describe("Formula Equation Preview", function () {
...
@@ -62,10 +65,10 @@ describe("Formula Equation Preview", function () {
MathJax
.
Hub
.
Queue
=
jasmine
.
createSpy
(
'MathJax.Hub.Queue'
);
MathJax
.
Hub
.
Queue
=
jasmine
.
createSpy
(
'MathJax.Hub.Queue'
);
});
});
it
(
'(the test)
should be
able to swap out the behavior of $'
,
function
()
{
it
(
'(the test)
is
able to swap out the behavior of $'
,
function
()
{
// This was a pain to write, make sure it doesn't get screwed up.
// This was a pain to write, make sure it doesn't get screwed up.
// Find the
DOM
element using DOM methods.
// Find the element using DOM methods.
var
legitInput
=
this
.
$fixture
[
0
].
getElementsByTagName
(
"input"
)[
0
];
var
legitInput
=
this
.
$fixture
[
0
].
getElementsByTagName
(
"input"
)[
0
];
// Use the (modified) jQuery.
// Use the (modified) jQuery.
...
@@ -96,7 +99,7 @@ describe("Formula Equation Preview", function () {
...
@@ -96,7 +99,7 @@ describe("Formula Equation Preview", function () {
"THE_URL"
,
"THE_URL"
,
"THE_ID"
,
"THE_ID"
,
"preview_formcalc"
,
"preview_formcalc"
,
{
formula
:
"
prefilled_value
"
,
{
formula
:
"
PREFILLED_VALUE
"
,
request_start
:
jasmine
.
any
(
Number
)},
request_start
:
jasmine
.
any
(
Number
)},
jasmine
.
any
(
Function
)
jasmine
.
any
(
Function
)
]);
]);
...
@@ -117,7 +120,7 @@ describe("Formula Equation Preview", function () {
...
@@ -117,7 +120,7 @@ describe("Formula Equation Preview", function () {
});
});
});
});
it
(
"
shouldn't be
requested for empty input"
,
function
()
{
it
(
"
isn't
requested for empty input"
,
function
()
{
Problem
.
inputAjax
.
reset
();
Problem
.
inputAjax
.
reset
();
// When we make an input of '',
// When we make an input of '',
...
@@ -136,7 +139,7 @@ describe("Formula Equation Preview", function () {
...
@@ -136,7 +139,7 @@ describe("Formula Equation Preview", function () {
});
});
});
});
it
(
'
should limit
the number of requests per second'
,
function
()
{
it
(
'
limits
the number of requests per second'
,
function
()
{
var
minDelay
=
formulaEquationPreview
.
minDelay
;
var
minDelay
=
formulaEquationPreview
.
minDelay
;
var
end
=
Date
.
now
()
+
minDelay
*
1.1
;
var
end
=
Date
.
now
()
+
minDelay
*
1.1
;
var
step
=
10
;
// ms
var
step
=
10
;
// ms
...
@@ -171,7 +174,7 @@ describe("Formula Equation Preview", function () {
...
@@ -171,7 +174,7 @@ describe("Formula Equation Preview", function () {
});
});
describe
(
"Visible results (icon and mathjax)"
,
function
()
{
describe
(
"Visible results (icon and mathjax)"
,
function
()
{
it
(
'
should display
a loading icon when requests are open'
,
function
()
{
it
(
'
displays
a loading icon when requests are open'
,
function
()
{
var
$img
=
$
(
"img.loading"
);
var
$img
=
$
(
"img.loading"
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
);
formulaEquationPreview
.
enable
();
formulaEquationPreview
.
enable
();
...
@@ -199,7 +202,7 @@ describe("Formula Equation Preview", function () {
...
@@ -199,7 +202,7 @@ describe("Formula Equation Preview", function () {
});
});
});
});
it
(
'
should update
MathJax and loading icon on callback'
,
function
()
{
it
(
'
updates
MathJax and loading icon on callback'
,
function
()
{
formulaEquationPreview
.
enable
();
formulaEquationPreview
.
enable
();
waitsFor
(
function
()
{
waitsFor
(
function
()
{
return
Problem
.
inputAjax
.
wasCalled
;
return
Problem
.
inputAjax
.
wasCalled
;
...
@@ -217,7 +220,7 @@ describe("Formula Equation Preview", function () {
...
@@ -217,7 +220,7 @@ describe("Formula Equation Preview", function () {
expect
(
$
(
"img.loading"
).
css
(
'visibility'
)).
toEqual
(
'hidden'
);
expect
(
$
(
"img.loading"
).
css
(
'visibility'
)).
toEqual
(
'hidden'
);
// We should look in the preview div for the MathJax.
// We should look in the preview div for the MathJax.
var
previewDiv
=
$
(
"
div
"
)[
0
];
var
previewDiv
=
$
(
"
#input_THE_ID_preview
"
)[
0
];
expect
(
MathJax
.
Hub
.
getAllJax
).
toHaveBeenCalledWith
(
previewDiv
);
expect
(
MathJax
.
Hub
.
getAllJax
).
toHaveBeenCalledWith
(
previewDiv
);
// Refresh the MathJax.
// Refresh the MathJax.
...
@@ -242,7 +245,7 @@ describe("Formula Equation Preview", function () {
...
@@ -242,7 +245,7 @@ describe("Formula Equation Preview", function () {
// Cannot find MathJax.
// Cannot find MathJax.
MathJax
.
Hub
.
getAllJax
.
andReturn
([]);
MathJax
.
Hub
.
getAllJax
.
andReturn
([]);
spyOn
(
console
,
'
error
'
);
spyOn
(
console
,
'
warn
'
);
callback
({
callback
({
preview
:
'THE_FORMULA'
,
preview
:
'THE_FORMULA'
,
...
@@ -250,10 +253,10 @@ describe("Formula Equation Preview", function () {
...
@@ -250,10 +253,10 @@ describe("Formula Equation Preview", function () {
});
});
// Tests.
// Tests.
expect
(
console
.
error
).
toHaveBeenCalled
();
expect
(
console
.
warn
).
toHaveBeenCalled
();
// We should look in the preview div for the MathJax.
// We should look in the preview div for the MathJax.
var
previewElement
=
$
(
"
div
"
)[
0
];
var
previewElement
=
$
(
"
#input_THE_ID_preview
"
)[
0
];
expect
(
previewElement
.
firstChild
.
data
).
toEqual
(
"
\\
[THE_FORMULA
\\
]"
);
expect
(
previewElement
.
firstChild
.
data
).
toEqual
(
"
\\
[THE_FORMULA
\\
]"
);
// Refresh the MathJax.
// Refresh the MathJax.
...
@@ -263,7 +266,7 @@ describe("Formula Equation Preview", function () {
...
@@ -263,7 +266,7 @@ describe("Formula Equation Preview", function () {
});
});
});
});
it
(
'
should display
errors from the server well'
,
function
()
{
it
(
'
displays
errors from the server well'
,
function
()
{
var
$img
=
$
(
"img.loading"
);
var
$img
=
$
(
"img.loading"
);
formulaEquationPreview
.
enable
();
formulaEquationPreview
.
enable
();
waitsFor
(
function
()
{
waitsFor
(
function
()
{
...
@@ -329,7 +332,7 @@ describe("Formula Equation Preview", function () {
...
@@ -329,7 +332,7 @@ describe("Formula Equation Preview", function () {
});
});
});
});
it
(
'
should update
requests sequentially'
,
function
()
{
it
(
'
updates
requests sequentially'
,
function
()
{
var
$img
=
$
(
"img.loading"
);
var
$img
=
$
(
"img.loading"
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'visible'
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'visible'
);
...
@@ -349,7 +352,7 @@ describe("Formula Equation Preview", function () {
...
@@ -349,7 +352,7 @@ describe("Formula Equation Preview", function () {
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
)
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
)
});
});
it
(
"
should
n't display outdated information"
,
function
()
{
it
(
"
does
n't display outdated information"
,
function
()
{
var
$img
=
$
(
"img.loading"
);
var
$img
=
$
(
"img.loading"
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'visible'
);
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'visible'
);
...
@@ -368,7 +371,7 @@ describe("Formula Equation Preview", function () {
...
@@ -368,7 +371,7 @@ describe("Formula Equation Preview", function () {
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
)
expect
(
$img
.
css
(
'visibility'
)).
toEqual
(
'hidden'
)
});
});
it
(
"
should
n't show an error if the responses are close together"
,
it
(
"
does
n't show an error if the responses are close together"
,
function
()
{
function
()
{
this
.
callbacks
[
0
]({
this
.
callbacks
[
0
]({
error
:
'OOPSIE'
,
error
:
'OOPSIE'
,
...
...
common/static/js/capa/src/formula_equation_preview.js
View file @
6defd7ba
...
@@ -52,12 +52,14 @@ formulaEquationPreview.enable = function () {
...
@@ -52,12 +52,14 @@ formulaEquationPreview.enable = function () {
// Show the loading icon.
// Show the loading icon.
inputData
.
$img
.
css
(
'visibility'
,
'visible'
);
inputData
.
$img
.
css
(
'visibility'
,
'visible'
);
// Say we are waiting for request.
inputData
.
isWaitingForRequest
=
true
;
inputData
.
isWaitingForRequest
=
true
;
// First thing in `sendRequest`, say we aren't anymore.
throttledRequest
(
inputData
,
this
.
value
);
throttledRequest
(
inputData
,
this
.
value
);
};
};
$this
.
on
(
"input"
,
initializeRequest
);
$this
.
on
(
"input"
,
initializeRequest
);
//
send an initial
//
Ask for initial preview.
initializeRequest
.
call
(
this
);
initializeRequest
.
call
(
this
);
}
}
...
@@ -85,7 +87,7 @@ formulaEquationPreview.enable = function () {
...
@@ -85,7 +87,7 @@ formulaEquationPreview.enable = function () {
// // This is run when ajax call fails.
// // This is run when ajax call fails.
// // Have an error message and other stuff here?
// // Have an error message and other stuff here?
// inputData.$img.css('visibility', 'hidden');
// inputData.$img.css('visibility', 'hidden');
// });
*/
// });
}
}
else
{
else
{
inputData
.
requestCallback
({
inputData
.
requestCallback
({
...
@@ -140,7 +142,7 @@ formulaEquationPreview.enable = function () {
...
@@ -140,7 +142,7 @@ formulaEquationPreview.enable = function () {
);
);
}
}
else
if
(
latex
)
{
else
if
(
latex
)
{
console
.
error
(
"
Oops no mathjax for "
,
latex
);
console
.
warn
(
"[FormulaEquationInput]
Oops no mathjax for "
,
latex
);
// Fall back to modifying the actual element.
// Fall back to modifying the actual element.
var
textNode
=
previewElement
.
childNodes
[
0
];
var
textNode
=
previewElement
.
childNodes
[
0
];
textNode
.
data
=
"
\\
["
+
latex
+
"
\\
]"
;
textNode
.
data
=
"
\\
["
+
latex
+
"
\\
]"
;
...
...
lms/djangoapps/courseware/features/problems.feature
View file @
6defd7ba
...
@@ -7,7 +7,7 @@ Feature: Answer problems
...
@@ -7,7 +7,7 @@ Feature: Answer problems
Given
External graders respond
"correct"
Given
External graders respond
"correct"
And
I am viewing a
"<ProblemType>"
problem
And
I am viewing a
"<ProblemType>"
problem
When
I answer a
"<ProblemType>"
problem
"correctly"
When
I answer a
"<ProblemType>"
problem
"correctly"
Then
M
y
"<ProblemType>"
answer is marked
"correct"
Then
m
y
"<ProblemType>"
answer is marked
"correct"
And
The
"<ProblemType>"
problem displays a
"correct"
answer
And
The
"<ProblemType>"
problem displays a
"correct"
answer
Examples
:
Examples
:
...
@@ -28,7 +28,7 @@ Feature: Answer problems
...
@@ -28,7 +28,7 @@ Feature: Answer problems
Given
External graders respond
"incorrect"
Given
External graders respond
"incorrect"
And
I am viewing a
"<ProblemType>"
problem
And
I am viewing a
"<ProblemType>"
problem
When
I answer a
"<ProblemType>"
problem
"incorrectly"
When
I answer a
"<ProblemType>"
problem
"incorrectly"
Then
M
y
"<ProblemType>"
answer is marked
"incorrect"
Then
m
y
"<ProblemType>"
answer is marked
"incorrect"
And
The
"<ProblemType>"
problem displays a
"incorrect"
answer
And
The
"<ProblemType>"
problem displays a
"incorrect"
answer
Examples
:
Examples
:
...
@@ -48,7 +48,7 @@ Feature: Answer problems
...
@@ -48,7 +48,7 @@ Feature: Answer problems
Scenario
:
I
can submit a blank answer
Scenario
:
I
can submit a blank answer
Given
I am viewing a
"<ProblemType>"
problem
Given
I am viewing a
"<ProblemType>"
problem
When
I check a problem
When
I check a problem
Then
M
y
"<ProblemType>"
answer is marked
"incorrect"
Then
m
y
"<ProblemType>"
answer is marked
"incorrect"
And
The
"<ProblemType>"
problem displays a
"blank"
answer
And
The
"<ProblemType>"
problem displays a
"blank"
answer
Examples
:
Examples
:
...
@@ -69,7 +69,7 @@ Feature: Answer problems
...
@@ -69,7 +69,7 @@ Feature: Answer problems
Given
I am viewing a
"<ProblemType>"
problem
Given
I am viewing a
"<ProblemType>"
problem
And
I answer a
"<ProblemType>"
problem
"<Correctness>ly"
And
I answer a
"<ProblemType>"
problem
"<Correctness>ly"
When
I reset the problem
When
I reset the problem
Then
M
y
"<ProblemType>"
answer is marked
"unanswered"
Then
m
y
"<ProblemType>"
answer is marked
"unanswered"
And
The
"<ProblemType>"
problem displays a
"blank"
answer
And
The
"<ProblemType>"
problem displays a
"blank"
answer
Examples
:
Examples
:
...
@@ -171,3 +171,68 @@ Feature: Answer problems
...
@@ -171,3 +171,68 @@ Feature: Answer problems
|
numerical
|
1
point
possible
|
|
numerical
|
1
point
possible
|
|
formula
|
1
point
possible
|
|
formula
|
1
point
possible
|
|
script
|
2
points
possible
|
|
script
|
2
points
possible
|
Scenario
:
I
can reset the correctness of a problem after changing my answer
Given
I am viewing a
"<ProblemType>"
problem
Then
my
"<ProblemType>"
answer is marked
"unanswered"
When
I answer a
"<ProblemType>"
problem
"<InitialCorrectness>ly"
And
I wait for
"1"
seconds
And
I input an answer on a
"<ProblemType>"
problem
"<OtherCorrectness>ly"
Then
my
"<ProblemType>"
answer is marked
"unanswered"
And
I reset the problem
Examples
:
|
ProblemType
|
InitialCorrectness
|
OtherCorrectness
|
|
drop
down
|
correct
|
incorrect
|
|
drop
down
|
incorrect
|
correct
|
|
checkbox
|
correct
|
incorrect
|
|
checkbox
|
incorrect
|
correct
|
|
string
|
correct
|
incorrect
|
|
string
|
incorrect
|
correct
|
|
numerical
|
correct
|
incorrect
|
|
numerical
|
incorrect
|
correct
|
|
formula
|
correct
|
incorrect
|
|
formula
|
incorrect
|
correct
|
|
script
|
correct
|
incorrect
|
|
script
|
incorrect
|
correct
|
# Radio groups behave slightly differently than other types of checkboxes, because they
# don't put their status to the top left of the boxes (like checkboxes do), thus, they'll
# not ever have a status of "unanswered" once you've made an answer. They should simply NOT
# be marked either correct or incorrect. Arguably this behavior should be changed; when it
# is, these cases should move into the above Scenario.
Scenario
:
I
can reset the correctness of a radiogroup problem after changing my answer
Given
I am viewing a
"<ProblemType>"
problem
When
I answer a
"<ProblemType>"
problem
"<InitialCorrectness>ly"
And
I wait for
"1"
seconds
Then
my
"<ProblemType>"
answer is marked
"<InitialCorrectness>"
And
I input an answer on a
"<ProblemType>"
problem
"<OtherCorrectness>ly"
Then
my
"<ProblemType>"
answer is NOT marked
"<InitialCorrectness>"
And
my
"<ProblemType>"
answer is NOT marked
"<OtherCorrectness>"
And
I reset the problem
Examples
:
|
ProblemType
|
InitialCorrectness
|
OtherCorrectness
|
|
multiple
choice
|
correct
|
incorrect
|
|
multiple
choice
|
incorrect
|
correct
|
|
radio
|
correct
|
incorrect
|
|
radio
|
incorrect
|
correct
|
Scenario
:
I
can reset the correctness of a problem after submitting a blank answer
Given
I am viewing a
"<ProblemType>"
problem
When
I check a problem
And
I input an answer on a
"<ProblemType>"
problem
"correctly"
Then
my
"<ProblemType>"
answer is marked
"unanswered"
Examples
:
|
ProblemType
|
|
drop
down
|
|
multiple
choice
|
|
checkbox
|
|
radio
|
|
string
|
|
numerical
|
|
formula
|
|
script
|
lms/djangoapps/courseware/features/problems.py
View file @
6defd7ba
...
@@ -82,14 +82,22 @@ def answer_problem_step(step, problem_type, correctness):
...
@@ -82,14 +82,22 @@ def answer_problem_step(step, problem_type, correctness):
*problem_type* is a string representing the type of problem (e.g. 'drop down')
*problem_type* is a string representing the type of problem (e.g. 'drop down')
*correctness* is in ['correct', 'incorrect']
*correctness* is in ['correct', 'incorrect']
"""
"""
# Change the answer on the page
input_problem_answer
(
step
,
problem_type
,
correctness
)
# Submit the problem
check_problem
(
step
)
@step
(
u'I input an answer on a "([^"]*)" problem "([^"]*)ly"'
)
def
input_problem_answer
(
_
,
problem_type
,
correctness
):
"""
Have the browser input an answer (either correct or incorrect)
"""
assert
(
correctness
in
[
'correct'
,
'incorrect'
])
assert
(
correctness
in
[
'correct'
,
'incorrect'
])
assert
(
problem_type
in
PROBLEM_DICT
)
assert
(
problem_type
in
PROBLEM_DICT
)
answer_problem
(
problem_type
,
correctness
)
answer_problem
(
problem_type
,
correctness
)
# Submit the problem
check_problem
(
step
)
@step
(
u'I check a problem'
)
@step
(
u'I check a problem'
)
def
check_problem
(
step
):
def
check_problem
(
step
):
...
@@ -146,8 +154,8 @@ def see_score(_step, score):
...
@@ -146,8 +154,8 @@ def see_score(_step, score):
assert
world
.
browser
.
is_text_present
(
score
)
assert
world
.
browser
.
is_text_present
(
score
)
@step
(
u'
My "([^"]*)" answer is
marked "([^"]*)"'
)
@step
(
u'
[Mm]y "([^"]*)" answer is( NOT)?
marked "([^"]*)"'
)
def
assert_answer_mark
(
step
,
problem_type
,
correctness
):
def
assert_answer_mark
(
_step
,
problem_type
,
isnt_marked
,
correctness
):
"""
"""
Assert that the expected answer mark is visible
Assert that the expected answer mark is visible
for a given problem type.
for a given problem type.
...
@@ -162,7 +170,10 @@ def assert_answer_mark(step, problem_type, correctness):
...
@@ -162,7 +170,10 @@ def assert_answer_mark(step, problem_type, correctness):
# At least one of the correct selectors should be present
# At least one of the correct selectors should be present
for
sel
in
PROBLEM_DICT
[
problem_type
][
correctness
]:
for
sel
in
PROBLEM_DICT
[
problem_type
][
correctness
]:
has_expected
=
world
.
is_css_present
(
sel
)
if
isnt_marked
:
has_expected
=
world
.
is_css_not_present
(
sel
)
else
:
has_expected
=
world
.
is_css_present
(
sel
)
# As soon as we find the selector, break out of the loop
# As soon as we find the selector, break out of the loop
if
has_expected
:
if
has_expected
:
...
...
lms/djangoapps/courseware/features/problems_setup.py
View file @
6defd7ba
...
@@ -24,6 +24,8 @@ from capa.tests.response_xml_factory import OptionResponseXMLFactory, \
...
@@ -24,6 +24,8 @@ from capa.tests.response_xml_factory import OptionResponseXMLFactory, \
# Factories from capa.tests.response_xml_factory that we will use
# Factories from capa.tests.response_xml_factory that we will use
# to generate the problem XML, with the keyword args used to configure
# to generate the problem XML, with the keyword args used to configure
# the output.
# the output.
# 'correct', 'incorrect', and 'unanswered' keys are lists of CSS selectors
# the presence of any in the list is sufficient
PROBLEM_DICT
=
{
PROBLEM_DICT
=
{
'drop down'
:
{
'drop down'
:
{
'factory'
:
OptionResponseXMLFactory
(),
'factory'
:
OptionResponseXMLFactory
(),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment