2018-01-16 06:58:15 +01:00
# -*- coding: utf-8 -*-
2018-01-16 11:34:37 +01:00
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
2018-01-16 06:58:15 +01:00
import random
import re
from collections import Counter
from itertools import product
from werkzeug import urls
2018-01-16 11:34:37 +01:00
from flectra import _
from flectra . addons . http_routing . models . ir_http import slug
from flectra . exceptions import UserError
from flectra . tests . common import TransactionCase
2018-01-16 06:58:15 +01:00
class TestSurvey ( TransactionCase ) :
def setUp ( self ) :
super ( TestSurvey , self ) . setUp ( )
User = self . env [ ' res.users ' ] . with_context ( { ' no_reset_password ' : True } )
( group_survey_user , group_employee ) = ( self . ref ( ' survey.group_survey_user ' ) , self . ref ( ' base.group_user ' ) )
self . survey_manager = User . create ( {
' name ' : ' Gustave Doré ' , ' login ' : ' Gustav ' , ' email ' : ' gustav.dore@example.com ' ,
' groups_id ' : [ ( 6 , 0 , [ self . ref ( ' survey.group_survey_manager ' ) , group_survey_user , group_employee ] ) ] } )
self . survey_user = User . create ( {
' name ' : ' Lukas Peeters ' , ' login ' : ' Lukas ' , ' email ' : ' lukas.petters@example.com ' ,
' groups_id ' : [ ( 6 , 0 , [ group_survey_user , group_employee ] ) ] } )
self . user_public = User . create ( {
' name ' : ' Wout Janssens ' , ' login ' : ' Wout ' , ' email ' : ' wout.janssens@example.com ' ,
' groups_id ' : [ ( 6 , 0 , [ self . ref ( ' base.group_public ' ) ] ) ] } )
self . survey1 = self . env [ ' survey.survey ' ] . sudo ( self . survey_manager ) . create ( { ' title ' : " S0 " , ' page_ids ' : [ ( 0 , 0 , { ' title ' : " P0 " } ) ] } )
self . page1 = self . survey1 . page_ids [ 0 ]
def test_00_create_minimal_survey ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( { ' page_id ' : self . page1 . id , ' question ' : ' Q0 ' } )
self . assertEqual ( self . survey1 . title , " S0 " , msg = " Title of the survey is somehow modified. " )
self . assertEqual ( len ( self . survey1 . page_ids ) , 1 , msg = " Additional Pages are linked with the survey after creation. " )
self . assertEqual ( self . page1 . title , " P0 " , msg = " Title of the page is somehow modified. " )
self . assertEqual ( len ( self . page1 . question_ids ) , 1 , msg = " Additional questions are linked with the page after creation. " )
self . assertEqual ( question . question , " Q0 " , msg = " Title of the Question is somehow modified. " )
def test_01_question_type_validation_save_line_function ( self ) :
for ( question_type , text ) in self . env [ ' survey.question ' ] . _fields [ ' type ' ] . selection :
# Each question ype must have validation function.
self . assertTrue ( hasattr ( self . env [ ' survey.question ' ] , ' validate_ ' + question_type ) , msg = " Question must have a validation method in \
the form of ' validate_ ' followed by the name of the type . " )
# Survey Input Lines must have validation function for each line.
self . assertTrue ( hasattr ( self . env [ ' survey.user_input_line ' ] , ' save_line_ ' + question_type ) , msg = " Inputline must have Save method in \
the form of ' save_line_ ' followed by the name of the type . " )
def test_02_question_answer_required ( self ) :
for ( question_type , text ) in self . env [ ' survey.question ' ] . _fields [ ' type ' ] . selection :
# Blank value of field is not accepted for mandatory questions.
if question_type == ' multiple_choice ' :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' multiple_choice ' ,
' constr_mandatory ' : True , ' constr_error_msg ' : ' Error ' ,
' labels_ids ' : [ ( 0 , 0 , { ' value ' : " MChoice0 " , " quizz_mark " : 0 } ) , ( 0 , 0 , { ' value ' : " MChoice1 " , " quizz_mark " : 0 } ) ] } )
elif question_type == ' matrix ' :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' matrix ' , ' matrix_subtype ' : ' simple ' ,
' constr_mandatory ' : True , ' constr_error_msg ' : ' Error ' ,
' labels_ids ' : [ ( 0 , 0 , { ' value ' : " Column0 " , " quizz_mark " : 0 } ) , ( 0 , 0 , { ' value ' : " Column1 " , " quizz_mark " : 0 } ) ] ,
' labels_ids_2 ' : [ ( 0 , 0 , { ' value ' : " Row0 " , " quizz_mark " : 0 } ) , ( 0 , 0 , { ' value ' : " Row1 " , " quizz_mark " : 0 } ) ] } )
else :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : question_type , ' constr_mandatory ' : True , ' constr_error_msg ' : ' Error ' } )
answer_tag = ' %s _ %s _ %s ' % ( self . survey1 . id , self . page1 . id , question . id )
self . assertDictEqual ( { answer_tag : " Error " } , question . validate_question ( { answer_tag : ' ' } , answer_tag ) ,
msg = ( " Validation function for type %s is unable to generate error if it is mandatory and answer is blank. " % question_type ) )
def test_03_question_textbox ( self ) :
questions = [
self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' textbox ' , ' validation_email ' : True } ) ,
self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q1 ' , ' type ' : ' textbox ' , ' validation_required ' : True ,
' validation_length_min ' : 2 , ' validation_length_max ' : 8 , ' validation_error_msg ' : " Error " } ) ]
results = [ ( ' test @ testcom ' , _ ( ' This answer must be an email address ' ) ) , ( ' t ' , ' Error ' ) ]
for i in range ( len ( questions ) ) :
answer_tag = ' %s _ %s _ %s ' % ( self . survey1 . id , self . page1 . id , questions [ i ] . id )
self . assertEqual ( questions [ i ] . validate_question ( { answer_tag : results [ i ] [ 0 ] } , answer_tag ) , { answer_tag : results [ i ] [ 1 ] } , msg = " \
Validation function for textbox is unable to notify if answer is violating the validation rules " )
def test_04_question_numerical_box ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' numerical_box ' , ' validation_required ' : True ,
' validation_min_float_value ' : 2.1 , ' validation_max_float_value ' : 3.0 , ' validation_error_msg ' : " Error " } )
answer_tag = ' %s _ %s _ %s ' % ( self . survey1 . id , self . page1 . id , question . id )
results = [ ( ' aaa ' , _ ( ' This is not a number ' ) ) , ( ' 4.5 ' , ' Error ' ) , ( ' 0.1 ' , ' Error ' ) ]
for i in range ( len ( results ) ) :
self . assertEqual ( question . validate_question ( { answer_tag : results [ i ] [ 0 ] } , answer_tag ) , { answer_tag : results [ i ] [ 1 ] } , msg = " \
Validation function for type numerical_box is unable to notify if answer is violating the validation rules " )
def test_05_question_date ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' date ' , ' validation_required ' : True ,
' validation_min_date ' : ' 2015-03-20 ' , ' validation_max_date ' : ' 2015-03-25 ' , ' validation_error_msg ' : " Error " } )
answer_tag = ' %s _ %s _ %s ' % ( self . survey1 . id , self . page1 . id , question . id )
results = [ ( ' 2015-55-10 ' , _ ( ' This is not a date ' ) ) , ( ' 2015-03-19 ' , ' Error ' ) , ( ' 2015-03-26 ' , ' Error ' ) ]
for i in range ( len ( results ) ) :
self . assertEqual ( question . validate_question ( { answer_tag : results [ i ] [ 0 ] } , answer_tag ) , { answer_tag : results [ i ] [ 1 ] } , msg = " \
Validation function for type date is unable to notify if answer is violating the validation rules " )
def test_06_survey_sharing ( self ) :
# Case-1: Executing action with correct data.
correct_survey = self . env [ ' survey.survey ' ] . sudo ( self . survey_manager ) . create ( {
' title ' : " S0 " , ' stage_id ' : self . env [ ' survey.stage ' ] . search ( [ ( ' sequence ' , ' = ' , 1 ) ] ) . id ,
' page_ids ' : [ ( 0 , 0 , { ' title ' : " P0 " , ' question_ids ' : [ ( 0 , 0 , { ' question ' : " Q0 " , ' type ' : ' free_text ' } ) ] } ) ] } )
action = correct_survey . action_send_survey ( )
template = self . env . ref ( ' survey.email_template_survey ' , raise_if_not_found = False )
ctx = dict (
self . env . context ,
default_model = ' survey.survey ' ,
default_res_id = correct_survey . id ,
default_survey_id = correct_survey . id ,
default_use_template = bool ( template ) ,
default_template_id = template and template . id or False ,
default_composition_mode = ' comment ' )
self . assertDictEqual ( action , {
' type ' : ' ir.actions.act_window ' ,
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' survey.mail.compose.message ' ,
' target ' : ' new ' ,
' context ' : ctx ,
} )
# Case-2: Executing action with incorrect data.
surveys = [
self . env [ ' survey.survey ' ] . sudo ( self . survey_manager ) . create ( { # Survey without any page or question.
' title ' : " Test survey " } ) ,
self . env [ ' survey.survey ' ] . sudo ( self . survey_manager ) . create ( { # Closed Survey.
' title ' : " S0 " , ' stage_id ' : self . env [ ' survey.stage ' ] . search ( [ ( ' closed ' , ' = ' , True ) ] ) . id , # Getting Closed stage id.
' page_ids ' : [ ( 0 , 0 , { ' title ' : " P0 " , ' question_ids ' : [ ( 0 , 0 , { ' question ' : " Q0 " , ' type ' : ' free_text ' } ) ] } ) ] } ) ]
for survey in surveys :
self . assertRaises ( UserError , survey . action_send_survey )
def test_07_survey_email_message ( self ) :
# Case-1: Executing send_mail with correct data.
partner = self . env [ ' res.partner ' ] . create ( { ' name ' : ' Marie De Cock ' , ' email ' : ' marie.de.cock@gmail.com ' } )
survey_mail_message = self . env [ ' survey.mail.compose.message ' ] . sudo ( self . survey_manager ) . create ( {
' survey_id ' : self . survey1 . id , ' public ' : ' email_public_link ' , ' body ' : ' __URL__ ' , ' partner_ids ' : [ ( 4 , partner . id ) ] } )
survey_mail_message . send_mail ( )
# Case-2: Executing send_mail with incorrect data.
mail_messages = [
self . env [ ' survey.mail.compose.message ' ] . sudo ( self . survey_manager ) . create ( { # Mail Message without __URL__ in body.
' survey_id ' : self . survey1 . id , ' public ' : ' email_public_link ' } ) ,
self . env [ ' survey.mail.compose.message ' ] . sudo ( self . survey_manager ) . create ( { # Mail Message without recipents.
' survey_id ' : self . survey1 . id , ' public ' : ' email_public_link ' , ' body ' : " __URL__ " } ) ]
for message in mail_messages :
self . assertRaises ( UserError , message . send_mail )
def test_08_survey_urls ( self ) :
def validate_url ( url ) :
""" Reference: https://github.com/django/django/blob/master/django/core/validators.py """
url_regex = re . compile (
r ' ^https?:// ' # http:// or https://
r ' (?:(?:[A-Z0-9](?:[A-Z0-9-] { 0,61}[A-Z0-9])? \ .)+(?:[A-Z] { 2,6} \ .?|[A-Z0-9-] { 2,} \ .?)| ' # domain...
r ' localhost| ' # localhost...
r ' \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3}| ' # ...or ipv4
r ' \ [?[A-F0-9]*:[A-F0-9:]+ \ ]?) ' # ...or ipv6
r ' (?:: \ d+)? ' # optional port
r ' (?:/?|[/?] \ S+)$ ' , re . IGNORECASE )
return True if url_regex . match ( url ) else False
base_url = self . env [ ' ir.config_parameter ' ] . get_param ( ' web.base.url ' )
urltypes = { ' public ' : ' start ' , ' print ' : ' print ' , ' result ' : ' results ' }
for urltype , urltxt in urltypes . items ( ) :
survey_url = getattr ( self . survey1 , urltype + ' _url ' )
survey_url_relative = getattr ( self . survey1 . with_context ( { ' relative_url ' : True } ) , urltype + ' _url ' )
self . assertTrue ( validate_url ( survey_url ) )
url = " survey/ %s / %s " % ( urltxt , slug ( self . survey1 ) )
full_url = urls . url_join ( base_url , url )
self . assertEqual ( full_url , survey_url )
self . assertEqual ( ' / ' + url , survey_url_relative )
if urltype == ' public ' :
url_html = ' <a href= " %s " >Click here to start survey</a> '
self . assertEqual ( url_html % full_url , getattr ( self . survey1 , urltype + ' _url_html ' ) , msg = " Public URL is incorrect " )
self . assertEqual ( url_html % ( ' / ' + url ) , getattr ( self . survey1 . with_context ( { ' relative_url ' : True } ) , urltype + ' _url_html ' ) , msg = " Public URL is incorrect. " )
def test_09_answer_survey ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( { ' page_id ' : self . page1 . id , ' question ' : ' Q0 ' } )
input_portal = self . env [ ' survey.user_input ' ] . sudo ( self . survey_user ) . create ( {
' survey_id ' : self . survey1 . id ,
' partner_id ' : self . survey_user . partner_id . id ,
' user_input_line_ids ' : [ ( 0 , 0 , {
' skipped ' : False , ' answer_type ' : ' free_text ' , ' value_free_text ' : " Test Answer " ,
' survey_id ' : self . survey1 . id , ' question_id ' : question . id } ) ] } )
input_public = self . env [ ' survey.user_input ' ] . sudo ( self . user_public ) . create ( {
' survey_id ' : self . survey1 . id ,
' partner_id ' : self . survey_user . partner_id . id ,
' user_input_line_ids ' : [ ( 0 , 0 , {
' skipped ' : False , ' answer_type ' : ' free_text ' , ' value_free_text ' : " Test Answer " ,
' survey_id ' : self . survey1 . id , ' question_id ' : question . id } ) ] } )
answers = [ input_portal . user_input_line_ids [ 0 ] , input_public . user_input_line_ids [ 0 ] ]
expected_values = { ' answer_type ' : ' free_text ' , ' value_free_text ' : " Test Answer " }
for answer in answers :
for field , value in expected_values . items ( ) :
self . assertEqual ( answer [ field ] , value , msg = " Unable to answer the survey. Expected behaviour of %s is not proper. " % ( field ) )
def test_10_survey_result_simple_multiple_choice ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' simple_choice ' ,
' labels_ids ' : [ ( 0 , 0 , { ' value ' : " Choice0 " , ' quizz_mark ' : 0 } ) , ( 0 , 0 , { ' value ' : " Choice1 " , ' quizz_mark ' : 0 } ) ] } )
for i in range ( 3 ) :
self . env [ ' survey.user_input ' ] . sudo ( self . user_public ) . create ( { ' survey_id ' : self . survey1 . id , ' user_input_line_ids ' : [ ( 0 , 0 , {
' question_id ' : question . id ,
' answer_type ' : ' suggestion ' ,
' value_suggested ' : random . choice ( question . labels_ids . ids ) } ) ] } )
lines = [ line . value_suggested . id for line in question . user_input_line_ids ]
answers = [ { ' text ' : label . value , ' count ' : lines . count ( label . id ) , ' answer_id ' : label . id } for label in question . labels_ids ]
prp_result = self . env [ ' survey.survey ' ] . prepare_result ( question ) [ ' answers ' ]
self . assertItemsEqual ( prp_result , answers , msg = " Statistics of simple, multiple choice questions are different from expectation " )
def test_11_survey_result_matrix ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( {
' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' matrix ' , ' matrix_subtype ' : ' simple ' ,
' labels_ids ' : [ ( 0 , 0 , { ' value ' : " Column0 " , " quizz_mark " : 0 } ) , ( 0 , 0 , { ' value ' : " Column1 " , " quizz_mark " : 0 } ) ] ,
' labels_ids_2 ' : [ ( 0 , 0 , { ' value ' : " Row0 " , " quizz_mark " : 0 } ) , ( 0 , 0 , { ' value ' : " Row1 " , " quizz_mark " : 0 } ) ] } )
for i in range ( 3 ) :
self . env [ ' survey.user_input ' ] . sudo ( self . user_public ) . create ( { ' survey_id ' : self . survey1 . id , ' user_input_line_ids ' : [ ( 0 , 0 , {
' question_id ' : question . id , ' answer_type ' : ' suggestion ' , ' value_suggested ' : random . choice ( question . labels_ids . ids ) ,
' value_suggested_row ' : random . choice ( question . labels_ids_2 . ids ) } ) ] } )
lines = [ ( line . value_suggested_row . id , line . value_suggested . id ) for line in question . user_input_line_ids ]
res = { }
for i in product ( question . labels_ids_2 . ids , question . labels_ids . ids ) :
res [ i ] = lines . count ( ( i ) )
self . assertEqual ( self . env [ ' survey.survey ' ] . prepare_result ( question ) [ ' result ' ] , res , msg = " Statistics of matrix type questions are different from expectations " )
def test_12_survey_result_numeric_box ( self ) :
question = self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( { ' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' numerical_box ' } )
num = [ float ( n ) for n in random . sample ( range ( 1 , 100 ) , 3 ) ]
nsum = sum ( num )
for i in range ( 3 ) :
self . env [ ' survey.user_input ' ] . sudo ( self . user_public ) . create ( { ' survey_id ' : self . survey1 . id , ' user_input_line_ids ' : [ ( 0 , 0 , {
' question_id ' : question . id , ' answer_type ' : ' number ' , ' value_number ' : num [ i ] } ) ] } )
exresult = {
' average ' : round ( ( nsum / len ( num ) ) , 2 ) , ' max ' : round ( max ( num ) , 2 ) ,
' min ' : round ( min ( num ) , 2 ) , ' sum ' : nsum , ' most_common ' : Counter ( num ) . most_common ( 5 ) }
result = self . env [ ' survey.survey ' ] . prepare_result ( question )
for key in exresult :
self . assertEqual ( result [ key ] , exresult [ key ] , msg = " Statistics of numeric box type questions are different from expectations " )
def test_13_survey_actions ( self ) :
self . env [ ' survey.question ' ] . sudo ( self . survey_manager ) . create ( { ' page_id ' : self . page1 . id , ' question ' : ' Q0 ' , ' type ' : ' numerical_box ' } )
actions = {
' start ' : { ' method ' : ' public ' , ' token ' : ' /test ' , ' text ' : ' Start ' } ,
' print ' : { ' method ' : ' print ' , ' token ' : ' /test ' , ' text ' : ' Print ' } ,
' result ' : { ' method ' : ' result ' , ' token ' : ' ' , ' text ' : ' Results of the ' } ,
' test ' : { ' method ' : ' public ' , ' token ' : ' /phantom ' , ' text ' : ' Results of the ' } }
for action , val in actions . items ( ) :
result = getattr ( self . survey1 . with_context ( { ' survey_token ' : val [ ' token ' ] [ 1 : ] } ) , ' action_ ' + action + ' _survey ' ) ( )
url = getattr ( self . survey1 . with_context ( { ' relative_url ' : True } ) , val [ ' method ' ] + ' _url ' ) + val [ ' token ' ]
self . assertEqual ( result [ ' url ' ] , url )