def test_should_return_correct_date_format_for_year_or_monthyear_appearance_combined_With_other_appearance(self):
     with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
         fields = {'children': [
             {u'type': u'date', u'name': u'birth_date', u'label': u'1. What is your date of birth?',
              u'control': {u'appearance': u'w2 year'}},
             {u'type': u'date', u'name': u'birth_date2', u'label': u'2. What is your date of birth?',
              u'control': {u'appearance': u'w4 horizontal month-year'}}]}
         xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
         self.assertEquals('yyyy', xls_form_parser._get_date_format(fields['children'][0]))
         self.assertEquals('mm.yyyy', xls_form_parser._get_date_format(fields['children'][1]))
    def test_should_return_default_date_format_for_any_other_appearance(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {'children': [
                {u'type': u'date', u'name': u'birth_date', u'label': u'1. What is your date of birth?',
                 u'control': {u'appearance': u'w4'}
                }]}
            get_xform_dict.return_value = fields

            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
            self.assertEquals('dd.mm.yyyy', xls_form_parser._get_date_format(fields['children'][0]))
    def test_sequence_of_the_mixed_type_fields_in_from_model_should_be_same_as_xlsform(self):
        parser = XlsFormParser(self.REPEAT, "My questionnaire")

        xls_parser_response = parser.parse()

        names = [f['code'] if f['type'] != 'field_set' else self._repeat_codes(f) for f in xls_parser_response.json_xform_data]
        expected_names = ['familyname',
                          ['family',['name','age']],
                          'city',
                          ['house',['name','room','numberofrooms']]]
        self.assertEqual(names, expected_names)
    def test_should_populate_error_when_constraint_not_given_for_dw_idnr_question(self):
        with patch('datawinners.blue.xform_bridge.entity_type_already_defined') as is_entity_type_already_defined:
            with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
                xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
                fields = [{u'name': u'my_unique', u'label': u'mu_uni', u'type': u'dw_idnr'}]

                get_xform_dict.return_value = fields
                is_entity_type_already_defined.return_value = True
                questions, errors, unique_id_errors = xls_form_parser._create_questions(fields)

                self.assertEqual(questions.__len__(), 0)
                self.assertEqual(errors, {
                    u"The Identification Number Type (dw_idnr) is missing in the Constraints column. Please add the Identification Number Type and upload again. <a target='_blank'>Learn More</a> about how to manage Identification Numbers with XLSForms. "})
 def test_should_populate_error_when_label_defined_in_single_explict_language(self):
     with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
         xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
         fields = {'children': [{u'bind': {u'required': u'yes'}, u'type': u'text', u'name': u'name',
                                 u'label': {u'english': u'1. What is your name?'}},
                                {u'bind': {u'required': u'yes'}, u'type': u'integer', u'name': u'age',
                                 u'label': {u'english': u'2. What is your age?'}},
                                {u'bind': {u'required': u'yes'}, u'type': u'text', u'name': u'new_loc',
                                 u'label': {u'english': u'1. What is your new loc?'}},
                                {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                    {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                     'type': 'calculate', 'name': 'instanceID'}]}]}
         get_xform_dict.return_value = fields
         actual_errors = xls_form_parser._validate_fields_are_recognised(fields['children'])
         self.assertEquals(actual_errors, {"XLSForm language settings."})
    def test_should_convert_multi_select_question(self):
        xls_parser_response = XlsFormParser(self.MULTI_SELECT, u"My questionnairé").parse()

        mangroveService = MangroveService(self.mock_request, xls_parser_response=xls_parser_response)
        questionnaire_id = mangroveService.create_project()

        self.assertIsNotNone(questionnaire_id)
Example #7
0
    def test_all_fields_types_in_xlsform_is_converted_to_json(self):

        xls_parser_response = XlsFormParser(self.ALL_FIELDS,
                                            "My questionnaire").parse()

        expected_json = \
            [{"code": "name", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a word", "name": "What is your name?", "parent_field_code": None, "title": "What is your name?", "default": None, "hint": None, "appearance": None, "required": True, "type": "text"},
                # repeat
             {"code": "education", "is_entity_question": False, "relevant": None, "fieldset_type": "repeat", "name": "Education", "parent_field_code": None, "title": "Education", "default": None,
              "fields": [{"code": "degree", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a word", "name": "Degree name", "parent_field_code": "education", "title": "Degree name", "default": None, "hint": None, "appearance": None, "required": True, "type": "text"},
                         {"code": "completed_on", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a date in the following format: day.month.year. Example: 25.12.2011", "event_time_field_flag": False, "date_format": "dd.mm.yyyy", "name": "Degree completion year", "parent_field_code": "education", "title": "Degree completion year", "default": None, "hint": None, "appearance": None, "required": True, "type": "date"}],
                            "instruction": "No answer required", "appearance": None, "required": False, "type": "field_set"},
                # end repeat
             {"code": "age", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a number", "name": "What is your age?", "parent_field_code": None, "title": "What is your age?", "default": None, "hint": None, "appearance": None, "required": False, "type": "integer"},
             {"code": "height", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a decimal or number", "name": "What is your height?", "parent_field_code": None, "title": "What is your height?", "default": None, "hint": None, "appearance": None, "required": False, "type": "integer"},
             {"code": "fav_color", "constraint_message": None, "is_cascade": False, "has_other": False, "required": True, "xform_constraint": None, "relevant": None, "parent_field_code": None, "title": "Which colors you like?", "default": None, "hint": None, "appearance": None,
              "choices": [{"value": {"text": "Red", "val": "a"}},
                          {"value": {"text": "Blue", "val": "b"}},
                          {"value": {"text": "Green", "val": "c"}}], "is_entity_question": False, "type": "select"},
                #group
             {"code": "pizza_test_group", "is_entity_question": False, "relevant": None, "fieldset_type": "group", "name": "Pizza fan", "parent_field_code": None, "title": "Pizza fan", "default": None,
              "fields": [{"code": "pizza_fan", "constraint_message": None, "is_cascade": False, "has_other": False, "required": True, "xform_constraint": None, "relevant": None, "parent_field_code": "pizza_test_group", "title": "Do you like pizza?", "default": None, "hint": None, "appearance": None,
                          "choices": [{"value": {"text": "Yes", "val": "a"}}, {"value": {"text": "No", "val": "b"}}],
                          "is_entity_question": False, "type": "select1"},
                            #group
                         {"code": "like_group", "is_entity_question": False, "relevant": None, "fieldset_type": "group", "name": "Like group", "parent_field_code": "pizza_test_group", "title": "Like group", "default": None,
                          "fields": [{"code": "other", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": "${pizza_fan} = 'b'", "instruction": "Answer must be a word", "name": "What else you like?", "parent_field_code": "like_group", "title": "What else you like?", "default": None, "hint": None, "appearance": None,
                                      "required": False, "type": "text"}, {"code": "pizza_type", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": "${pizza_fan} = 'a'", "instruction": "Answer must be a word", "name": "Which pizza type you like?", "parent_field_code": "like_group", "title": "Which pizza type you like?", "default": None, "hint": None, "appearance": None, "required": False, "type": "text"}], "instruction": "No answer required", "appearance": None, "required": False, "type": "field_set"}], "instruction": "No answer required", "appearance": None, "required": False, "type": "field_set"},
             {"code": "location", "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a geopoint", "name": "Your location?", "parent_field_code": None, "title": "Your location?", "default": None, "hint": None, "appearance": None, "required": False, "type": "geocode"},
             {"code": "add_age_height", "is_calculated": True, "constraint_message": None, "is_entity_question": False, "xform_constraint": None, "relevant": None, "instruction": "Answer must be a calculated field", "name": "Age and height", "parent_field_code": None, "title": "Age and height", "default": None, "hint": None, "appearance": None, "required": False, "type": "text"},
             {"code": "ab", "constraint_message": None, "is_cascade": False, "has_other": False, "required": True, "xform_constraint": None, "relevant": None, "parent_field_code": None, "title": "A or B?", "default": None, "hint": None, "appearance": None,
              "choices": [{"value": {"text": "A", "val": "a"}}, {"value": {"text": "B", "val": "b"}}], "is_entity_question": False, "type": "select1"}]
        self.assertEqual(expected_json, xls_parser_response.json_xform_data)
        self.assertIsNotNone(xls_parser_response.xform_as_string)
    def test_should_convert_skip_logic_question(self):
        xls_parser_response = XlsFormParser(self.SKIP, u"My questionnairé").parse()

        mangroveService = MangroveService(self.mock_request, xls_parser_response=xls_parser_response)
        questionnaire_id = mangroveService.create_project()

        self.assertIsNotNone(questionnaire_id)
    def test_should_not_populate_errors_when_choice_answer_has_no_media_present(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {u'name': u'tmpGX1Ud_', u'title': u'tmpGX1Ud_', u'sms_keyword': u'tmpGX1Ud_',
                      u'default_language': u'default', u'id_string': u'tmpGX1Ud_', u'type': u'survey', u'children': [
                {u'choices': [{u'name': u'crow', u'label': u'crow'}, {u'name': u'eagle', u'label': u'Eagle'}],
                 u'label': u'What bird did you see?', u'type': u'select one', u'name': u'bird',
                 u'hint': u'Some birds have included images or audio.'},
                {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                    {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"}, 'type': 'calculate',
                     'name': 'instanceID'}]}]}
            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', u'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors, [])
    def test_should_create_project_using_xlsform_file(self):
        xls_parser_response = XlsFormParser(self.ALL_FIELDS, u"My questionnairé").parse()

        mangroveService = MangroveService(self.mock_request, xls_parser_response=xls_parser_response)
        quesionnaire_id = mangroveService.create_project()

        self.assertIsNotNone(quesionnaire_id)
    def test_sequence_of_the_fields_in_form_model_should_be_same_as_in_xlsform(self):

        xls_parser_response = XlsFormParser(self.MANY_FIELD, "My questionnaire").parse()

        self.assertIsNotNone(xls_parser_response.xform_as_string)
        names = [f['code'] for f in xls_parser_response.json_xform_data]
        expected_names = ["a312name1312","a528name2528","a972name3972","a667name4667","a868name5868","a970name6970","a870name7870","a320name8320","a863name9863","a509name10509","a191name11191","a216name12216","a320name13320","a165name14165","a116name15116","a413name16413","a568name17568","a379name18379","a863name19863","a929name20929","a640name21640","a392name22392","a264name23264","a868name24868","a191name25191","a316name26316","a908name27908","a488name28488","a455name29455","a802name30802","a595name31595","a668name32668","a329name33329","a566name34566","a335name35335","a197name36197","a536name37536","a204name38204","a418name39418","a399name40399","a614name41614","a510name42510","a515name43515","a835name44835","a575name45575","a531name46531","a247name47247","a143name48143","a811name49811","a110name50110"]
        self.assertEqual(names, expected_names)
    def test_should_populate_error_when_settings_sheet_present_with_default_language(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {'children': [{u'bind': {u'required': u'no'}, u'type': u'text', u'name': u'college',
                                    u'label': u'College Name'},
                                   {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                       {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                        'type': 'calculate', 'name': 'instanceID'}]}],
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default_something'
            }
            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors,
                              {"XLSForm settings worksheet and the related values in survey sheet."})
    def test_should_populate_error_when_calculate_field_with_prefetch_present(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {'children': [
                {u'bind': {u'calculate': u'pulldata(fruit, "mangoes")'}, u'type': u'calculate', u'name': u'calc',
                 u'label': u'1. Are you a student?'},
                {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                    {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                     'type': 'calculate', 'name': 'instanceID'}]}],
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default'
            }
            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors, {"preloading of CSV data (the PullData() function)."})
    def test_xform_validation_for_nested_repeats_names(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
            fields = {
                'children': [{u'bind': {u'required': u'yes'}, u'type': u'text', u'name': u'name', u'label': u'Name'},
                             {u'children': [{u'children': [
                                 {u'bind': {u'required': u'no'}, u'type': u'text', u'name': u'college',
                                  u'label': u'College Name'}],
                                             u'type': u'repeat', u'name': u'some', u'label': u'some'}],
                              u'type': u'repeat',
                              u'name': u'highest_degree', u'label': u'degree'},
                             {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                 {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                  'type': 'calculate',
                                  'name': 'instanceID'}]}]}
            get_xform_dict.return_value = fields
            actual_errors = xls_form_parser._validate_fields_are_recognised(fields['children'])

            self.assertEqual(actual_errors, {"more than one level of repeated questions."})
    def test_should_verify_repeat_field_added_to_questionnaire(self):
        xls_parser_response = XlsFormParser(self.REPEAT, u"My questionnairé").parse()
        mangroveService = MangroveService(self.mock_request, xls_parser_response=xls_parser_response)
        mangroveService.create_project()

        questionnaire_code = mangroveService.questionnaire_code
        mgr = mangroveService.manager
        from_model = get_form_model_by_code(mgr, questionnaire_code)

        self.assertNotEqual([], [f for f in from_model.fields if type(f) is FieldSet and f.fields])
    def test_should_verify_field_is_not_mandatory_when_required_is_not_specified(self):
        xls_parser_response = XlsFormParser(self.REQUIRED, "My questionnaire").parse()

        root = ET.fromstring(xls_parser_response.xform_as_string)
        ET.register_namespace('', 'http://www.w3.org/2002/xforms')

        binds = [node.attrib.get('required') for node in root.iter('{http://www.w3.org/2002/xforms}bind')]

        self.assertEqual('true()', binds[0])
        self.assertEqual(None, binds[1])
    def test_should_not_populate_error_when_default_choice_for_multi_select_is_present_in_choice_list(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {'children': [{u'bind': {u'required': u'yes'}, u'type': u'select all that apply or specify other',
                                    'default': "yes no", u'name': u'is_student',
                                    u'label': u'1. Are you a student?',
                                    u'choices': [{u'name': u'yes', u'label': 'yes'},
                                                 {u'name': u'no', u'label': u'No'}]},
                                   {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                       {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                        'type': 'calculate', 'name': 'instanceID'}]}],
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default'
            }
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            errors = xls_form_parser._validate_choice_names(fields['children'])

            self.assertEquals(errors, [])
    def test_should_populate_error_when_choice_has_no_label(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {'children': [{u'bind': {u'required': u'yes'}, u'type': u'select one', u'name': u'is_student',
                                    u'label': u'1. Are you a student?',
                                    u'choices': [{u'name': u'yes'}, {u'name': u'no', u'label': u'No'}]},
                                   {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                       {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                        'type': 'calculate', 'name': 'instanceID'}]}],
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default'
            }
            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors,
                              {"optional labels. Label is a mandatory field for choice option with name [yes]"})
    def test_should_not_create_question_for_select_that_are_only_labels(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
            fields = [{u'control': {u'appearance': u'label'}, u'name': u'table_list_test_label',
                       u'hint': u'Show only the labels of these options and not the inputs (type=select_one yes_no, appearance=label)',
                       u'choices': [{u'name': u'yes', u'label': u'Yes'}, {u'name': u'no', u'label': u'No'},
                                    {u'name': u'dk', u'label': u"Don't Know"},
                                    {u'name': u'na', u'label': u'Not Applicable'}], u'label': u'Table',
                       u'type': u'select one'}, {u'control': {u'appearance': u'list-nolabel'}, u'name': u'table_list_1',
                                                 u'hint': u'Show only the inputs of these options and not the labels (type=select_one yes_no, appearance=list-nolabel)',
                                                 u'choices': [{u'name': u'yes', u'label': u'Yes'},
                                                              {u'name': u'no', u'label': u'No'},
                                                              {u'name': u'dk', u'label': u"Don't Know"},
                                                              {u'name': u'na', u'label': u'Not Applicable'}],
                                                 u'label': u'Q1', u'type': u'select one'},
                      {u'control': {u'appearance': u'list-nolabel'}, u'name': u'table_list_2',
                       u'hint': u'Show only the inputs of these options and not the labels (type=select_one yes_no, appearance=list-nolabel)',
                       u'choices': [{u'name': u'yes', u'label': u'Yes'}, {u'name': u'no', u'label': u'No'},
                                    {u'name': u'dk', u'label': u"Don't Know"},
                                    {u'name': u'na', u'label': u'Not Applicable'}], u'label': u'Question 2',
                       u'type': u'select one'}, {'control': {'bodyless': True}}]

            questions, errors, unique_id_errors = xls_form_parser._create_questions(fields)

            self.assertEqual(questions.__len__(), 2)
            self.assertDictEqual(questions[0], {'code': u'table_list_1', 'title': u'Q1', 'required': False,
                                                'parent_field_code': None,
                                                'has_other': False,
                                                'choices': [{'value': {'text': u'Yes', 'val': u'yes'}},
                                                            {'value': {'text': u'No', 'val': u'no'}},
                                                            {'value': {'text': u"Don't Know", 'val': u'dk'}},
                                                            {'value': {'text': u'Not Applicable', 'val': u'na'}}],
                                                'is_entity_question': False, 'type': 'select1'})
            self.assertDictEqual(questions[1], {'code': u'table_list_2', 'title': u'Question 2', 'required': False,
                                                'parent_field_code': None,
                                                'has_other': False,
                                                'choices': [{'value': {'text': u'Yes', 'val': u'yes'}},
                                                            {'value': {'text': u'No', 'val': u'no'}},
                                                            {'value': {'text': u"Don't Know", 'val': u'dk'}},
                                                            {'value': {'text': u'Not Applicable', 'val': u'na'}}],
                                                'is_entity_question': False, 'type': 'select1'})
    def test_should_create_entity_question_for_dw_idnr_question(self):
        with patch('datawinners.blue.xform_bridge.entity_type_already_defined') as is_entity_type_already_defined:
            with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
                manager = Mock(DatabaseManager)
                manager.view = Mock(View)
                manager.view.count_non_voided_entities_by_type = Mock(
                    return_value=[Row({'key': ['clinic'], 'value': 10})])
                xls_form_parser = XlsFormParser('some_path', 'questionnaire_name', dbm=manager)
                fields = [{u'name': u'my_unique',
                           u'bind': {u'constraint': u'clinic'}, u'label': u'mu_uni', u'type': u'dw_idnr'}]

                get_xform_dict.return_value = fields
                is_entity_type_already_defined.return_value = True
                questions, errors, unique_id_errors = xls_form_parser._create_questions(fields)

                self.assertEqual(questions.__len__(), 1)
                self.assertDictEqual(questions[0], {'instruction': 'Answer must be a Identification Number',
                                                    'code': u'my_unique', 'title': u'mu_uni', 'required': False,
                                                    'parent_field_code': None, 'name': u'mu_uni',
                                                    'is_entity_question': True, 'type': 'unique_id',
                                                    'uniqueIdType': u'clinic'})
    def test_should_populate_error_when_media_type_present_as_a_data_type(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {u'children': [{u'name': u'bird', u'hint': u'Some birds have included images or audio.',
                                     u'media': {u'audio': u'question.wav'},
                                     u'choices': [{u'name': u'eagle', u'label': u'Eagle'}],
                                     u'label': u'What bird did you see?', u'type': u'select one'},
                                    {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                                        {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"},
                                         'type': 'calculate', 'name': 'instanceID'}]}], u'type': u'repeat',
                      u'name': u'myrepeat', u'label': u'My repeat',
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default'
            }

            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors, {"XLSForm media type (audio) in survey sheet."})
    def test_should_populate_error_when_unsupported_geoshape_question_present_within_a_repeat(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            fields = {u'children': [
                {u'children': [
                    {u'bind': {u'required': u'yes'},
                     u'type': u'geoshape', u'name': u'timeq', u'label': u'Time q'},
                    {u'bind': {u'required': u'yes'}, u'type': u'datetime', u'name': u'datetq',
                     u'label': u'Date time q'}],
                 u'type': u'group', u'name': u'mygroup', u'label': u'My group'
                }], u'type': u'repeat', u'name': u'myrepeat', u'label': u'My repeat',
                      'title': 'asdasx',
                      'name': 'asdasx',
                      'id_string': 'asdasx',
                      'default_language': 'default'
            }

            get_xform_dict.return_value = fields
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')

            xls_parser_response = xls_form_parser.parse()

            self.assertEquals(xls_parser_response.errors, {"geoshape as a datatype"})
    def test_should_verify_xform_is_stored_when_project_created(self):

        manager = get_database_manager(self.user)
        questionnaire_code = generate_questionnaire_code(manager)
        project_name = 'xform-' + questionnaire_code

        xls_parser_response = XlsFormParser(self.REPEAT, u"My questionnairé").parse()

        mangrove_service = MangroveService(self.mock_request, project_name=project_name, xls_parser_response=xls_parser_response)
        mangrove_service.create_project()

        questionnaire_code = mangrove_service.questionnaire_code
        mgr = mangrove_service.manager
        from_model = get_form_model_by_code(mgr, questionnaire_code)
        self.assertIsNotNone(from_model.xform)
    def test_should_create_additional_text_question_for_single_select_or_other_question(self):
        with patch('datawinners.blue.xform_bridge.parse_file_to_json') as get_xform_dict:
            xls_form_parser = XlsFormParser('some_path', 'questionnaire_name')
            fields = [{u'choices': [{u'name': u'male', u'label': u'Male'}, {u'name': u'female', u'label': u'Female'}],
                       u'type': u'select one or specify other', u'name': u'hh_user_gender', u'label': u'Sex'},
                      {'control': {'bodyless': True}, 'type': 'group', 'name': 'meta', 'children': [
                          {'bind': {'readonly': 'true()', 'calculate': "concat('uuid:', uuid())"}, 'type': 'calculate',
                           'name': 'instanceID'}]}]

            questions, errors, unique_id_errors = xls_form_parser._create_questions(fields)

            self.assertEqual(questions.__len__(), 2)
            self.assertDictEqual(questions[0], {'code': u'hh_user_gender', 'title': u'Sex', 'required': False,
                                                'parent_field_code': None,
                                                'has_other': True,
                                                'choices': [{'value': {'text': u'Male', 'val': u'male'}},
                                                            {'value': {'text': u'Female', 'val': u'female'}}],
                                                'is_entity_question': False, 'type': 'select1'})
            self.assertDictEqual(questions[1],
                                 {'code': u'hh_user_gender_other', 'title': u'Sex_other', 'required': False,
                                  'parent_field_code': None,
                                  'name': u'Sex_other',
                                  'instruction': 'Answer must be a word',
                                  'is_entity_question': False, 'type': u'text'})
    def test_should_convert_cascaded_select_field(self):
        xls_parser_response = XlsFormParser(self.CASCADE, "My questionnaire").parse()

        expected_json = [{'code': 'name', 'name': 'What is your name?', 'title': 'What is your name?', 'required': False,
          'is_entity_question': False, 'instruction': 'Answer must be a word', 'parent_field_code': None, 'type': 'text'},
         {'code': 'respondent_district_counties', 'parent_field_code': None, 'title': 'Please select the county', 'required': False,
          'has_other': False,
          'choices': [{'value': {'text': 'Bomi', 'val': 'bomi'}},
                      {'value': {'text': 'Grand Bassa', 'val': 'grand_bassa'}}], 'is_entity_question': False,
          'type': 'select1'},
         {'code': 'respondent_district', 'parent_field_code': None, 'title': 'Please select the district', 'required': False,
          'has_other': False,
          'choices': [{'value': {'text': 'Klay', 'val': 'klay'}},
                      {'value': {'text': 'Commonwealth 1', 'val': 'commonwealth_1'}}], 'is_entity_question': False,
          'type': 'select1'}]

        self.assertEqual(expected_json, xls_parser_response.json_xform_data)
Example #26
0
    def test_all_fields_types_in_xlsform_is_converted_to_json(self):

        xls_parser_response = XlsFormParser(self.ALL_FIELDS,
                                            "My questionnaire").parse()

        expected_json = \
            [{'code': 'name', 'parent_field_code': None, 'name': 'What is your name?', 'title': 'What is your name?', 'required': True, 'is_entity_question': False, 'instruction': 'Answer must be a word', 'type': 'text'},
                # repeat
             {'code': 'education', 'parent_field_code': None, 'instruction': 'No answer required', 'name': 'Education', 'title': 'Education',
                'fields': [{'code': 'degree', 'parent_field_code': u'education', 'name': 'Degree name', 'title': 'Degree name', 'required': True, 'is_entity_question': False, 'instruction': 'Answer must be a word', 'type': 'text'},
                         {'code': 'completed_on', 'parent_field_code': u'education', 'date_format': 'dd.mm.yyyy', 'name': 'Degree completion year', 'title': 'Degree completion year', 'required': True, 'is_entity_question': False, 'instruction': 'Answer must be a date in the following format: day.month.year. Example: 25.12.2011','event_time_field_flag': False, 'type': 'date'}], 'is_entity_question': False,
                          'type': 'field_set', 'required': False, 'fieldset_type': 'repeat'},
                # end repeat
            {'code': 'age', 'parent_field_code': None, 'name': 'What is your age?', 'title': 'What is your age?', 'required': False, 'is_entity_question': False, 'instruction': 'Answer must be a number', 'type': 'integer'},
             {'code': 'height', 'parent_field_code': None, 'name': 'What is your height?', 'title': 'What is your height?', 'required': False, 'is_entity_question': False, 'instruction': 'Answer must be a decimal or number', 'type': 'integer'},
             {'code': 'fav_color', 'parent_field_code': None, 'title': 'Which colors you like?', 'required': True, 'has_other': False,
                'choices': [{'value':{'text': 'Red', 'val': 'a'}}, {'value': {'text': 'Blue', 'val': 'b'}},
                          {'value':{'text': 'Green', 'val': 'c'}}], 'is_entity_question': False, 'type': 'select'},
                #group
            {'code': u'pizza_test_group', 'parent_field_code': None, 'instruction': 'No answer required', 'name': u'Pizza fan', 'title': u'Pizza fan',
              'fields': [{'code': u'pizza_fan', 'parent_field_code': u'pizza_test_group', 'title': u'Do you like pizza?', 'required': True, 'has_other': False,
                          'choices': [{'value': {'text': u'Yes', 'val': u'a'}}, {'value': {'text': u'No', 'val': u'b'}}],
                          'is_entity_question': False, 'type': 'select1'},
                         #group
                         {'code': u'like_group', 'parent_field_code': u'pizza_test_group', 'instruction': 'No answer required', 'name': u'Like group', 'title': u'Like group',
                          'fields': [
                              {'code': u'other', 'parent_field_code': u'like_group', 'name': u'What else you like?', 'title': u'What else you like?', 'required': False,
                               'is_entity_question': False, 'instruction': 'Answer must be a word', 'type': u'text'},
                              {'code': u'pizza_type', 'parent_field_code': u'like_group', 'name': u'Which pizza type you like?', 'title': u'Which pizza type you like?',
                               'required': False, 'is_entity_question': False, 'instruction': 'Answer must be a word',
                               'type': u'text'}], 'is_entity_question': False, 'type': 'field_set', 'fieldset_type': 'group',
                          'required': False}], 'is_entity_question': False, 'type': 'field_set', 'fieldset_type': 'group', 'required': False},

             {'code': 'location', 'parent_field_code': None, 'name': 'Your location?', 'title': 'Your location?', 'required': False, 'is_entity_question': False, 'instruction': 'Answer must be a geopoint', 'type': 'geocode'},
             {'code': 'add_age_height', 'parent_field_code': None, 'name': 'Age and height', 'title': 'Age and height', 'required': False, 'is_calculated': True, 'is_entity_question': False, 'instruction': 'Answer must be a calculated field', 'type': 'text'},
             {'code': 'ab','parent_field_code': None, 'title': 'A or B?', 'required': True, 'has_other': False,
                'choices': [{'value':{'text': 'A', 'val': 'a'}}, {'value':{'text': 'B', 'val': 'b'}}], 'is_entity_question': False, 'type': 'select1'}]

        self.assertEqual(expected_json, xls_parser_response.json_xform_data)
        self.assertIsNotNone(xls_parser_response.xform_as_string)
Example #27
0
 def test_should_throw_error_for_invalid_field_type(self):
     xls_parser_response = XlsFormParser(self.INVALID_FIELDS,
                                         u"My questionnairé").parse()
     self.assertEqual(xls_parser_response.errors,
                      set(["dfdfd as a datatype"]))
Example #28
0
 def test_should_throw_error_for_unsupported_valid_field_type(self):
     xls_parser_response = XlsFormParser(self.UNSUPPORTED_FIELDS,
                                         u"My questionnairé").parse()
     self.assertEqual(xls_parser_response.errors,
                      set(["geoshape as a datatype"]))
Example #29
0
    def post(self, request):
        file_content = None
        tmp_file = None
        try:
            file_content = request.raw_post_data
            file_errors, file_extension = _perform_file_validations(request)
            tmp_file = NamedTemporaryFile(delete=True, suffix=file_extension)
            if file_errors:
                logger.info(
                    "User: %s. Upload File validation failed: %s. File name: %s, size: %d",
                    request.user.username, json.dumps(file_errors),
                    request.GET.get("qqfile"),
                    int(request.META.get('CONTENT_LENGTH')))

                return HttpResponse(json.dumps({
                    'success': False,
                    'error_msg': file_errors
                }),
                                    content_type='application/json')

            tmp_file.write(file_content)
            tmp_file.seek(0)

            project_name = request.GET['pname'].strip()
            manager = get_database_manager(request.user)
            questionnaire_code = generate_questionnaire_code(manager)

            xls_parser_response = XlsFormParser(tmp_file, project_name,
                                                manager).parse()

            send_email_if_unique_id_type_question_has_no_registered_unique_ids(
                xls_parser_response, request, project_name)

            profile = request.user.get_profile()
            organization = Organization.objects.get(org_id=profile.org_id)
            if xls_parser_response.is_multiple_languages:
                logger.info(
                    "Creating Questionnaire %s with Multi Language support for organization : %s(%s) and email: %s",
                    project_name, organization.name, profile.org_id,
                    profile.user.email)

            if xls_parser_response.errors:
                error_list = list(xls_parser_response.errors)
                logger.info("User: %s. Upload Errors: %s",
                            request.user.username, json.dumps(error_list))

                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg':
                        error_list,
                        'message_prefix':
                        _("Sorry! Current version of DataWinners does not support"
                          ),
                        'message_suffix':
                        _("Update your XLSForm and upload again.")
                    }))
            tmp_file.seek(0)
            mangrove_service = MangroveService(
                request,
                questionnaire_code=questionnaire_code,
                project_name=project_name,
                xls_form=tmp_file,
                xls_parser_response=xls_parser_response)
            questionnaire_id, form_code = mangrove_service.create_project()

        except PyXFormError as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            message = transform_error_message(e.message)
            if 'name_type_error' in message or 'choice_name_type_error' in message:
                if 'choice_name_type_error' in message:
                    message_prefix = _(
                        "On your \"choices\" sheet the first and second column must be \"list_name\" and \"name\".  Possible errors:"
                    )
                else:
                    message_prefix = _(
                        "On your \"survey\" sheet the first and second column must be \"type\" and \"name\".  Possible errors:"
                    )
                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg': [
                            _("Columns are missing"),
                            _("Column name is misspelled"),
                            _("Additional space in column name")
                        ],
                        'message_prefix':
                        message_prefix,
                        'message_suffix':
                        _("Update your XLSForm and upload again.")
                    }))
            else:
                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg': [
                            message if message else ugettext(
                                "all XLSForm features. Please check the list of unsupported features."
                            )
                        ]
                    }))

        except QuestionAlreadyExistsException as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            return HttpResponse(
                content_type='application/json',
                content=json.dumps({
                    'success':
                    False,
                    'error_msg': [
                        _("Duplicate labels. All questions (labels) must be unique."
                          )
                    ],
                    'message_prefix':
                    _("Sorry! Current version of DataWinners does not support"
                      ),
                    'message_suffix':
                    _("Update your XLSForm and upload again.")
                }))

        except UnicodeDecodeError as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            return HttpResponse(
                content_type='application/json',
                content=json.dumps({
                    'success':
                    False,
                    'error_msg': [
                        _("Check your columns for errors.<br>There are missing symbols (like $ for relevant or calculate) or incorrect characters<br>"
                          ) + _("Update your XLSForm and upload again.")
                    ],
                }))

        except Exception as e:

            message = e.message if e.message else _("Errors in excel")

            logger.info("User: %s. Upload Exception message: %s",
                        request.user.username, e.message)

            odk_message = ''
            if not 'ODK Validate Errors:' in e.message:
                send_email_on_exception(
                    request.user,
                    "Questionnaire Create",
                    traceback.format_exc(),
                    additional_details={'file_contents': file_content})
            else:
                odk_message = translate_odk_message(e.message)
            message = odk_message if odk_message else message
            return HttpResponse(content_type='application/json',
                                content=json.dumps({
                                    'success': False,
                                    'error_msg': [message],
                                }))

        finally:

            if tmp_file:
                tmp_file.close()

        if not questionnaire_id:
            org = get_organization(request)
            if org.is_pro_sms:
                message = _(
                    "Questionnaire or Poll with same name already exists.Upload was cancelled."
                )
            else:
                message = _(
                    "Questionnaire with same name already exists.Upload was cancelled."
                )
            return HttpResponse(json.dumps({
                'success': False,
                'duplicate_project_name': True,
                'error_msg': [message]
            }),
                                content_type='application/json')

        return HttpResponse(json.dumps({
            "success": True,
            "project_name": project_name,
            "project_id": questionnaire_id,
            "form_code": form_code
        }),
                            content_type='application/json')
Example #30
0
    def post(self, request, project_id):

        manager = get_database_manager(request.user)
        questionnaire = Project.get(manager, project_id)
        file_content = None
        tmp_file = None
        try:
            file_content = request.raw_post_data

            file_errors, file_extension = _perform_file_validations(request)
            tmp_file = NamedTemporaryFile(delete=True, suffix=file_extension)

            if file_errors:
                logger.info(
                    "User: %s. Edit upload File validation failed: %s. File name: %s, size: %d",
                    request.user.username, json.dumps(file_errors),
                    request.GET.get("qqfile"),
                    int(request.META.get('CONTENT_LENGTH')))

                return HttpResponse(content_type='application/json',
                                    content=json.dumps({
                                        'success': False,
                                        'error_msg': file_errors
                                    }))

            tmp_file.write(file_content)
            tmp_file.seek(0)

            xls_parser_response = XlsFormParser(tmp_file, questionnaire.name,
                                                manager).parse()

            send_email_if_unique_id_type_question_has_no_registered_unique_ids(
                xls_parser_response, request, questionnaire.name)

            profile = request.user.get_profile()
            organization = Organization.objects.get(org_id=profile.org_id)
            if xls_parser_response.is_multiple_languages:
                logger.info(
                    "Edit Questionnaire %s with Multi Language support for organization : %s(%s) and email: %s",
                    questionnaire.name, organization.name, profile.org_id,
                    profile.user.email)

            if xls_parser_response.errors:
                info_list = list(xls_parser_response.errors)
                logger.info("User: %s. Edit upload Errors: %s",
                            request.user.username, json.dumps(info_list))

                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg':
                        info_list,
                        'message_prefix':
                        _("Sorry! Current version of DataWinners does not support"
                          ),
                        'message_suffix':
                        _("Update your XLSForm and upload again.")
                    }))

            mangrove_service = MangroveService(
                request,
                questionnaire_code=questionnaire.form_code,
                project_name=questionnaire.name,
                xls_parser_response=xls_parser_response)

            questionnaire.xform = mangrove_service.xform_with_form_code
            QuestionnaireBuilder(questionnaire,
                                 manager).update_questionnaire_with_questions(
                                     xls_parser_response.json_xform_data)

            tmp_file.seek(0)
            questionnaire.update_media_field_flag()
            questionnaire.save(process_post_update=False)

            base_name, extension = os.path.splitext(tmp_file.name)
            questionnaire.update_attachments(tmp_file,
                                             'questionnaire%s' % extension)
            self._purge_submissions(manager, questionnaire)
            self._purge_feed_documents(questionnaire, request)
            self._purge_media_details_documents(manager, questionnaire)
            self.recreate_submissions_mapping(manager, questionnaire)
            if xls_parser_response.info:
                info_list = list(xls_parser_response.info)
                logger.info("User: %s. Edit upload Errors: %s",
                            request.user.username, json.dumps(info_list))
                return HttpResponse(content_type='application/json',
                                    content=json.dumps({
                                        'success':
                                        True,
                                        'information':
                                        info_list,
                                    }))
        except PyXFormError as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            message = transform_error_message(e.message)
            if 'name_type_error' in message or 'choice_name_type_error' in message:
                if 'choice_name_type_error' in message:
                    message_prefix = _(
                        "On your \"choices\" sheet the first and second column must be \"list_name\" and \"name\".  Possible errors:"
                    )
                else:
                    message_prefix = _(
                        "On your \"survey\" sheet the first and second column must be \"type\" and \"name\".  Possible errors:"
                    )
                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg': [
                            _("Columns are missing"),
                            _("Column name is misspelled"),
                            _("Additional space in column name")
                        ],
                        'message_prefix':
                        message_prefix,
                        'message_suffix':
                        _("Update your XLSForm and upload again.")
                    }))
            else:
                return HttpResponse(
                    content_type='application/json',
                    content=json.dumps({
                        'success':
                        False,
                        'error_msg': [
                            message if message else ugettext(
                                "all XLSForm features. Please check the list of unsupported features."
                            )
                        ]
                    }))

        except QuestionAlreadyExistsException as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            return HttpResponse(
                content_type='application/json',
                content=json.dumps({
                    'success':
                    False,
                    'error_msg': [
                        _("Duplicate labels. All questions (labels) must be unique."
                          )
                    ],
                    'message_prefix':
                    _("Sorry! Current version of DataWinners does not support"
                      ),
                    'message_suffix':
                    _("Update your XLSForm and upload again.")
                }))

        except UnicodeDecodeError as e:
            logger.info("User: %s. Upload Error: %s", request.user.username,
                        e.message)

            return HttpResponse(
                content_type='application/json',
                content=json.dumps({
                    'success':
                    False,
                    'error_msg': [
                        _("Check your columns for errors.<br>There are missing symbols (like $ for relevant or calculate) or incorrect characters<br>"
                          ) + _("Update your XLSForm and upload again.")
                    ],
                }))

        except Exception as e:

            logger.info("User: %s. Edit Upload Exception message: %s",
                        request.user.username, e.message)

            message = e.message if e.message else _("Some error in excel")
            odk_message = ''
            if not 'ODK Validate Errors:' in e.message:
                send_email_on_exception(
                    request.user,
                    "Questionnaire Edit",
                    traceback.format_exc(),
                    additional_details={'file_contents': file_content})
            else:
                odk_message = translate_odk_message(e.message)
            message = odk_message if odk_message else message
            return HttpResponse(content_type='application/json',
                                content=json.dumps({
                                    'error_msg': [message],
                                    'success': False,
                                }))

        finally:
            if tmp_file:
                tmp_file.close()

        return HttpResponse(
            json.dumps({
                "success":
                True,
                "project_name":
                questionnaire.name,
                "project_id":
                questionnaire.id,
                "file_name":
                "%s%s" % (slugify(questionnaire.name), extension),
                # "xls_dict": XlsProjectParser().parse(file_content)
            }),
            content_type='application/json')