diff options
Diffstat (limited to 'webapp/webapp')
18 files changed, 486 insertions, 12 deletions
diff --git a/webapp/webapp/features/active_resultados_button.feature b/webapp/webapp/features/active_resultados_button.feature new file mode 100644 index 0000000..0ab83a9 --- /dev/null +++ b/webapp/webapp/features/active_resultados_button.feature @@ -0,0 +1,11 @@ +Feature: Button for show results is active when a poll has results + As a researcher, I can do click in "Resultados" button + of "list of polls" page to see "Resultados" page + + Scenario: A poll with .poll_results uploaded + Given I am a researcher + And "poll1" exists + And "encuestador1" is binded to "poll1" + And with "simple.poll_result" uploaded by "encuestador1" on "31/12/2000 24:00hs" + When I visit the "list of polls" page + Then I should see active a "Resultados" button
\ No newline at end of file diff --git a/webapp/webapp/features/active_resultados_button.py b/webapp/webapp/features/active_resultados_button.py new file mode 100644 index 0000000..7876d59 --- /dev/null +++ b/webapp/webapp/features/active_resultados_button.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +from lettuce import step, world + + +@step(u'.*I should see active a "([^"]*)" button') +def i_should_see_active_a_status_button(step, status): + browser = world.browser + xpath = "/html/body/div/div[2]/div/table/tbody/tr[1]/td[4]/a" + element = browser.find_by_xpath(xpath).first + + assert not element.has_class('disabled') diff --git a/webapp/webapp/features/download_csv_button.py b/webapp/webapp/features/download_csv_button.py new file mode 100644 index 0000000..8543f94 --- /dev/null +++ b/webapp/webapp/features/download_csv_button.py @@ -0,0 +1,22 @@ +from lettuce import step, world +from lettuce.django import django_url +from nose.tools import assert_true, assert_equals +from django.core.urlresolvers import reverse + + +@step(u'Then I should see a "([^"]*)" button') +def then_i_should_see_a_label_button(step, button_label): + browser = world.browser + button_names = {"Descargar resultados (csv)": "download_results_as_csv"} + button_name = button_names[button_label] + assert_true( + browser.is_element_present_by_name(button_name)) + world.button = browser.find_by_name(button_name)[0] + + +@step(u'And the button links to "([^"]*)" for "([^"]*)"') +def button_links_to_url_name_for_poll_name(step, url_name, poll_name): + poll_id = str(world.poll_id) + button = world.button + csv_download_url = reverse(url_name, kwargs={'poll_id': poll_id}) + assert_equals(django_url(csv_download_url), button['href']) diff --git a/webapp/webapp/features/download_csv_button_exists.feature b/webapp/webapp/features/download_csv_button_exists.feature new file mode 100644 index 0000000..50ddf76 --- /dev/null +++ b/webapp/webapp/features/download_csv_button_exists.feature @@ -0,0 +1,11 @@ +Feature: Button for download results as csv + As a reasearcher + I want see a csv button + So that I can download all results + + Scenario: Visit "Resultados" page with at least one .poll_result + Given I am a researcher + And "poll1" exists + When I visit the "Resultados" page for "poll1" poll + Then I should see a "Descargar resultados (csv)" button + And the button links to "sociologist:csv_download" for "poll1" diff --git a/webapp/webapp/features/download_poll_result_file.feature b/webapp/webapp/features/download_poll_result_file.feature new file mode 100644 index 0000000..97acd08 --- /dev/null +++ b/webapp/webapp/features/download_poll_result_file.feature @@ -0,0 +1,12 @@ +Feature: Link to download .poll_result file + As a reasearcher + I want to be able to download a .poll_result of a poll + So that I can analyse it as it is + + Scenario: One .poll_result uploaded + Given I am a researcher + And "poll1" is "Cerrada" + And "encuestador1" is binded to "poll1" + And with "simple.poll_result" uploaded by "encuestador1" on "31/12/2000 23:59hs" + When I visit the "Resultados" page for "poll1" poll + Then I should see link to "simple.poll_result"
\ No newline at end of file diff --git a/webapp/webapp/features/fixtures/2schools.poll_result b/webapp/webapp/features/fixtures/2schools.poll_result new file mode 100644 index 0000000..707c8ea --- /dev/null +++ b/webapp/webapp/features/fixtures/2schools.poll_result @@ -0,0 +1,33 @@ +{ + "poll_id":"", + "poll_name":"", + "poll_type":"general", + "pollster_id":"", + "pollster_username":"", + "result":{ + "0":{ + "answers":{}, + "polled":{ + "DEPARTAMENTO":"MONTEVIDEO", + "GRADO":"2", + "GRUPO":"A", + "ID":"0", + "NUM_ESC":"1", + "RUEE":"1101236", + "TIPO_GRUPO":"1" + } + }, + "1":{ + "answers":{}, + "polled":{ + "DEPARTAMENTO":"MONTEVIDEO", + "GRADO":"2", + "GRUPO":"A", + "ID":"0", + "NUM_ESC":"2", + "RUEE":"1101236", + "TIPO_GRUPO":"1" + } + } + } +}
\ No newline at end of file diff --git a/webapp/webapp/features/fixtures/simple.poll_result b/webapp/webapp/features/fixtures/simple.poll_result new file mode 100644 index 0000000..18c7308 --- /dev/null +++ b/webapp/webapp/features/fixtures/simple.poll_result @@ -0,0 +1,21 @@ +{ + "poll_id":"", + "poll_name":"", + "poll_type":"general", + "pollster_id":"", + "pollster_username":"", + "result":{ + "0":{ + "answers":{}, + "polled":{ + "DEPARTAMENTO":"MONTEVIDEO", + "GRADO":"2", + "GRUPO":"A", + "ID":"0", + "NUM_ESC":"236", + "RUEE":"1101236", + "TIPO_GRUPO":"1" + } + } + } +}
\ No newline at end of file diff --git a/webapp/webapp/features/fixtures/simple2.poll_result b/webapp/webapp/features/fixtures/simple2.poll_result new file mode 100644 index 0000000..bb9168b --- /dev/null +++ b/webapp/webapp/features/fixtures/simple2.poll_result @@ -0,0 +1,33 @@ +{ + "poll_id":"", + "poll_name":"", + "poll_type":"general", + "pollster_id":"", + "pollster_username":"", + "result":{ + "0":{ + "answers":{}, + "polled":{ + "DEPARTAMENTO":"MONTEVIDEO", + "GRADO":"2", + "GRUPO":"A", + "ID":"0", + "NUM_ESC":"236", + "RUEE":"1101236", + "TIPO_GRUPO":"1" + } + }, + "1":{ + "answers":{}, + "polled":{ + "DEPARTAMENTO":"MONTEVIDEO", + "GRADO":"2", + "GRUPO":"A", + "ID":"0", + "NUM_ESC":"236", + "RUEE":"1101236", + "TIPO_GRUPO":"1" + } + } + } +}
\ No newline at end of file diff --git a/webapp/webapp/features/index.py b/webapp/webapp/features/index.py index e273bd9..b7e2a72 100644 --- a/webapp/webapp/features/index.py +++ b/webapp/webapp/features/index.py @@ -1,14 +1,8 @@ -from lettuce import * -from splinter import Browser +from lettuce import step, world from nose.tools import assert_equals from lettuce.django import django_url -@before.all -def set_browser(): - world.browser = Browser('phantomjs') - - @step(r'I access the url "(.*)"') def access_url(step, url): url = django_url(url) @@ -18,8 +12,3 @@ def access_url(step, url): @step(r'I should see "(.*)" as title') def then_i_should_see_the_title_group1(step, title): assert_equals(world.browser.title, title) - - -@after.all -def exit_browser(total): - world.browser.quit() diff --git a/webapp/webapp/features/poll_result_details.feature b/webapp/webapp/features/poll_result_details.feature new file mode 100644 index 0000000..331bad3 --- /dev/null +++ b/webapp/webapp/features/poll_result_details.feature @@ -0,0 +1,20 @@ +Feature: A Researcher sees the .poll_result details of a poll + As a Researcher + I want see the .poll_result details of a given poll + So that I can inspect a particular .poll_result + And I can see the .poll_results uploaded during the progress of a poll + + Scenario: 3 .poll_results uploaded + Given I am a researcher + And "poll1" is "Cerrada" + And "encuestador1" is binded to "poll1" + And "encuestador2" is binded to "poll1" + And with "simple.poll_result" uploaded by "encuestador1" on "31/12/2000 24:00hs" + And with "simple2.poll_result" uploaded by "encuestador2" on "01/01/2001 00:01hs" + And with "2schools.poll_result" uploaded by "encuestador2" on "15/09/2013 09:14hs" + When I visit the "Resultados" page for "poll1" poll + Then I should see the poll_result details: + | Número de escuela | Nombre de Encuestador | Cantidad de Encuestados | Nombre del Archivo .polls_results | Time Stamp | + | 236 | encuestador1 | 1 | simple.poll_result | 31/12/2000 24:00hs | + | 236 | encuestador2 | 2 | simple2.poll_result | 01/01/2001 00:01hs | + | 1, 2 | encuestador2 | 2 | 2schools.poll_result | 15/09/2013 09:14hs | diff --git a/webapp/webapp/features/poll_result_details.py b/webapp/webapp/features/poll_result_details.py new file mode 100644 index 0000000..a63c246 --- /dev/null +++ b/webapp/webapp/features/poll_result_details.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +import json +import os +import tempfile +import shutil + +from lettuce import step, world, after +from lettuce.django import django_url +from nose.tools import assert_equals +from django.conf import settings + +from pollster.models import Pollster +from polls.models import Poll + + +def create_poll_result_file(poll_result_data, poll_result_name): + tmp_file = tempfile.NamedTemporaryFile(suffix='.poll_result', delete=False) + try: + tmp_file.write( + json.dumps(poll_result_data, sort_keys=True, indent=4, + separators=(',', ': ')) + ) + tmp_dir = os.path.dirname(tmp_file.name) + poll_result_path = os.path.join(tmp_dir, poll_result_name) + os.rename(tmp_file.name, poll_result_path) + finally: + tmp_file.close() + return poll_result_path + + +def get_pollster_by_username(encuestador_name): + return filter(lambda e: e.username == encuestador_name, Pollster.all())[0] + + +@step(u'When I visit the "([^"]*)" page for "([^"]*)" poll') +def visit_page_for_poll(step, page_name, poll_name): + page_list = {'Resultados': 'results'} + page = page_list[page_name] + poll_id = world.poll_id.__str__() + b = world.browser + url = '/manager/polls/{poll_id}/{page}/'.format(poll_id=poll_id, page=page) + b.visit(django_url(url)) + + +@step(u'Then I should see the poll_result details:') +def then_i_should_see_the_poll_result_details(step): + b = world.browser + for poll_result_details in step.hashes: + for detail_desc in poll_result_details.keys(): + assert b.is_text_present(detail_desc), \ + detail_desc.encode('utf-8') + " is not present" + value = poll_result_details[detail_desc] + assert b.is_text_present(value), \ + value.encode('utf-8') + " is not present" + + +@after.each_feature +def remove_poll_results_files(feature): + if feature.name == 'Poll result details': + MEDIA_RESULTS = settings.RESULT_BCK_ROOT + result_dir = os.path.join(MEDIA_RESULTS, world.poll_id.__str__()) + shutil.rmtree(result_dir) + + +@step(u'Then I should see link to "([^"]*)"') +def then_i_should_see_link_to_poll_result_name(step, poll_result_name): + browser = world.browser + poll_id = str(world.poll_id) + poll = Poll.get(poll_id) + poll_result_file = poll.get_result_files()[0] + + poll_result_url = poll_result_file.get_absolute_url() + element = browser.find_by_name("poll_result_file").first + assert_equals(django_url(poll_result_url), element['href']) diff --git a/webapp/webapp/features/resultados_need_poll_name.feature b/webapp/webapp/features/resultados_need_poll_name.feature new file mode 100644 index 0000000..5ac23da --- /dev/null +++ b/webapp/webapp/features/resultados_need_poll_name.feature @@ -0,0 +1,7 @@ +Feature: Result page for a poll needs poll name + + Scenario: "Result" page has name of current poll + Given I am a researcher + And "poll1" exists + When I visit the "Resultados" page for "poll1" poll + Then I should see a message that says "Poll1" diff --git a/webapp/webapp/features/steps.py b/webapp/webapp/features/steps.py new file mode 100644 index 0000000..1f5a2fd --- /dev/null +++ b/webapp/webapp/features/steps.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +import os +import json +import shutil + +from lettuce.django import django_url +from lettuce import step, world +from django.conf import settings +from nose.tools import assert_true + +from sociologist.models import Sociologist +from pollster.models import Pollster +from polls.models import Poll +from poll_result_details import get_pollster_by_username + +from poll_result_details import create_poll_result_file + + +@step(u'When I visit the "([^"]*)" page$') +def when_i_visit_the_page_name(step, page_name): + page_list = { + 'upload': 'polls/upload_result', + 'list of polls': 'manager/polls/' + } + page = page_list[page_name] + b = world.browser + b.visit(django_url(page)) + + +@step(u'Given I am a researcher') +def given_i_am_a_researcher(step): + username = "researcher" + password = username + create_user_and_login(Sociologist, username, password) + + +def login(browser, username, password): + browser.visit(django_url('/accounts/login')) + browser.fill_form({'username': username, 'password': password}) + login_xpath = '/html/body/div/div[2]/div/form/fieldset/button' + browser.find_by_xpath(login_xpath).first.click() + + +@step(u'Given I am a pollster: "([^"]*)"') +def given_i_am_a_pollster_username(step, username): + password = username + create_user_and_login(Pollster, username, password) + + +def create_user_and_login(rol, username, password): + rol.create(username=username, password=password) + b = world.browser + login(b, username, password) + + +def create_poll(name, status=Poll.OPEN): + poll = Poll(data={'name': name, 'status': status}) + world.poll_id = poll.save() + + +@step(u'And "([^"]*)" exists') +def and_poll_name_exists(step, poll_name): + create_poll(poll_name) + + +@step(u'And "([^"]*)" is "([^"]*)"') +def and_poll_is_status(step, poll_name, status): + status = Poll.CLOSED if status == "Cerrada" else Poll.OPEN + create_poll(poll_name, status) + + +@step(u'And "([^"]*)" is binded to "([^"]*)"') +def and_encuestador_is_binded_to_poll(step, encuestador, poll_name): + username = encuestador + password = username + try: + pollster = get_pollster_by_username(encuestador) + except IndexError: + pollster = Pollster.create(username=username, password=password) + polls = [world.poll_id] + Poll.pollster_assignment(pollster.id, polls) + + +def get_fixture(poll_result): + path = os.path.abspath(os.path.dirname(__file__)) + path = os.path.join(path, "fixtures", poll_result) + return path + + +@step(u'And with "([^"]*)" uploaded by "([^"]*)" on "([^"]*)"') +def poll_result_uploaded_by_encuestador(step, poll_result_name, + encuestador_name, datetime_str): + poll_result_path = get_fixture(poll_result_name) + encuestador = get_pollster_by_username(encuestador_name) + + with open(poll_result_path) as f: + poll_result_data = json.load(f, "utf-8") + poll_result_data['poll_id'] = world.poll_id.__str__() + poll_result_data['pollster_username'] = encuestador.username + poll_result_data['pollster_id'] = encuestador.id.__str__() + poll_result_data['upload_timestamp'] = datetime_str + + poll_result_path = create_poll_result_file(poll_result_data, + poll_result_name) + + media_results = settings.RESULT_BCK_ROOT + results_dir = os.path.join(media_results, world.poll_id.__str__()) + if not os.path.exists(results_dir): + os.mkdir(results_dir) + shutil.move(poll_result_path, results_dir) + + +@step(u'Then I should see a message that says "([^"]*)"$') +def i_should_see_a_message_that_says_text(step, text): + b = world.browser + assert_true(b.is_text_present(text)) diff --git a/webapp/webapp/features/terrain.py b/webapp/webapp/features/terrain.py new file mode 100644 index 0000000..70f079b --- /dev/null +++ b/webapp/webapp/features/terrain.py @@ -0,0 +1,33 @@ +from lettuce import world, before, after +from splinter import Browser +from fabric.api import local +from fabric.context_managers import hide +from django.conf import settings +from django.core import management + + +@before.all +def set_browser(): + world.browser = Browser('phantomjs') + + +@after.all +def exit_browser(total): + world.browser.quit() + + +def drop_mongo(): + db = settings.MONGO_SETTINGS['NAME'] + with hide('running'): + cmd = "mongo {mongo_db} --eval 'db.dropDatabase()' > /dev/null" + local(cmd.format(mongo_db=db)) + + +def drop_sqlite(): + management.call_command('flush', interactive=False, verbosity=0) + + +@before.each_feature +def before_each_feature(feature): + drop_mongo() + drop_sqlite() diff --git a/webapp/webapp/features/upload_poll_result.feature b/webapp/webapp/features/upload_poll_result.feature new file mode 100644 index 0000000..fa01a95 --- /dev/null +++ b/webapp/webapp/features/upload_poll_result.feature @@ -0,0 +1,14 @@ +Feature: Upload .poll_result files + As a pollster + I want to upload .poll_result files + So that researcher can compute them like a chunk of the whole poll result + + Scenario: Upload one valid .poll_result file + Given I am a pollster: "encuestador1" + And "poll1" is "Cerrada" + And "encuestador1" is binded to "poll1" + And "valid.poll_result" is authored by "encuestador1" + When I visit the "upload" page + And I upload "valid.poll_result" on "31/12/1999 23:59hs" + Then I should see a message that says "valid.poll_result" and "éxito" + And "valid.poll_result" has the time string "31/12/1999 23:59hs" diff --git a/webapp/webapp/features/upload_poll_result.py b/webapp/webapp/features/upload_poll_result.py new file mode 100644 index 0000000..dc15c42 --- /dev/null +++ b/webapp/webapp/features/upload_poll_result.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +from lettuce import step, world +from nose.tools import assert_true, assert_equals + +from polls.models import Poll +from poll_result_details import (create_poll_result_file, + get_pollster_by_username) + + +@step(u'And "([^"]*)" is authored by "([^"]*)"') +def result_file_is_authored_by_pollster(step, file_name, pollster_username): + pollster = get_pollster_by_username(pollster_username) + data = {} + data['poll_id'] = world.poll_id.__str__() + data['pollster_username'] = pollster.username + data['pollster_id'] = pollster.id.__str__() + data['result'] = {} + world.poll_result_path = create_poll_result_file(data, file_name) + + +@step(u'And I upload "([^"]*)" on "([^"]*)"') +def upload_file_name_on_time_string(step, file_name, time_string): + b = world.browser + b.find_by_xpath('/html/body/div/div[2]/form/fieldset/div/button').click() + b.attach_file('result', world.poll_result_path) + b.find_by_xpath('/html/body/div/div[2]/form/div[1]/div/button').click() + + +@step(u'Then I should see a message that says "([^"]*)" and "([^"]*)"') +def i_should_see_a_message_that_says_text1_and_text2(step, text1, text2): + b = world.browser + assert_true(b.is_text_present(text1)) + assert_true(b.is_text_present(text2)) + + +@step(u'And "([^"]*)" has the time string "([^"]*)"') +def file_name_has_the_time_string_time_string(step, file_name, time_string): + poll = Poll.get(world.poll_id) + result_files = poll.get_result_files() + result_file = filter( + lambda f: file_name == f.get_file_name(), result_files)[0] + # Using (mock) Clock class from django settings + assert_equals(time_string, result_file.get_upload_timestamp()) diff --git a/webapp/webapp/settings.py b/webapp/webapp/settings.py index 865817b..b3e5671 100644 --- a/webapp/webapp/settings.py +++ b/webapp/webapp/settings.py @@ -126,6 +126,10 @@ TEMPLATE_DIRS = ( PROJECT_ROOT + "/templates", ) +FILE_UPLOAD_HANDLERS = ( + "django.core.files.uploadhandler.TemporaryFileUploadHandler", +) + INSTALLED_APPS = ( # Test Runner @@ -215,12 +219,16 @@ IMAGES_ROOT = MEDIA_ROOT + 'images' RESULT_BCK_ROOT = MEDIA_ROOT + 'results_bck' +RESULT_BCK_URL = MEDIA_URL + 'results_bck' + IMAGE_OPTIONS_MEDIA_URL = MEDIA_URL + 'image_options' IMAGES_MEDIA_URL = MEDIA_URL + 'images' THUMBNAIL_DEBUG = True +CLOCK_CLASS = "utils.clock.Clock" + try: from env_settings import * except ImportError: diff --git a/webapp/webapp/test_settings.py b/webapp/webapp/test_settings.py index 099352f..5e8b856 100644 --- a/webapp/webapp/test_settings.py +++ b/webapp/webapp/test_settings.py @@ -23,3 +23,19 @@ register_connection( LETTUCE_SERVER_PORT = 63001 + + +DATABASES['default']['TEST_NAME'] = '/tmp/testserver.db' + + +RESULT_BCK_ROOT = '/tmp' + + +class MockClock(object): + + @staticmethod + def get_time_string(): + return "31/12/1999 23:59hs" + + +CLOCK_CLASS = "webapp.test_settings.MockClock" |