frontend_tests.py 9.01 KB
import os
import unittest
import urllib.request

from flask import url_for
from flask_testing import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.select import Select

from app import create_app
from app.models import Agent, Charge
from pdc_config import TestConfig
from tests.common_db_feed import resources_to_instancedb


class BaseFrontTestCase(LiveServerTestCase):
    def create_app(self):
        # # remove logging lines on test output
        import logging
        log = logging.getLogger('werkzeug')
        log.setLevel(logging.INFO)
        log.disabled = True
        os.environ['WERKZEUG_RUN_MAIN'] = 'true'

        # pass in test configurations
        self.app = create_app(TestConfig)
        self.db_path = resources_to_instancedb(self.app)
        self.app.config.update(
            # Specify the test database as the default in_memory wont work for web tests
            SQLALCHEMY_DATABASE_URI='sqlite:///' + self.db_path,
            # Change the port that the liveserver listens on as we dont want to conflict with running:5000
            LIVESERVER_PORT=8943
        )

        self.app_context = self.app.app_context()
        self.app_context.push()
        return self.app

    def setUp(self):
        self.driver = self.create_chrome_driver()
        # db.create_all()

    def tearDown(self):
        # fs_utils.clean_dirs()
        # db.session.remove()
        # db.drop_all()
        self.app_context.pop()
        if os.path.exists(self.db_path):
            os.remove(self.db_path)
        self.driver.close()
        self.driver.quit()

    # noinspection PyMethodMayBeStatic
    def is_in_docker(self):
        """
        Test if in docker.
        :return: True if running in docker, False otherwise.
        """
        if os.path.exists('/proc/self/cgroup'):
            with open('/proc/self/cgroup') as f:
                content = f.read()
                return '/docker/' in content
        return False

    def create_chrome_driver(self):
        """
        Create then return the chrome driver.

        :return: the chrome driver.
        """
        from selenium.webdriver.chrome.options import Options
        options = Options()
        options.add_argument('--headless')
        # options.add_argument('--log-level=3')
        # options.add_experimental_option('excludeSwitches', ['enable-logging'])

        if self.is_in_docker():
            options.add_argument("--no-sandbox")
        return webdriver.Chrome(options=options)


class AccessTestCase(BaseFrontTestCase):
    def test_ping(self):
        self.assertEqual("http://localhost:8943", self.get_server_url())

    def test_selenium_access(self):
        # On ouvre le navigateur avec l'adresse du serveur.
        self.driver.get(self.get_server_url())
        # L'adresse dans l'url doit être celle que l'on attend.
        self.assertEqual(self.driver.current_url, 'http://localhost:8943/')

    def test_server_is_up_and_running(self):
        response = urllib.request.urlopen(self.get_server_url())
        self.assertEqual(response.code, 200)

    def test_agents_page(self):
        target_url = self.get_server_url() + url_for('main.agents')
        self.driver.get(target_url)
        self.assertEqual(self.driver.current_url, 'http://localhost:8943/agents')

    def test_agent_page(self):
        agent_id = 60
        target_url = self.get_server_url() + url_for('main.agent', agent_id=agent_id)
        self.driver.get(target_url)
        self.assertEqual(self.driver.current_url, f'http://localhost:8943/agent/{agent_id}')
        td_elmts = self.driver.find_elements_by_xpath("//table[@id='charge_table']/tbody/tr/td")
        self.assertEqual(260, len(td_elmts))

    def test_projects_page(self):
        target_url = self.get_server_url() + url_for('main.projects')
        self.driver.get(target_url)
        self.assertEqual(self.driver.current_url, 'http://localhost:8943/projects')

    def test_projects_trs(self):
        target_url = self.get_server_url() + url_for('main.projects')
        self.driver.get(target_url)
        td_elmts = self.driver.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(101, len(td_elmts))

    def test_projects_tds(self):
        target_url = self.get_server_url() + url_for('main.projects')
        self.driver.get(target_url)
        for tr in self.driver.find_elements_by_xpath("//table/tbody/tr"):
            with self.subTest(tr):
                tds = tr.find_elements_by_tag_name('td')
                self.assertEqual(4, len(tds), tds[0].text + " has wrong number of columns")

    def test_project_page(self):
        project_id = 8
        target_url = self.get_server_url() + url_for('main.project', project_id=project_id)
        self.driver.get(target_url)
        self.assertEqual(self.driver.current_url, f'http://localhost:8943/project/{project_id}')
        td_elmts = self.driver.find_elements_by_xpath("//table[@id='charge_table']/tbody/tr/td")
        self.assertEqual(1085, len(td_elmts))

    def test_project_page_categories(self):
        project_id = 84
        target_url = self.get_server_url() + url_for('main.project', project_id=project_id)
        self.driver.get(target_url)
        self.assertEqual(self.driver.current_url, f'http://localhost:8943/project/{project_id}')
        # pole_dt_db = self.driver.find_element_by_xpath("//dt[text()='Pôle']/following-sibling::dd")
        pole_dt_db = self.driver.find_element_by_xpath("//dt[contains(text(),'Pôle')]/following-sibling::dd")
        self.assertEqual('Solaire', pole_dt_db.text)
        domaine_dt_db = self.driver.find_element_by_xpath("//dt[contains(text(),'Domaine')]/following-sibling::dd")
        self.assertTrue('LESIA' in domaine_dt_db.text)


class FormsTestCase(BaseFrontTestCase):

    def test_agent_add(self):
        # load the form
        target_url = self.get_server_url() + url_for('main.agent_edit')
        self.driver.get(target_url)
        # fill it in
        firstname_input = self.driver.find_elements_by_xpath("//input[@id='firstname']")[0]
        firstname_input.send_keys("Hitier")
        secondname_input = self.driver.find_elements_by_xpath("//input[@id='secondname']")[0]
        secondname_input.send_keys("Richard")
        # submit
        submit_button = self.driver.find_elements_by_xpath("//input[@type='submit']")[0]
        submit_button.send_keys(Keys.ENTER)
        # check on database
        latest_agent = Agent.query.order_by(Agent.id.desc()).all()[0]
        self.assertEqual('Hitier', latest_agent.firstname)

    # Test agent form
    def test_agent_edit(self):
        # load the form
        target_url = self.get_server_url() + url_for('main.agent_edit', agent_id=1)
        self.driver.get(target_url)
        # fill it in
        firstname_input = self.driver.find_elements_by_xpath("//input[@id='firstname']")[0]
        self.assertEqual("Dubois", firstname_input.get_attribute('value'))
        firstname_input.clear()
        firstname_input.send_keys("Hitier")
        # # submit
        submit_button = self.driver.find_elements_by_xpath("//input[@type='submit']")[0]
        submit_button.send_keys(Keys.ENTER)
        # # check on database
        latest_agent = Agent.query.filter(Agent.id == 1).one()
        self.assertEqual('Hitier', latest_agent.firstname)

    # Test charge form add new
    def test_charge_add(self):
        # load the form
        target_url = self.get_server_url() + url_for('main.charge_add')
        self.driver.get(target_url)
        # fill it in
        agent_select = Select(self.driver.find_elements_by_xpath("//select[@id='agent_id']")[0])
        agent_select.select_by_index(1)
        project_select = Select(self.driver.find_elements_by_xpath("//select[@id='project_id']")[0])
        project_select.select_by_index(1)
        service_select = Select(self.driver.find_elements_by_xpath("//select[@id='service_id']")[0])
        service_select.select_by_index(1)
        period_select = Select(self.driver.find_elements_by_xpath("//select[@id='period_id']")[0])
        period_select.select_by_index(1)
        capacity_select = Select(self.driver.find_elements_by_xpath("//select[@id='capacity_id']")[0])
        capacity_select.select_by_index(1)
        charge_input = self.driver.find_elements_by_xpath("//input[@id='charge_rate']")[0]
        charge_input.send_keys("99")

        # submit
        submit_button = self.driver.find_elements_by_xpath("//input[@type='submit']")[0]
        submit_button.send_keys(Keys.ENTER)
        # check on database
        latest_charge = Charge.query.order_by(Charge.id.desc()).all()[0]
        self.assertEqual([514, 41, 17, 1, 1, 99],
                         [latest_charge.agent_id,
                          latest_charge.project_id,
                          latest_charge.service_id,
                          latest_charge.capacity_id,
                          latest_charge.period_id,
                          latest_charge.charge_rate]
                         )

    # Test charge form edit existing
    @unittest.skip("charge edit to be implemented")
    def test_charge_edit(self):
        pass