From 6c58e1de81121eab569ed39739dbdab027b9f761 Mon Sep 17 00:00:00 2001 From: Patrick Donelan Date: Wed, 22 Apr 2009 07:19:23 +0000 Subject: [PATCH] Added Survey meta-targets NEXT_SECTION and END_SURVEY to allow for more convenient jumping Improved processGotoExpression tests --- .../Asset/Wobject/Survey/ResponseJSON.pm | 34 +++++-- lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm | 17 ++-- t/Asset/Wobject/Survey/ResponseJSON.t | 89 +++++++++++++------ 3 files changed, 100 insertions(+), 40 deletions(-) diff --git a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm index d0bf30549..e49864ed2 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm @@ -274,17 +274,20 @@ sub startTime { Accessor. Initialized on first access via L<"initSurveyOrder">. -This data strucutre is an array (reference) of Survey addresses (see -L), stored in the order -in which items are presented to the user. +This data strucutre represents the list of items that are shown to the user, in the order +that they will be shown (ignoring jumps and jump expressions). -In general, the surveyOrder data structure looks like: +Typically each item will correspond to a question, and contains enough information to look +up both the corresponding section and all contained answers (if any). + +Empty sections also appear in the list. + +Each element of the array is an address, similar in structure to +L, +except that instead of an answerIndex in the third slot, we have a sub-array of all contained answer indicies. [ $sectionIndex, $questionIndex, [ $answerIndex1, $answerIndex2, ....] -There is one array element for every section and address in the survey. If there are -no questions, or no addresses, those array elements will not be present. - By making use of L methods which expect address params as arguments, you can access Section/Question/Answer items in order by iterating over surveyOrder. @@ -590,6 +593,23 @@ A variable name to match against all section and question variable names. sub processGoto { my $self = shift; my ($goto) = validate_pos(@_, {type => SCALAR}); + + if ($goto eq 'NEXT_SECTION') { + $self->session->log->debug("NEXT_SECTION jump target encountered"); + my $lastResponseSectionIndex = $self->lastResponseSectionIndex; + + # Increment lastRepsonse until nextResponseSectionIndex moves + while ($self->nextResponseSectionIndex == $lastResponseSectionIndex) { + $self->lastResponse( $self->lastResponse + 1); + } + return; + } + + if ($goto eq 'END_SURVEY') { + $self->session->log->debug("END_SURVEY jump target encountered"); + $self->lastResponse( scalar( @{ $self->surveyOrder} ) - 1 ); + return; + } # Iterate over items in order.. my $itemIndex = 0; diff --git a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm index 57b6856e8..ca74c70d7 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm @@ -414,16 +414,17 @@ Generates the list of valid goto targets sub getGotoTargets { my $self = shift; - # Valid goto targets are all of the section variable names.. - my @section_vars = map {$_->{variable}} @{$self->sections}; + # Valid goto targets are all of the non-empty section variable names.. + my @section_vars = grep { $_ ne q{} } map {$_->{variable}} @{$self->sections}; - # ..and all of the question variable names.. - my @question_vars = map {$_->{variable}} @{$self->questions}; + # ..and all of the non-empty question variable names.. + my @question_vars = grep { $_ ne q{} } map {$_->{variable}} @{$self->questions}; - # ..excluding the ones that are empty - my @grep = grep { $_ ne q{} } (@section_vars, @question_vars); - return \@grep; - #return grep { $_ ne q{} } (@section_vars, @question_vars); + # ..plus some special vars + my @special_vars = qw(NEXT_SECTION END_SURVEY); + + # ..all combined + return [ @section_vars, @question_vars, @special_vars ]; } =head2 getSectionEditVars ( $address ) diff --git a/t/Asset/Wobject/Survey/ResponseJSON.t b/t/Asset/Wobject/Survey/ResponseJSON.t index 83e65f06a..fb84d8091 100644 --- a/t/Asset/Wobject/Survey/ResponseJSON.t +++ b/t/Asset/Wobject/Survey/ResponseJSON.t @@ -22,7 +22,7 @@ my $session = WebGUI::Test->session; #---------------------------------------------------------------------------- # Tests -my $tests = 75; +my $tests = 81; plan tests => $tests + 1; #---------------------------------------------------------------------------- @@ -352,42 +352,81 @@ cmp_deeply($rJSON->responseScoresByVariableName, { s1q0 => 100, s1q1 => 200, s1 # Turn on the survey Expression Engine WebGUI::Test->originalConfig('enableSurveyExpressionEngine'); $session->config->set('enableSurveyExpressionEngine', 1); -$rJSON->survey->section([0])->{variable} = 's0'; # our first test jump target -$rJSON->survey->section([2])->{variable} = 's2'; # our second test jump target -$rJSON->survey->question([1,0])->{variable} = 's1q0'; # a question variable to use in our expressions -$rJSON->survey->answer([1,0,0])->{recordedAnswer} = 3; # value recorded in responses hash for multi-choice answer +$rJSON->survey->section([0])->{variable} = 's0'; +$rJSON->survey->question([0,0])->{variable} = 's0q0'; # surveyOrder index = 0 +$rJSON->survey->question([0,1])->{variable} = 's0q1'; # surveyOrder index = 1 +$rJSON->survey->question([0,2])->{variable} = 's0q2'; # surveyOrder index = 2 +$rJSON->survey->section([1])->{variable} = 's1'; +$rJSON->survey->question([1,0])->{variable} = 's1q0'; # surveyOrder index = 3 +$rJSON->survey->question([1,1])->{variable} = 's1q1'; # surveyOrder index = 4 +$rJSON->survey->section([2])->{variable} = 's2'; # empty section appears as surveyOrder index = 5 +$rJSON->survey->section([3])->{variable} = 's3'; +$rJSON->survey->question([3,0])->{variable} = 's3q0'; # surveyOrder index = 6 +$rJSON->survey->question([3,1])->{variable} = 's3q1'; # surveyOrder index = 7 +$rJSON->survey->question([3,2])->{variable} = 's3q2'; # surveyOrder index = 8 -$rJSON->lastResponse(2); +$rJSON->survey->answer([0,0,0])->{recordedAnswer} = 3; # value recorded in responses hash for multi-choice answer +$rJSON->survey->answer([0,0,0])->{value} = 100; # set answer score +$rJSON->survey->answer([0,1,0])->{value} = 200; # set answer score + +# Reset responses and record first answer +$rJSON->lastResponse(-1); $rJSON->recordResponses({ - '1-0comment' => 'Section 1, question 0 comment', - '1-0-0' => 'My chosen answer', - '1-0-0comment' => 'Section 1, question 0, answer 0 comment', + '0-0-0' => 'I chose the first answer to s0q0', + '0-1-0' => 'I chose the first answer to s0q1', }); -is($rJSON->lastResponse, 4, 'lastResponse at 4 before any gotoExpressions processed'); + +is($rJSON->nextResponse, 2, 'nextResponse at 2 (s0q1) after first response'); $rJSON->processGotoExpression('blah-dee-blah-blah {'); -is($rJSON->lastResponse, 4, '..unchanged after duff expression'); +is($rJSON->nextResponse, 2, '..unchanged after duff expression'); -$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0'); -is($rJSON->lastResponse, 4, '..unchanged after false expression'); +$rJSON->processGotoExpression('jump { value(s0q0) == 4} s1'); +is($rJSON->nextResponse, 2, '..unchanged after false expression'); -$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0; jump { value(s1q0) == 5} s0;'); -is($rJSON->lastResponse, 4, '..similarly for multi-statement false expression'); +$rJSON->processGotoExpression('jump { value(s0q0) == 4} s0; jump { value(s1q0) == 5} s1;'); +is($rJSON->nextResponse, 2, '..similarly for multi-statement false expression'); -$rJSON->processGotoExpression('jump { value(s1q0) == 3} DUFF_TARGET'); -is($rJSON->lastResponse, 4, '..similarly for expression with invalid target'); +$rJSON->processGotoExpression('jump { value(s0q0) == 3} DUFF_TARGET'); +is($rJSON->nextResponse, 2, '..similarly for expression with invalid target'); -$rJSON->processGotoExpression('jump { value(s1q0) == 3} s0'); -is($rJSON->lastResponse, -1, '..but updated to s0 after true expression'); +$rJSON->processGotoExpression('jump { value(s0q0) == 3} s1'); +is($rJSON->nextResponse, 3, 'jumps to index of first question in section'); -$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0; jump { value(s1q0) == 3} s2'); -is($rJSON->lastResponse, 4, '..changed again for multi-statement true expression'); +$rJSON->processGotoExpression('jump { value(s0q0) == 3} s2'); +is($rJSON->nextResponse, 5, '..and updated to s2 with different jump target'); -$rJSON->processGotoExpression('jump { score(s1q0) == 100} s0'); -is($rJSON->lastResponse, -1, '..and again when score used'); +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { value(s0q0) == 3} s3'); +is($rJSON->nextResponse, 6, '..and updated to s3 with different jump target'); -$rJSON->processGotoExpression('jump { score("s1") == 300} s2'); -is($rJSON->lastResponse, 4, '..and again when section score total used'); +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { value(s0q0) == 3} s3q1'); +is($rJSON->nextResponse, 7, '..we can also jump to a question rather than a section'); + +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { value(s0q0) == 3} NEXT_SECTION'); +is($rJSON->nextResponse, 3, '..we can also use the NEXT_SECTION target'); + +$rJSON->lastResponse(3); # pretend we just finished s1q0 +$rJSON->processGotoExpression('jump { value(s0q0) == 3} NEXT_SECTION'); +is($rJSON->nextResponse, 5, '..try that again from a different starting point'); + +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { value(s0q0) == 3} END_SURVEY'); +is($rJSON->nextResponse, 9, '..we can also jump to end with END_SURVEY target'); + +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { value(s0q0) == 4} s0; jump { value(s0q0) == 3} s1'); +is($rJSON->nextResponse, 3, '..first true statement wins'); + +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { score(s0q0) == 100} s1'); +is($rJSON->nextResponse, 3, '..and again when score used'); + +$rJSON->nextResponse(2); # pretend we just finished s0q2 +$rJSON->processGotoExpression('jump { score("s0") == 300} s1'); +is($rJSON->nextResponse, 3, '..and again when section score total used'); $rJSON->responses({}); $rJSON->questionsAnswered(-1 * $rJSON->questionsAnswered);