Added Survey tests for more question types

This commit is contained in:
Patrick Donelan 2009-05-28 07:23:43 +00:00
parent 83497b773e
commit d14cf19e9d
7 changed files with 209 additions and 95 deletions

View file

@ -385,9 +385,7 @@ sub responseJSON {
my $self = shift;
my ($json, $responseId) = validate_pos(@_, { type => SCALAR | UNDEF, optional => 1 }, { type => SCALAR, optional => 1});
if (!defined $responseId) {
$responseId = $self->responseId;
}
$responseId ||= $self->responseId;
if (!$self->{_responseJSON} || $json) {
@ -769,7 +767,7 @@ sub www_submitObjectEdit {
return $self->addType($params->{addtype},\@address);
}
# Update the addressed object
# Update the addressed object (and have it automatically persisted)
$self->surveyJSON_update( \@address, $params );
# Return the updated Survey structure
@ -1853,37 +1851,12 @@ sub persistResponseJSON {
#-------------------------------------------------------------------
=head2 responseIdCookies
Mutator for the responseIdCookies that determines whether cookies are used as
part of the L<"responseId"> lookup process.
Useful for disabling cookie operations during tests, since WebGUI::Test::getPage
currently does not support cookies.
=cut
sub responseIdCookies {
my $self = shift;
my ($x) = validate_pos(@_, {type => SCALAR, optional => 1});
if (defined $x) {
$self->{_responseIdCookies} = $x;
}
# Defaults to true..
return defined $self->{_responseIdCookies} ? $self->{_responseIdCookies} : 1;
}
#-------------------------------------------------------------------
=head2 responseId( [userId] )
Accessor for the responseId property, which is the unique identifier for a single
L<WebGUI::Asset::Wobject::Survey::ResponseJSON> instance. See also L<"responseJSON">.
The responseId of the current user is returned, or created if one does not already exist.
If the user is anonymous, the IP is used. Or an emailed or linked code can be used.
=head3 userId (optional)

View file

@ -536,7 +536,6 @@ sub run {
# (re)Instantiate the survey instance using the responseId
use WebGUI::Asset::Wobject::Survey;
$asset = WebGUI::Asset::Wobject::Survey->newByResponseId( $session, $mostRecentlyCompletedResponseId );
$asset->responseIdCookies(0);
if ( !$asset ) {
$session->log->warn("Unable to instantiate asset by responseId: $mostRecentlyCompletedResponseId");
return;

View file

@ -556,18 +556,22 @@ sub recordResponses {
# Server-side Validation and storing of extra data for special q types goes here
# Any answer that fails validation should be skipped with 'next'
if ( $questionType eq 'Number' ) {
if ( $questionType eq 'Country' ) {
# Must be a valid country
next if !grep { $_ eq $recordedAnswer } WebGUI::Form::Country->getCountries;
}
elsif ( $questionType eq 'Date' ) {
# Must be a valid date (until we get date i18n this is limited to YYYY/MM/DD)
next if $recordedAnswer !~ m|^\d{4}/\d{2}/\d{2}$|;
}
elsif ( $questionType eq 'Number' || $questionType eq 'Slider' ) {
if ( $answer->{max} =~ /\d/ and $recordedAnswer > $answer->{max} ) {
next;
}
elsif ( $answer->{min} =~ /\d/ and $recordedAnswer < $answer->{min} ) {
next;
}
elsif ( $answer->{step} =~ /\d/ and $recordedAnswer % $answer->{step} != 0 ) {
next;
}
}
}
elsif ( $questionType eq 'Year Month' ) {
# store year and month as "YYYY Month"
$recordedAnswer = $responses->{ "$aId-year" } . " " . $responses->{ "$aId-month" };
@ -576,7 +580,7 @@ sub recordResponses {
# In the case of a mc question, only selected answers will have a defined recordedAnswer
# Thus we skip any answers where recordedAnswer is not defined
next if !defined $recordedAnswer || $recordedAnswer !~ /\S/;
}
}
# If we reach here, answer validated ok
$aValid = 1;

View file

@ -38,28 +38,31 @@ $import_node = WebGUI::Asset->getImportNode($session);
$survey = $import_node->addChild( { className => 'WebGUI::Asset::Wobject::Survey', } );
isa_ok($survey, 'WebGUI::Asset::Wobject::Survey');
my $sJSON = $survey->surveyJSON;
# Load bare-bones survey, containing a single section (S0)
$survey->surveyJSON_update([0], { variable => 'S0' });
$sJSON->update([0], { variable => 'S0' });
# Add 2 questions to S0
$survey->surveyJSON_newObject([0]); # S0Q0
$survey->surveyJSON_update([0,0], { variable => 'S0Q0', questionType => 'Yes/No' });
$survey->surveyJSON_newObject([0]); # S0Q1
$survey->surveyJSON_update([0,1], { variable => 'S0Q1', questionType => 'Yes/No' });
$sJSON->newObject([0]); # S0Q0
$sJSON->update([0,0], { variable => 'S0Q0', questionType => 'Yes/No' });
$sJSON->newObject([0]); # S0Q1
$sJSON->update([0,1], { variable => 'S0Q1', questionType => 'Yes/No' });
# Add a new section (S1)
$survey->surveyJSON_newObject([]); # S1
$survey->surveyJSON_update([1], { variable => 'S1' });
$sJSON->newObject([]); # S1
$sJSON->update([1], { variable => 'S1' });
# Add 2 questions to S1
$survey->surveyJSON_newObject([1]); # S1Q0
$survey->surveyJSON_update([1,0], { variable => 'S1Q0' });
$survey->surveyJSON_newObject([1]); # S1Q1
$survey->surveyJSON_update([1,1], { variable => 'S1Q1' });
$sJSON->newObject([1]); # S1Q0
$sJSON->update([1,0], { variable => 'S1Q0' });
$sJSON->newObject([1]); # S1Q1
$sJSON->update([1,1], { variable => 'S1Q1' });
$survey->persistSurveyJSON;
# Now start a response as admin user
$session->user( { userId =>3 } );
$survey->responseIdCookies(0);
my $responseId = $survey->responseId;
my $s = WebGUI::Asset::Wobject::Survey->newByResponseId($session, $responseId);
@ -73,7 +76,6 @@ $s->surveyEnd();
# Uncache canTake
delete $s->{canTake};
delete $s->{responseId};
$s->responseIdCookies(0);
ok(!$s->canTakeSurvey, 'Cannot take survey a second time (maxResponsesPerUser=1)');
cmp_deeply($s->responseId, undef, '..and similarly cannot get responseId');

View file

@ -214,7 +214,6 @@ SKIP: {
$survey->surveyJSON->answer([0,1,0])->{recordedAnswer} = 'ext_s0q1a0';
$survey->surveyJSON->answer([0,1,0])->{value} = 50; # worth 50 points
$survey->responseIdCookies(0); # disable cookies so that test code doesn't die
my $responseId = $survey->responseId($user->userId);
my $rJSON = $survey->responseJSON(undef, $responseId);

View file

@ -22,7 +22,7 @@ my $session = WebGUI::Test->session;
#----------------------------------------------------------------------------
# Tests
my $tests = 104;
my $tests = 114;
plan tests => $tests + 1;
#----------------------------------------------------------------------------
@ -749,6 +749,106 @@ is($rJSON->pop, undef, 'additional pop has no effect');
$rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(buildSurveyJSON($session));
# Use Section 1 (containing 2 questions) for testing. This allows us to test 2 different responses at once.
########
# Country
for my $q (0,1) {
$rJSON->survey->updateQuestionAnswers([1,$q], 'Country');
$rJSON->survey->answer([1,$q,0])->{recordedAnswer} = '-';
}
$rJSON->reset;
$rJSON->lastResponse(2);
$rJSON->recordResponses( {
'1-0-0' => 'Australia',
'1-1-0' => 'JTville',
});
cmp_deeply(
$rJSON->responses->{'1-0-0'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => 'Australia'
},
'Valid value recorded correctly'
);
is($rJSON->responses->{'1-1-0'}, undef, 'Invalid country ignored');
########
# Date
for my $q (0,1) {
$rJSON->survey->updateQuestionAnswers([1,$q], 'Date');
$rJSON->survey->answer([1,$q,0])->{recordedAnswer} = '-';
}
$rJSON->reset;
$rJSON->lastResponse(2);
$rJSON->recordResponses( {
'1-0-0' => '2009/05/01',
'1-1-0' => '12345',
});
cmp_deeply(
$rJSON->responses->{'1-0-0'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => '2009/05/01'
},
'Valid value recorded correctly'
);
is($rJSON->responses->{'1-1-0'}, undef, 'Invalid date ignored');
########
# Number
for my $q (0,1) {
$rJSON->survey->updateQuestionAnswers([1,$q], 'Number');
$rJSON->survey->answer([1,$q,0])->{recordedAnswer} = '-';
$rJSON->survey->answer([1,$q,0])->{min} = '-5';
$rJSON->survey->answer([1,$q,0])->{max} = '10';
}
$rJSON->reset;
$rJSON->lastResponse(2);
$rJSON->recordResponses( {
'1-0-0' => '-3',
'1-1-0' => '11',
});
cmp_deeply(
$rJSON->responses->{'1-0-0'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => '-3'
},
'Valid value recorded correctly'
);
is($rJSON->responses->{'1-1-0'}, undef, 'Invalid number ignored');
########
# Slider
for my $q (0,1) {
$rJSON->survey->updateQuestionAnswers([1,$q], 'Slider');
$rJSON->survey->answer([1,$q,0])->{recordedAnswer} = '-';
$rJSON->survey->answer([1,$q,0])->{min} = '-5';
$rJSON->survey->answer([1,$q,0])->{max} = '10';
$rJSON->survey->answer([1,$q,0])->{step} = '1';
}
$rJSON->reset;
$rJSON->lastResponse(2);
$rJSON->recordResponses( {
'1-0-0' => '-3',
'1-1-0' => '11',
});
cmp_deeply(
$rJSON->responses->{'1-0-0'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => '-3'
},
'Valid value recorded correctly'
);
is($rJSON->responses->{'1-1-0'}, undef, 'Invalid slider value ignored');
########
# Yes/No
@ -785,6 +885,41 @@ cmp_deeply(
'No recorded correctly'
);
########
# True/False
$rJSON->survey->updateQuestionAnswers([1,0], 'True/False');
$rJSON->survey->updateQuestionAnswers([1,1], 'True/False');
for my $q (0,1) {
$rJSON->survey->answer([1,$q,0])->{recordedAnswer} = 'True';
$rJSON->survey->answer([1,$q,1])->{recordedAnswer} = 'False';
}
$rJSON->reset;
$rJSON->lastResponse(2);
$rJSON->recordResponses( {
'1-0-0' => 1, # Multi-choice answers are submitted like this,
'1-1-1' => 1, # with the selected answer set to 1
});
cmp_deeply(
$rJSON->responses->{'1-0-0'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => 'True'
},
'True recorded correctly'
);
cmp_deeply(
$rJSON->responses->{'1-1-1'},
{
'verbatim' => undef,
'comment' => undef,
'time' => num(time(), 3),
'value' => 'False'
},
'False recorded correctly'
);
####################################################
#
# logical sections

View file

@ -37,74 +37,76 @@ my $import_node = WebGUI::Asset->getImportNode($session);
$s = $import_node->addChild( { className => 'WebGUI::Asset::Wobject::Survey', } );
isa_ok( $s, 'WebGUI::Asset::Wobject::Survey' );
$s->responseIdCookies(0);
my $sJSON = $s->surveyJSON;
# N.B. Survey starts off with a single empty section (S0)
# Add some sections and questions
$s->surveyJSON_newObject( [] ); # S1
$s->surveyJSON_newObject( [] ); # S2
$s->surveyJSON_newObject( [] ); # S3
$s->surveyJSON_newObject( [] ); # S4
$s->surveyJSON_newObject( [] ); # S5
$s->surveyJSON_newObject( [] ); # S6
$sJSON->newObject( [] ); # S1
$sJSON->newObject( [] ); # S2
$sJSON->newObject( [] ); # S3
$sJSON->newObject( [] ); # S4
$sJSON->newObject( [] ); # S5
$sJSON->newObject( [] ); # S6
# Name the sections
for my $sIndex (0..6) {
$s->surveyJSON_update( [$sIndex], { variable => "S$sIndex" } );
$sJSON->update( [$sIndex], { variable => "S$sIndex" } );
}
# ..and now some questions
$s->surveyJSON_newObject( [0] ); # S0Q0
$s->surveyJSON_newObject( [1] ); # S1Q0
$s->surveyJSON_newObject( [2] ); # S2Q0
$s->surveyJSON_newObject( [3] ); # S3Q0
$s->surveyJSON_newObject( [3] ); # S3Q1
$s->surveyJSON_newObject( [3] ); # S3Q2
$s->surveyJSON_newObject( [4] ); # S4Q0
$s->surveyJSON_newObject( [5] ); # S5Q0
$s->surveyJSON_newObject( [5] ); # S5Q1
$s->surveyJSON_newObject( [5] ); # S5Q2
$sJSON->newObject( [0] ); # S0Q0
$sJSON->newObject( [1] ); # S1Q0
$sJSON->newObject( [2] ); # S2Q0
$sJSON->newObject( [3] ); # S3Q0
$sJSON->newObject( [3] ); # S3Q1
$sJSON->newObject( [3] ); # S3Q2
$sJSON->newObject( [4] ); # S4Q0
$sJSON->newObject( [5] ); # S5Q0
$sJSON->newObject( [5] ); # S5Q1
$sJSON->newObject( [5] ); # S5Q2
# Name the questions
$s->surveyJSON_update( [ 0, 0 ], { variable => 'S0Q0' } );
$s->surveyJSON_update( [ 1, 0 ], { variable => 'S1Q0' } );
$s->surveyJSON_update( [ 2, 0 ], { variable => 'S2Q0' } );
$s->surveyJSON_update( [ 3, 0 ], { variable => 'S3Q0' } );
$s->surveyJSON_update( [ 3, 1 ], { variable => 'S3Q1' } );
$s->surveyJSON_update( [ 3, 2 ], { variable => 'S3Q2' } );
$s->surveyJSON_update( [ 4, 0 ], { variable => 'S4Q0' } );
$s->surveyJSON_update( [ 5, 0 ], { variable => 'S5Q0' } );
$s->surveyJSON_update( [ 5, 1 ], { variable => 'S5Q1' } );
$s->surveyJSON_update( [ 5, 2 ], { variable => 'S5Q2' } );
$sJSON->update( [ 0, 0 ], { variable => 'S0Q0' } );
$sJSON->update( [ 1, 0 ], { variable => 'S1Q0' } );
$sJSON->update( [ 2, 0 ], { variable => 'S2Q0' } );
$sJSON->update( [ 3, 0 ], { variable => 'S3Q0' } );
$sJSON->update( [ 3, 1 ], { variable => 'S3Q1' } );
$sJSON->update( [ 3, 2 ], { variable => 'S3Q2' } );
$sJSON->update( [ 4, 0 ], { variable => 'S4Q0' } );
$sJSON->update( [ 5, 0 ], { variable => 'S5Q0' } );
$sJSON->update( [ 5, 1 ], { variable => 'S5Q1' } );
$sJSON->update( [ 5, 2 ], { variable => 'S5Q2' } );
# Set additional options..
$s->surveyJSON_update( [ 0, 0 ], { questionType => 'Yes/No' } ); # S0Q0 is a Yes/No
$s->surveyJSON_update( [ 0, 0 ], { gotoExpression => q{ tag('tagged at S0Q0'); } } ); # S0Q0 tagged data
$sJSON->update( [ 0, 0 ], { questionType => 'Yes/No' } ); # S0Q0 is a Yes/No
$sJSON->update( [ 0, 0 ], { gotoExpression => q{ tag('tagged at S0Q0'); } } ); # S0Q0 tagged data
$s->surveyJSON_update( [ 1, 0 ], { questionType => 'Yes/No' } ); # S1Q0 is a Yes/No
$s->surveyJSON_update( [ 1, 0, 0 ], { goto => 'S3', recordedAnswer => q{} } ); # S1Q0 answer 0 jumps to S3 (set recordedAnswer to '' to detect subtle bug)
$s->surveyJSON_update( [ 1, 0, 1 ], { gotoExpression => q{ tag('tagged at S1Q0', 999); }, recordedAnswer => q{} } );# S1Q0 answer 1 tagged numeric data
$sJSON->update( [ 1, 0 ], { questionType => 'Yes/No' } ); # S1Q0 is a Yes/No
$sJSON->update( [ 1, 0, 0 ], { goto => 'S3', recordedAnswer => q{} } ); # S1Q0 answer 0 jumps to S3 (set recordedAnswer to '' to detect subtle bug)
$sJSON->update( [ 1, 0, 1 ], { gotoExpression => q{ tag('tagged at S1Q0', 999); }, recordedAnswer => q{} } );# S1Q0 answer 1 tagged numeric data
$s->surveyJSON_update( [ 3 ], { gotoExpression => q{ jump { score(S3) == 0 } S5; } } ); # jump to S5 if all 3 questions answered as No
$sJSON->update( [ 3 ], { gotoExpression => q{ jump { score(S3) == 0 } S5; } } ); # jump to S5 if all 3 questions answered as No
for my $qIndex (0..2) {
$s->surveyJSON_update( [ 3, $qIndex ], { questionType => 'Yes/No', required => 1 } );
$s->surveyJSON_update( [ 3, $qIndex, 1 ], { value => 0 } ); # Set 'No' score to 0
$sJSON->update( [ 3, $qIndex ], { questionType => 'Yes/No', required => 1 } );
$sJSON->update( [ 3, $qIndex, 1 ], { value => 0 } ); # Set 'No' score to 0
}
$s->surveyJSON_update( [ 4, 0 ], { questionType => 'Concern' } );
$sJSON->update( [ 4, 0 ], { questionType => 'Concern' } );
$s->surveyJSON_update( [ 5, 0 ], { questionType => 'Slider', required => 1 } );
$s->surveyJSON_update( [ 5, 1 ], { questionType => 'Text', required => 1 } );
$s->surveyJSON_update( [ 5, 2 ], { questionType => 'Number', required => 1 } );
$sJSON->update( [ 5, 0 ], { questionType => 'Slider', required => 1 } );
$sJSON->update( [ 5, 1 ], { questionType => 'Text', required => 1 } );
$sJSON->update( [ 5, 2 ], { questionType => 'Number', required => 1 } );
$s->surveyJSON_update( [ 6 ], { logical => 1, gotoExpression => q{tag('tagged at S6');} } );
$sJSON->update( [ 6 ], { logical => 1, gotoExpression => q{tag('tagged at S6');} } );
# And finally, persist the changes..
$s->persistSurveyJSON;
my $rJSON = $s->responseJSON;
cmp_deeply(
$s->responseJSON->surveyOrder,
$rJSON->surveyOrder,
[ [ 0, 0, [ 0, 1 ] ], # S0Q0 (surveyOrderIndex: 0)
[ 1, 0, [ 0, 1 ] ], # S1Q0 (surveyOrderIndex: 1)
[ 2, 0, [] ], # S2Q0 (surveyOrderIndex: 2)
@ -120,7 +122,7 @@ cmp_deeply(
'surveyOrder is correct'
);
cmp_deeply(
$s->responseJSON->surveyOrderIndexByVariableName,
$rJSON->surveyOrderIndexByVariableName,
{
'S0' => 0,
'S0Q0' => 0,