class ABCSearchEngine(ABC): session_key = None server = None def __init__(self): self.get_session_key() def get_session_key(self): self.server = Server(settings.LIMESURVEY['URL_API'] + '/index.php/admin/remotecontrol') try: self.session_key = self.server.get_session_key( settings.LIMESURVEY['USER'], settings.LIMESURVEY['PASSWORD']) self.session_key = None if isinstance(self.session_key, dict) \ else self.session_key except TransportError: self.session_key = None def release_session_key(self): if self.session_key: self.server.release_session_key(self.session_key) @abstractmethod def find_all_questionnaires(self): """ :return: all stored surveys """ list_survey = self.server.list_surveys(self.session_key, None) return list_survey @abstractmethod def find_all_active_questionnaires(self): """ :return: all active surveys """ list_survey = self.server.list_surveys(self.session_key, None) list_active_survey = [] if isinstance(list_survey, list): for survey in list_survey: if survey['active'] == "Y" and self.survey_has_token_table( survey['sid']): list_active_survey.append(survey) else: list_active_survey = None return list_active_survey @abstractmethod def find_questionnaire_by_id(self, sid): """ :param sid: survey ID :return: survey """ list_survey = self.server.list_surveys(self.session_key, None) try: survey = next( (survey for survey in list_survey if survey['sid'] == sid)) except StopIteration: survey = None return survey @abstractmethod def add_participant(self, sid): """ :param sid: Survey ID :return: dictionary with token and token_id; None if error. """ participant_data = {'email': '', 'firstname': '', 'lastname': ''} result = self.server.add_participants(self.session_key, sid, [participant_data], True) if result \ and isinstance(result, list) \ and isinstance(result[0], dict) \ and 'error' not in result[0]: return {'token': result[0]['token'], 'tid': result[0]['tid']} else: return None @abstractmethod def delete_participant(self, survey_id, tokens_ids): """ Delete survey participant :param survey_id: survey ID :param tokens_ids: token_id to put in a list :return: on success, an array of deletion status for each participant; on failure, status array. """ result = self.server.delete_participants(self.session_key, survey_id, [tokens_ids]) return result @abstractmethod def get_survey_title(self, sid, language): """ :param sid: survey ID :param language: language :return: title of the survey """ if self.session_key: survey_title = self.server.get_language_properties( self.session_key, sid, {'method': 'surveyls_title'}, language) if 'surveyls_title' in survey_title: survey_title = survey_title.get('surveyls_title') else: survey_title = str(sid) else: survey_title = str(sid) return survey_title @abstractmethod def get_survey_properties(self, sid, prop): """ :param sid: survey ID :param prop: the name of the propriety of the survey :return: value of the property """ result = self.server.get_survey_properties(self.session_key, sid, {'method': prop}) return result.get(prop) @abstractmethod def get_survey_languages(self, sid): """ :param sid: survey ID :return: the base and the additional idioms """ result = self.server.get_survey_properties( self.session_key, sid, ['additional_languages', 'language']) return result @abstractmethod def activate_survey(self, sid): """ Activates a survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_survey(self.session_key, sid) return result['status'] @abstractmethod def activate_tokens(self, sid): """ Activates tokens for a determined survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_tokens(self.session_key, sid) return result['status'] @abstractmethod def get_participant_properties(self, survey_id, token_id, prop): """ :param survey_id: survey ID :param token_id: token ID :param prop: property name :return: value of a determined property from a participant/token """ if self.session_key: result = self.server.get_participant_properties( self.session_key, survey_id, token_id, {'method': prop}) result = result.get(prop) else: result = '' return result @abstractmethod def survey_has_token_table(self, sid): """ :param sid: survey ID :return: True if the survey has token table; False, if not. """ result = self.server.get_summary(self.session_key, sid, "token_completed") return isinstance(result, int) @abstractmethod def add_survey(self, sid, title, language, survey_format): """ Adds a survey to the LimeSurvey :param sid: survey ID :param title: title of the survey :param language: language of the survey :param survey_format: format of the survey :return: survey ID generated """ survey_id_generated = self.server.add_survey(self.session_key, sid, title, language, survey_format) return survey_id_generated @abstractmethod def delete_survey(self, sid): """ remove a survey from the LimeSurvey :param sid: survey ID :return: status of the operation """ status = self.server.delete_survey(self.session_key, sid) return status['status'] @abstractmethod def get_responses_by_token(self, sid, token, language, fields=[]): """ obtains responses from a determined token :param sid: survey ID :param token: token :param language: language :param fields: fields array, using SGQA identifier :return: responses in the txt format """ if fields: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', 'code', 'short', fields) else: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete') if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt @abstractmethod def get_responses(self, sid, language, response_type, fields, heading_type): """ Obtains responses from a determined survey :param sid: survey ID :param language: language :param response_type: (optional)'short' or 'long' Optional defaults to 'short' :param fields: filter fields that must be returned :param heading_type: (optional) 'code','full' or 'abbreviated' Optional defaults to 'code' :return: responses in txt format """ responses = self.server.export_responses(self.session_key, sid, 'csv', language, 'complete', heading_type, response_type) if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt def get_header_response(self, sid, language, token, heading_type): """ Obtain header responses :param sid: survey ID :param language: language :param heading_type: heading type (can be 'code' or 'full') :return: responses in the txt format """ responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', heading_type, 'short') if not isinstance(responses, str): responses = self.server.export_responses(self.session_key, sid, 'csv', language, 'complete', heading_type, 'short') if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt @abstractmethod def get_summary(self, sid, stat_name): """ :param sid: survey ID :param stat_name: name of the summary option - valid values are 'token_count', 'token_invalid', 'token_sent', 'token_opted_out', 'token_completed', 'completed_responses', 'incomplete_responses', 'full_responses' or 'all' :return: summary information """ summary_responses = self.server.get_summary(self.session_key, sid, stat_name) return summary_responses @abstractmethod def insert_questions(self, sid, questions_data, format_import_file): """ Imports a group of questions from a file :param sid: survey ID :param questions_data: question data :param format_import_file: lsg file :return: """ questions_data_b64 = b64encode(questions_data.encode('utf-8')) result = self.server.import_group(self.session_key, sid, questions_data_b64.decode('utf-8'), format_import_file) if isinstance(result, dict): if 'status' in result: return None else: return result @abstractmethod def get_question_properties(self, question_id, language): """ :param question_id: question ID :param language: language of the answer :return: properties of a question of a survey """ properties = self.server.get_question_properties( self.session_key, question_id, [ 'gid', 'question', 'subquestions', 'answeroptions', 'title', 'type', 'attributes_lang', 'attributes', 'other' ], language) return properties def set_question_properties(self, sid, data): return self.server.set_question_properties(self.session_key, sid, data) @abstractmethod def list_groups(self, sid): """ :param sid: survey ID :return: ids and info of groups belonging to survey """ groups = self.server.list_groups(self.session_key, sid) return groups @abstractmethod def get_group_properties(self, gid): """ :param gid: group ID :param lang: group language to return correct group, as Remote Control API does not do that :return: list of group properties """ return self.server.get_group_properties(self.session_key, gid) def set_group_properties(self, sid, data): return self.server.set_group_properties(self.session_key, sid, data) @abstractmethod def list_questions(self, sid, gid): """ :param sid: survey ID :param gid: group ID :return: ids and info of (sub-)questions of a survey/group """ question_list = [] questions = self.server.list_questions(self.session_key, sid, gid) for question in questions: question_list.append(question['id']['qid']) return question_list @abstractmethod def find_tokens_by_questionnaire(self, sid): """ :param sid: :return: tokens for specific id """ tokens = self.server.list_participants(self.session_key, sid, 0, 99999999) return tokens def add_group(self, sid, title, description): return self.server.add_group(self.session_key, sid, title) def add_response(self, sid, response_data): return self.server.add_response(self.session_key, sid, response_data) def set_participant_properties(self, sid, tid, properties_dict): return self.server.set_participant_properties(self.session_key, sid, tid, properties_dict)
class ABCSearchEngineTest(TestCase): session_key = None server = None def setUp(self): self.server = Server(settings.LIMESURVEY['URL_API'] + '/index.php/admin/remotecontrol') try: self.session_key = self.server.get_session_key( settings.LIMESURVEY['USER'], settings.LIMESURVEY['PASSWORD']) self.session_key = None if isinstance(self.session_key, dict) else self.session_key except TransportError: self.session_key = None def test_complete_survey(self): lime_survey = Questionnaires() sid = None try: # Cria uma nova survey no lime survey title_survey = 'Questionario de teste' sid = lime_survey.add_survey(9999, title_survey, 'en', 'G') # Obtenho o titulo da survey survey_title = lime_survey.get_survey_title(sid) self.assertEqual(survey_title, title_survey) # Verifica se esta ativa survey_active = lime_survey.get_survey_properties(sid, 'active') self.assertEqual(survey_active, 'N') # Obtem uma propriedade - Administrador da Survey survey_admin = lime_survey.get_survey_properties(sid, 'admin') self.assertEqual(survey_admin, None) # Importar grupo de questoes handle_file_import = \ open('quiz/static/quiz/tests/limesurvey_groups.lsg', 'r') questions_data = handle_file_import.read() questions_id = \ lime_survey.insert_questions(sid, questions_data, 'lsg') self.assertGreaterEqual(questions_id, 1) # Inicia tabela de tokens self.assertEqual(lime_survey.activate_tokens(sid), 'OK') # Ativar survey self.assertEqual(lime_survey.activate_survey(sid), 'OK') # Verifica se esta ativa survey_active = lime_survey.get_survey_properties(sid, 'active') self.assertEqual(survey_active, 'Y') # Adiciona participante e obtem o token result_token = lime_survey.add_participant(sid) # Verifica se o token está presente na tabela de participantes token = lime_survey.get_participant_properties( sid, result_token, "token") self.assertEqual(token, result_token['token']) finally: # Deleta a survey gerada no Lime Survey self.assertEqual(lime_survey.delete_survey(sid), 'OK') def test_find_all_questionnaires_method_returns_correct_result(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) self.assertEqual(questionnaires.find_all_questionnaires(), list_survey) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_found_survey(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) self.assertEqual( questionnaires.find_questionnaire_by_id(list_survey[3]['sid']), list_survey[3]) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_not_found_survey_by_string(self): questionnaires = Questionnaires() self.assertEqual(None, questionnaires.find_questionnaire_by_id('three')) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_not_found_survey_by_out_of_range( self): questionnaires = Questionnaires() self.assertEqual(None, questionnaires.find_questionnaire_by_id(10000000)) questionnaires.release_session_key() def test_list_active_questionnaires(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) list_active_survey = [] for survey in list_survey: survey_has_token = questionnaires.survey_has_token_table( survey['sid']) if survey['active'] == "Y" and survey_has_token is True: list_active_survey.append(survey) self.assertEqual(questionnaires.find_all_active_questionnaires(), list_active_survey) questionnaires.release_session_key() def test_add_participant_to_a_survey(self): """testa a insercao de participante em um questionario """ surveys = Questionnaires() list_active_surveys = surveys.find_all_active_questionnaires() self.assertNotEqual(list_active_surveys, None) survey = list_active_surveys[0] sid = int(survey['sid']) # list_participants = self.server.list_participants(self.session_key, sid) # participant_data = {'email': '*****@*****.**', 'lastname': 'junqueira', 'firstname': 'juca'} participant_data_result = surveys.add_participant(sid) # verificar se info retornada eh a mesma # self.assertEqual(participant_data_result[0]['email'], participant_data['email']) # self.assertEqual(participant_data_result[0]['lastname'], participant_data['lastname']) # self.assertEqual(participant_data_result[0]['firsStname'], participant_data['firstname']) self.assertNotEqual(participant_data_result, None) # list_participants_new = self.server.list_participants(self.session_key, sid) # self.assertEqual(len(list_participants_new), len(list_participants) + 1) # token_id = participant_data_result[0]['tid'] token_id = participant_data_result['tid'] # tokens_to_delete = [token_id] # remover participante do questionario result = self.server.delete_participants(self.session_key, sid, [token_id]) self.assertEqual(result[str(token_id)], 'Deleted') surveys.release_session_key() def test_add_and_delete_survey(self): """ TDD - Criar uma survey de teste e apos devera ser excluida """ survey_id_generated = self.server.add_survey(self.session_key, 9999, 'Questionario de Teste', 'en', 'G') self.assertGreaterEqual(survey_id_generated, 0) status = self.server.delete_survey(self.session_key, survey_id_generated) self.assertEqual(status['status'], 'OK') self.server.release_session_key(self.session_key) def test_add_and_delete_survey_methods(self): questionnaires = Questionnaires() sid = questionnaires.add_survey('9999', 'Questionario de Teste', 'en', 'G') self.assertGreaterEqual(sid, 0) status = questionnaires.delete_survey(sid) self.assertEqual(status, 'OK') # def test_get_survey_property_usetokens(self): # """testa a obtencao das propriedades de um questionario""" # # surveys = Questionnaires() # result = surveys.get_survey_properties(641729, "usetokens") # surveys.release_session_key() # # pass # def test_get_participant_property_usetokens(self): # """testa a obtencao das propriedades de um participant/token""" # # surveys = Questionnaires() # # # completo # result1 = surveys.get_participant_properties(426494, 2, "completed") # # # nao completo # result2 = surveys.get_participant_properties(426494, 230, "completed") # result3 = surveys.get_participant_properties(426494, 230, "token") # surveys.release_session_key() # # pass # def test_survey_has_token_table(self): # """testa se determinado questionario tem tabela de tokens criada""" # # surveys = Questionnaires() # # # exemplo de "true" # result = surveys.survey_has_token_table(426494) # # # exemplo de "false" # result2 = surveys.survey_has_token_table(642916) # surveys.release_session_key() # # pass def test_delete_participant_to_a_survey(self): """ Remove survey participant test testa a insercao de participante em um questionario """ surveys = Questionnaires() list_active_surveys = surveys.find_all_active_questionnaires() self.assertNotEqual(list_active_surveys, None) survey = list_active_surveys[0] sid = int(survey['sid']) # list_participants = self.server.list_participants(self.session_key, sid) # participant_data = {'email': '*****@*****.**', 'lastname': 'junqueira', 'firstname': 'juca'} participant_data_result = surveys.add_participant(sid) # verificar se info retornada eh a mesma # self.assertEqual(participant_data_result[0]['email'], participant_data['email']) # self.assertEqual(participant_data_result[0]['lastname'], participant_data['lastname']) # self.assertEqual(participant_data_result[0]['firstname'], participant_data['firstname']) self.assertNotEqual(participant_data_result, None) # list_participants_new = self.server.list_participants(self.session_key, sid) # self.assertEqual(len(list_participants_new), len(list_participants) + 1) # token_id = participant_data_result[0]['tid'] token_id = participant_data_result['tid'] # tokens_to_delete = [token_id] # remover participante do questionario result = surveys.delete_participant(sid, token_id) self.assertEqual(result[str(token_id)], 'Deleted') surveys.release_session_key()
class ABCSearchEngine(ABC): QUESTION_PROPERTIES = [ 'gid', 'question', 'question_order', 'subquestions', 'answeroptions', 'title', 'type', 'attributes_lang', 'attributes', 'other' ] session_key = None server = None def __init__(self): self.get_session_key() def get_session_key(self): self.server = Server( settings.LIMESURVEY['URL_API'] + '/index.php/admin/remotecontrol') try: self.session_key = self.server.get_session_key( settings.LIMESURVEY['USER'], settings.LIMESURVEY['PASSWORD'] ) self.session_key = None if isinstance(self.session_key, dict) \ else self.session_key except TransportError: self.session_key = None def release_session_key(self): if self.session_key: self.server.release_session_key(self.session_key) @abstractmethod def find_all_questionnaires(self): """ :return: all stored surveys """ list_survey = self.server.list_surveys(self.session_key, None) return list_survey @abstractmethod def find_all_active_questionnaires(self): """ :return: all active surveys """ list_survey = self.server.list_surveys(self.session_key, None) list_active_survey = [] if isinstance(list_survey, list): for survey in list_survey: if survey['active'] == "Y" and self.survey_has_token_table(survey['sid']): list_active_survey.append(survey) else: list_active_survey = None return list_active_survey @abstractmethod def find_questionnaire_by_id(self, sid): """ :param sid: survey ID :return: survey """ list_survey = self.server.list_surveys(self.session_key, None) try: survey = next((survey for survey in list_survey if survey['sid'] == sid)) except StopIteration: survey = None return survey @abstractmethod def add_participant(self, sid): """ :param sid: Survey ID :return: dictionary with token and token_id; None if error. """ participant_data = {'email': '', 'firstname': '', 'lastname': ''} result = self.server.add_participants( self.session_key, sid, [participant_data], True ) if result \ and isinstance(result, list) \ and isinstance(result[0], dict) \ and 'error' not in result[0]: return {'token': result[0]['token'], 'tid': result[0]['tid']} else: return None @abstractmethod def delete_participant(self, survey_id, tokens_ids): """ Delete survey participant :param survey_id: survey ID :param tokens_ids: token_id to put in a list :return: on success, an array of deletion status for each participant; on failure, status array. """ result = self.server.delete_participants( self.session_key, survey_id, [tokens_ids] ) return result @abstractmethod def get_survey_title(self, sid, language): """ :param sid: survey ID :param language: language :return: title of the survey """ if self.session_key: survey_title = self.server.get_language_properties(self.session_key, sid, {'method': 'surveyls_title'}, language) if 'surveyls_title' in survey_title: survey_title = survey_title.get('surveyls_title') else: survey_title = str(sid) else: survey_title = str(sid) return survey_title @abstractmethod def get_survey_properties(self, sid, prop): """ :param sid: survey ID :param prop: the name of the propriety of the survey :return: value of the property """ result = self.server.get_survey_properties(self.session_key, sid, {'method': prop}) return result.get(prop) @abstractmethod def get_survey_languages(self, sid): """ :param sid: survey ID :return: the base and the additional idioms """ result = self.server.get_survey_properties(self.session_key, sid, ['additional_languages', 'language']) return result @abstractmethod def activate_survey(self, sid): """ Activates a survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_survey(self.session_key, sid) return result['status'] @abstractmethod def activate_tokens(self, sid): """ Activates tokens for a determined survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_tokens(self.session_key, sid) return result['status'] @abstractmethod def get_participant_properties(self, survey_id, token_id, prop): """ :param survey_id: survey ID :param token_id: token ID :param prop: property name :return: value of a determined property from a participant/token """ if self.session_key: result = self.server.get_participant_properties( self.session_key, survey_id, token_id, {'method': prop} ) result = result.get(prop) else: result = '' return result @abstractmethod def survey_has_token_table(self, sid): """ :param sid: survey ID :return: True if the survey has token table; False, if not. """ result = self.server.get_summary(self.session_key, sid, "token_completed") return isinstance(result, int) @abstractmethod def add_survey(self, sid, title, language, survey_format): """ Adds a survey to the LimeSurvey :param sid: survey ID :param title: title of the survey :param language: language of the survey :param survey_format: format of the survey :return: survey ID generated """ survey_id_generated = self.server.add_survey( self.session_key, sid, title, language, survey_format ) return survey_id_generated @abstractmethod def delete_survey(self, sid): """ remove a survey from the LimeSurvey :param sid: survey ID :return: status of the operation """ status = self.server.delete_survey(self.session_key, sid) return status['status'] @abstractmethod def get_responses_by_token(self, sid, token, language, fields=[]): """ obtains responses from a determined token :param sid: survey ID :param token: token :param language: language :param fields: fields array, using SGQA identifier :return: responses in the txt format """ if fields: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', 'code', 'short', fields) else: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete') if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt @abstractmethod def get_responses(self, sid, language, response_type, fields, heading_type): """ Obtains responses from a determined survey :param sid: survey ID :param language: language :param response_type: (optional)'short' or 'long' Optional defaults to 'short' :param fields: filter fields that must be returned :param heading_type: (optional) 'code','full' or 'abbreviated' Optional defaults to 'code' :return: responses in txt format """ responses = self.server.export_responses( self.session_key, sid, 'csv', language, 'complete', heading_type, response_type ) if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt def get_header_response(self, sid, language, token, heading_type): """ Obtain header responses :param sid: survey ID :param language: language :param heading_type: heading type (can be 'code' or 'full') :return: responses in the txt format """ responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', heading_type, 'short' ) if not isinstance(responses, str): responses = self.server.export_responses( self.session_key, sid, 'csv', language, 'complete', heading_type, 'short' ) if isinstance(responses, str): responses_txt = b64decode(responses) else: responses_txt = responses return responses_txt @abstractmethod def get_summary(self, sid, stat_name): """ :param sid: survey ID :param stat_name: name of the summary option - valid values are 'token_count', 'token_invalid', 'token_sent', 'token_opted_out', 'token_completed', 'completed_responses', 'incomplete_responses', 'full_responses' or 'all' :return: summary information """ summary_responses = self.server.get_summary(self.session_key, sid, stat_name) return summary_responses @abstractmethod def insert_questions(self, sid, questions_data, format_import_file): """ Imports a group of questions from a file :param sid: survey ID :param questions_data: question data :param format_import_file: lsg file :return: """ questions_data_b64 = b64encode(questions_data.encode('utf-8')) result = self.server.import_group( self.session_key, sid, questions_data_b64.decode('utf-8'), format_import_file ) if isinstance(result, dict): if 'status' in result: return None else: return result @abstractmethod def get_question_properties(self, question_id, language): """ :param question_id: question ID :param language: language of the answer :return: properties of a question of a survey """ properties = self.server.get_question_properties( self.session_key, question_id, self.QUESTION_PROPERTIES, language ) return properties def set_question_properties(self, sid, data): return self.server.set_question_properties(self.session_key, sid, data) @abstractmethod def list_groups(self, sid): """ :param sid: survey ID :return: ids and info of groups belonging to survey """ groups = self.server.list_groups(self.session_key, sid) return groups @abstractmethod def get_group_properties(self, gid): """ :param gid: group ID :param lang: group language to return correct group, as Remote Control API does not do that :return: list of group properties """ return self.server.get_group_properties(self.session_key, gid) def set_group_properties(self, sid, data): return self.server.set_group_properties( self.session_key, sid, data ) @abstractmethod def list_questions(self, sid, gid): """ :param sid: survey ID :param gid: group ID :return: ids and info of (sub-)questions of a survey/group """ question_list = [] questions = self.server.list_questions(self.session_key, sid, gid) for question in questions: question_list.append(question['id']['qid']) return question_list @abstractmethod def find_tokens_by_questionnaire(self, sid): """ :param sid: :return: tokens for specific id """ tokens = self.server.list_participants( self.session_key, sid, 0, 99999999 ) return tokens def add_group(self, sid, title, description): return self.server.add_group(self.session_key, sid, title) def add_response(self, sid, response_data): return self.server.add_response(self.session_key, sid, response_data) def set_participant_properties(self, sid, tid, properties_dict): return self.server.set_participant_properties( self.session_key, sid, tid, properties_dict )
class ABCSearchEngineTest(TestCase): session_key = None server = None def setUp(self): self.server = Server('http://survey.numec.prp.usp.br/index.php/admin/remotecontrol') self.session_key = self.server.get_session_key(settings.LIMESURVEY['USER'], settings.LIMESURVEY['PASSWORD']) # Checks if connected in the LimeSurvey with the settings.py credentials self.assertNotIsInstance(self.session_key, dict) def test_complete_survey(self): lime_survey = Questionnaires() sid = None try: # Cria uma nova survey no lime survey title_survey = 'Questionario de teste' sid = lime_survey.add_survey(9999, title_survey, 'en', 'G') # Obtenho o titulo da survey survey_title = lime_survey.get_survey_title(sid) self.assertEqual(survey_title, title_survey) # Verifica se esta ativa survey_active = lime_survey.get_survey_properties(sid, 'active') self.assertEqual(survey_active, 'N') # Obtem uma propriedade - Administrador da Survey survey_admin = lime_survey.get_survey_properties(sid, 'admin') self.assertEqual(survey_admin, None) # Importar grupo de questoes handle_file_import = open('quiz/static/quiz/tests/limesurvey_groups.lsg', 'r') questions_data = handle_file_import.read() questions_id = lime_survey.insert_questions(sid, questions_data, 'lsg') self.assertGreaterEqual(questions_id, 1) # Inicia tabela de tokens self.assertEqual(lime_survey.activate_tokens(sid), 'OK') # Ativar survey self.assertEqual(lime_survey.activate_survey(sid), 'OK') # Verifica se esta ativa survey_active = lime_survey.get_survey_properties(sid, 'active') self.assertEqual(survey_active, 'Y') # Adiciona participante e obtem o token result_token = lime_survey.add_participant(sid) # Verifica se o token token = lime_survey.get_participant_properties(sid, result_token, "token") self.assertEqual(token, result_token['token']) finally: # Deleta a survey gerada no Lime Survey self.assertEqual(lime_survey.delete_survey(sid), 'OK') def test_find_all_questionnaires_method_returns_correct_result(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) self.assertEqual(questionnaires.find_all_questionnaires(), list_survey) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_found_survey(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) self.assertEqual(questionnaires.find_questionnaire_by_id(list_survey[3]['sid']), list_survey[3]) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_not_found_survey_by_string(self): questionnaires = Questionnaires() self.assertEqual(None, questionnaires.find_questionnaire_by_id('three')) questionnaires.release_session_key() def test_find_questionnaire_by_id_method_not_found_survey_by_out_of_range(self): questionnaires = Questionnaires() self.assertEqual(None, questionnaires.find_questionnaire_by_id(10000000)) questionnaires.release_session_key() def test_list_active_questionnaires(self): questionnaires = Questionnaires() list_survey = self.server.list_surveys(self.session_key, None) self.server.release_session_key(self.session_key) list_active_survey = [] for survey in list_survey: survey_has_token = questionnaires.survey_has_token_table(survey['sid']) if survey['active'] == "Y" and survey_has_token is True: list_active_survey.append(survey) self.assertEqual(questionnaires.find_all_active_questionnaires(), list_active_survey) questionnaires.release_session_key() def test_add_participant_to_a_survey(self): """testa a insercao de participante em um questionario """ surveys = Questionnaires() list_active_surveys = surveys.find_all_active_questionnaires() self.assertNotEqual(list_active_surveys, None) survey = list_active_surveys[0] sid = int(survey['sid']) # list_participants = self.server.list_participants(self.session_key, sid) # participant_data = {'email': '*****@*****.**', 'lastname': 'junqueira', 'firstname': 'juca'} participant_data_result = surveys.add_participant(sid) # verificar se info retornada eh a mesma # self.assertEqual(participant_data_result[0]['email'], participant_data['email']) # self.assertEqual(participant_data_result[0]['lastname'], participant_data['lastname']) # self.assertEqual(participant_data_result[0]['firsStname'], participant_data['firstname']) self.assertNotEqual(participant_data_result, None) # list_participants_new = self.server.list_participants(self.session_key, sid) # self.assertEqual(len(list_participants_new), len(list_participants) + 1) # token_id = participant_data_result[0]['tid'] token_id = participant_data_result['token_id'] # tokens_to_delete = [token_id] # remover participante do questionario result = self.server.delete_participants(self.session_key, sid, [token_id]) self.assertEqual(result[str(token_id)], 'Deleted') surveys.release_session_key() def test_add_and_delete_survey(self): """ TDD - Criar uma survey de teste e apos devera ser excluida """ survey_id_generated = self.server.add_survey(self.session_key, 9999, 'Questionario de Teste', 'en', 'G') self.assertGreaterEqual(survey_id_generated, 0) status = self.server.delete_survey(self.session_key, survey_id_generated) self.assertEqual(status['status'], 'OK') self.server.release_session_key(self.session_key) def test_add_and_delete_survey_methods(self): questionnaires = Questionnaires() sid = questionnaires.add_survey('9999', 'Questionario de Teste', 'en', 'G') self.assertGreaterEqual(sid, 0) status = questionnaires.delete_survey(sid) self.assertEqual(status, 'OK') # def test_get_survey_property_usetokens(self): # """testa a obtencao das propriedades de um questionario""" # # surveys = Questionnaires() # result = surveys.get_survey_properties(641729, "usetokens") # surveys.release_session_key() # # pass # def test_get_participant_property_usetokens(self): # """testa a obtencao das propriedades de um participant/token""" # # surveys = Questionnaires() # # # completo # result1 = surveys.get_participant_properties(426494, 2, "completed") # # # nao completo # result2 = surveys.get_participant_properties(426494, 230, "completed") # result3 = surveys.get_participant_properties(426494, 230, "token") # surveys.release_session_key() # # pass # def test_survey_has_token_table(self): # """testa se determinado questionario tem tabela de tokens criada""" # # surveys = Questionnaires() # # # exemplo de "true" # result = surveys.survey_has_token_table(426494) # # # exemplo de "false" # result2 = surveys.survey_has_token_table(642916) # surveys.release_session_key() # # pass def test_delete_participant_to_a_survey(self): """ Remove survey participant test testa a insercao de participante em um questionario """ surveys = Questionnaires() list_active_surveys = surveys.find_all_active_questionnaires() self.assertNotEqual(list_active_surveys, None) survey = list_active_surveys[0] sid = int(survey['sid']) # list_participants = self.server.list_participants(self.session_key, sid) # participant_data = {'email': '*****@*****.**', 'lastname': 'junqueira', 'firstname': 'juca'} participant_data_result = surveys.add_participant(sid) # verificar se info retornada eh a mesma # self.assertEqual(participant_data_result[0]['email'], participant_data['email']) # self.assertEqual(participant_data_result[0]['lastname'], participant_data['lastname']) # self.assertEqual(participant_data_result[0]['firstname'], participant_data['firstname']) self.assertNotEqual(participant_data_result, None) # list_participants_new = self.server.list_participants(self.session_key, sid) # self.assertEqual(len(list_participants_new), len(list_participants) + 1) # token_id = participant_data_result[0]['tid'] token_id = participant_data_result['token_id'] # tokens_to_delete = [token_id] # remover participante do questionario result = surveys.delete_participant(sid, token_id) self.assertEqual(result[str(token_id)], 'Deleted') surveys.release_session_key()
class ABCSearchEngine(ABC): QUESTION_PROPERTIES = [ 'gid', 'question', 'question_order', 'subquestions', 'answeroptions', 'title', 'type', 'attributes_lang', 'attributes', 'other' ] session_key = None server = None def __init__(self, limesurvey_rpc=None): self.limesurvey_rpc = limesurvey_rpc or settings.LIMESURVEY[ 'URL_API'] + '/index.php/admin/remotecontrol' self.get_session_key() def get_session_key(self): self.server = Server(self.limesurvey_rpc) try: self.session_key = self.server.get_session_key( settings.LIMESURVEY['USER'], settings.LIMESURVEY['PASSWORD']) self.session_key = None if isinstance(self.session_key, dict) else self.session_key except TransportError: self.session_key = None # TODO: catch user/password exception def release_session_key(self): if self.session_key: self.server.release_session_key(self.session_key) @abstractmethod def find_all_questionnaires(self): """ :return: all stored surveys """ list_survey = self.server.list_surveys(self.session_key, None) return list_survey @abstractmethod def find_all_active_questionnaires(self): """ :return: all active surveys """ list_survey = self.server.list_surveys(self.session_key, None) list_active_survey = [] if isinstance(list_survey, list): for survey in list_survey: if survey['active'] == "Y" and self.survey_has_token_table( survey['sid']): list_active_survey.append(survey) else: list_active_survey = None return list_active_survey @abstractmethod def find_questionnaire_by_id(self, sid): """ :param sid: survey ID :return: survey """ list_survey = self.server.list_surveys(self.session_key, None) try: survey = next( (survey for survey in list_survey if survey['sid'] == sid)) except StopIteration: survey = None return survey @abstractmethod def add_participant(self, sid): """ :param sid: Survey ID :return: dictionary with token and token_id; None if error. """ participant_data = {'email': '', 'firstname': '', 'lastname': ''} result = self.server.add_participants(self.session_key, sid, [participant_data], True) if result and isinstance(result, list) and isinstance( result[0], dict) and 'error' not in result[0]: return {'token': result[0]['token'], 'tid': result[0]['tid']} else: return None @abstractmethod def delete_participants(self, survey_id, tokens_ids): """ Delete survey participant :param survey_id: survey ID :param tokens_ids: list of token ids :return: on success, a dict of deletion status for each participant; on failure, status dict. """ result = self.server.delete_participants(self.session_key, survey_id, tokens_ids) # TODO: verify if there exists participants table. The questionnary # may be deactivated but NES keep tracking it. # In case of success RPC returs a list, otherwise a dict with error status return result if 'status' not in result else None @abstractmethod def get_survey_title(self, sid, language): """ :param sid: survey ID :param language: language :return: title of the survey """ if self.session_key: survey_title = self.server.get_language_properties( self.session_key, sid, {'method': 'surveyls_title'}, language) if 'surveyls_title' in survey_title: survey_title = survey_title.get('surveyls_title') else: survey_title = str(sid) else: survey_title = str(sid) return survey_title @abstractmethod def get_survey_properties(self, sid, prop): """ :param sid: survey ID :param prop: the name of the property of the survey :return: value of the property """ result = self.server.get_survey_properties(self.session_key, sid, {'method': prop}) return result.get(prop) @abstractmethod def get_survey_languages(self, sid): """ :param sid: survey ID :return: the base and the additional idioms """ result = self.server.get_survey_properties( self.session_key, sid, ['additional_languages', 'language']) # If failed to consume API, it return a dict with one element with # 'status' as key return None if 'status' in result else result @abstractmethod def activate_survey(self, sid): """ Activates a survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_survey(self.session_key, sid) return result['status'] @abstractmethod def activate_tokens(self, sid): """ Activates tokens for a determined survey :param sid: survey ID :return: status of the survey """ result = self.server.activate_tokens(self.session_key, sid) return result['status'] @abstractmethod def get_participant_properties(self, survey_id, token_id, prop): """ :param survey_id: survey ID :param token_id: token ID :param prop: property name :return: on success, dict with value of a determined property, else dict with error status """ # Backward compatibility with last method signature. # TODO: refactor the code and remove this if if isinstance(prop, str): prop = [prop] result = self.server.get_participant_properties( self.session_key, survey_id, token_id, prop) # This if-else for backward compatibility with last method signature # TODO: refactor the code and remove this if-else if prop is not None and len(prop) == 1: return result.get(prop[0]) if 'status' not in result else None else: return result if 'status' not in result else None @abstractmethod def survey_has_token_table(self, sid): """ :param sid: survey ID :return: True if the survey has token table; False, if not. """ result = self.server.get_summary(self.session_key, sid, "token_completed") return isinstance(result, int) @abstractmethod def add_survey(self, sid, title, language, survey_format): """ Adds a survey to the LimeSurvey :param sid: survey ID :param title: title of the survey :param language: language of the survey :param survey_format: format of the survey :return: survey ID generated """ survey_id_generated = self.server.add_survey(self.session_key, sid, title, language, survey_format) return survey_id_generated @abstractmethod def delete_survey(self, sid): """ remove a survey from the LimeSurvey :param sid: survey ID :return: status of the operation """ status = self.server.delete_survey(self.session_key, sid) return status['status'] @abstractmethod def get_responses_by_token(self, sid, token, language, doctype, fields): """Obtain responses from a determined token. Limesurvey returns a string that, when b65decoded, has two new lines at the end. We eliminate that new lines. If doctype == 'csv-allanswer' export as 'csv'. The exportCompleteAnswers plugin may be not installed. See https://gitlab.com/SondagesPro/ExportAndStats/exportCompleteAnswers :param sid: survey ID :param token: token :param doctype: type of coded string ('csv', 'json, ...) :param language: language :param fields: fields array, using SGQA identifier :return: responses in the txt format """ responses = {} if fields: try: responses = self.server.export_responses_by_token( self.session_key, sid, doctype, token, language, 'complete', 'code', 'short', fields) except AttributeError: if doctype == 'csv-allanswer': responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', 'code', 'short', fields) else: try: responses = self.server.export_responses_by_token( self.session_key, sid, doctype, token, language, 'complete') except AttributeError: if doctype == 'csv-allanswer': responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete') if isinstance(responses, dict): return None responses = b64decode(responses).decode() return re.sub('\n\n', '\n', responses) @abstractmethod def get_responses(self, sid, language, response_type, fields, heading_type): """ Obtains responses from a determined survey. If doctype == 'csv-allanswer' try to export. The plugin may by not installed. :param sid: survey ID :param language: language :param response_type: (optional)'short' or 'long' Optional defaults to 'short' :param fields: filter fields that must be returned :param heading_type: (optional) 'code','full' or 'abbreviated' Optional defaults to 'code' :return: responses in txt format """ if response_type == 'long': responses = self.server.export_responses(self.session_key, sid, 'csv', language, 'complete', heading_type, response_type) else: try: responses = self.server.export_responses( self.session_key, sid, 'csv-allanswer', language, 'complete', heading_type, response_type) except AttributeError: responses = self.server.export_responses( self.session_key, sid, 'csv', language, 'complete', heading_type, response_type) return None if isinstance(responses, dict) \ else b64decode(responses).decode() def get_header_response(self, sid, language, token, heading_type): """Obtain header responses. If doctype == 'csv-allanswer' try to export. The plugin may be not installed. :param sid: survey ID :param language: language :param token: token :param heading_type: heading type (can be 'code', 'abbreviated', 'full') :return: str - responses in the txt format in case of success, else None """ if heading_type != 'abbreviated': try: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv-allanswer', token, language, 'complete', heading_type, 'short') except AttributeError: # TODO: sid: 843661 responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', heading_type, 'short') else: responses = self.server.export_responses_by_token( self.session_key, sid, 'csv', token, language, 'complete', heading_type, 'short') # For compatibility with export view call: when export_responses # returns {'status': 'No Response found by Token'} export view call # export_responses, that returns a string to responses variable and # can mount the screen with the possible data to export if isinstance(responses, dict) \ and responses['status'] == 'No Response found for Token': try: responses = self.server.export_responses( self.session_key, sid, 'csv-allanswer', language, 'complete', heading_type, 'short') except AttributeError: responses = self.server.export_responses( self.session_key, sid, 'csv', language, 'complete', heading_type, 'short') return None if isinstance(responses, dict) \ else b64decode(responses).decode() @abstractmethod def get_summary(self, sid, stat_name): """ :param sid: survey ID :param stat_name: name of the summary option - valid values are 'token_count', 'token_invalid', 'token_sent', 'token_opted_out', 'token_completed', 'completed_responses', 'incomplete_responses', 'full_responses' or 'all' :return: summary information """ summary_responses = self.server.get_summary(self.session_key, sid, stat_name) return summary_responses @abstractmethod def insert_questions(self, sid, questions_data, format_import_file): """ Import a group of questions from a file :param sid: survey ID :param questions_data: question data :param format_import_file: lsg file :return: """ questions_data_b64 = b64encode(questions_data.encode('utf-8')) result = self.server.import_group(self.session_key, sid, questions_data_b64.decode('utf-8'), format_import_file) return None if isinstance(result, dict) else result @abstractmethod def get_question_properties(self, question_id, language): """ :param question_id: question ID :param language: language of the answer :return: properties of a question of a survey """ properties = self.server.get_question_properties( self.session_key, question_id, self.QUESTION_PROPERTIES, language) if 'status' in properties and properties['status'] in [ 'Error: Invalid questionid', 'Error: Invalid language', 'Error: Invalid questionid', 'No valid Data', 'No permission', 'Invalid session key' ]: return None return properties def set_question_properties(self, sid, data): return self.server.set_question_properties(self.session_key, sid, data) @abstractmethod def list_groups(self, sid): """ :param sid: survey ID :return: on success, list of ids and info of groups belonging to survey, else, None """ groups = self.server.list_groups(self.session_key, sid) return groups if isinstance(groups, list) else None @abstractmethod def get_group_properties(self, gid): """ :param gid: LimeSurvey group id :param lang: group language to return correct group, as Remote Control API does not do that (TODO (NES-956): see why lang is gone :return: list of group properties """ result = self.server.get_group_properties(self.session_key, gid) # TODO (NES-963): treat errors return result def set_group_properties(self, sid, data): result = self.server.set_group_properties(self.session_key, sid, data) # TODO (NES-963): treat errors return result def list_questions(self, sid, gid): """List questions with their properties :param sid: LimeSurvey survey id :param gid: LimeSurvey group id :return: on success, list of question properties, else None """ questions = self.server.list_questions(self.session_key, sid, gid) return questions if isinstance(questions, list) else None @abstractmethod def list_questions_ids(self, sid, gid): """ :param sid: LimeSurvey survey id :param gid: LimeSurvey group id :return: ids and info of (sub-)questions of a survey/group """ question_ids = [] questions = self.list_questions(sid, gid) if questions is not None: for question in questions: question_ids.append(question['id']['qid']) return question_ids @abstractmethod def find_tokens_by_questionnaire(self, sid): """ :param sid: :return: list of tokens | dict with error status """ tokens = self.server.list_participants(self.session_key, sid, 0, 99999999) # If some error occurs RPC returns a dict, so return None return tokens if isinstance(tokens, list) else None def add_group(self, sid, title, description): result = self.server.add_group(self.session_key, sid, title) # TODO (NES-963): treat errors return result def add_response(self, sid, response_data): result = self.server.add_response(self.session_key, sid, response_data) # TODO (NES-963): treat errors return result def set_participant_properties(self, sid, tid, properties_dict): result = self.server.set_participant_properties( self.session_key, sid, tid, properties_dict) # TODO (NES-963): treat errors return result def import_survey(self, base64_encoded_lsa): """ :param base64_encoded_lsa: Base 64 encoded string from lsa archive :return: lime survey id of survey created """ result = self.server.import_survey(self.session_key, base64_encoded_lsa, 'lsa') # RPC returns dict with error status if an issue occurred return None if isinstance(result, dict) else result def export_survey(self, sid): """TODO (NES-956): insert docstring :param sid: LimeSurvey survey id :return: on success base64 encoded survey, else None """ result = self.server.export_survey(self.session_key, sid) if isinstance(result, dict): # Returned a dict element (error) return None return result def delete_responses(self, sid, responses): """Delete responses from LimeSurvey survey :param sid: LimeSurvey survey id :param responses: list of response ids :return: on success, dict with status ok, else None """ result = self.server.delete_responses(self.session_key, sid, responses) return result if result['status'] == 'OK' else None def update_response(self, sid, response_data): result = self.server.update_response(self.session_key, sid, response_data) return result if result['status'] == 'OK' else None