gbazilio/nfebrasil

View on GitHub
api/tests.py

Summary

Maintainability
A
0 mins
Test Coverage
import os
from collections import namedtuple
from unittest import mock

from django.test import TestCase
from django.test.client import Client
from jsonschema.exceptions import ValidationError
from jsonschema.validators import validate
from oauth2_provider.models import AccessToken
from rest_framework import status
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView

import api.views as views
from api.parser import NFeParser
from api.webdriver_threading import WebDriverThread


class NFeRootViewsTestCase(TestCase):

    def tearDown(self):
        views.application_webdrivers.clear()

    @mock.patch('api.webdriver_threading.WebDriverThread.quit')
    @mock.patch('api.webdriver_threading.WebDriverThread.start')
    @mock.patch('api.navigator.NFeNavigator.get_captcha')
    def test_should_get_captcha_src(
            self, mock_captcha, mock_thread, mock_quit):

        expected_json_schema = {
            'type': 'object',
            'properties': {
                'captcha_src': {
                    'type': 'string',
                    'pattern': '^data:image/png;base64,.+'
                }
            },
            'required': ['captcha_src'],
            'additionalProperties': False
        }
        mock_captcha.return_value = 'data:image/png;base64,asdkjdlasdsd='
        # There is no need to really start the threaded web driver
        mock_thread.return_value = None
        mock_quit.return_value = None

        nfe_key = '1' * 44
        request = self._make_authenticated_request_object(
            '18273319832', nfe_key)
        response = views._get_nfe(request, nfe_key)

        try:
            validate(response.data, expected_json_schema)
        except ValidationError as e:
            self.fail(e.message)

    def _mock_request_auth_token(self, request, token):
        auth_mock = namedtuple('AuthMock', 'token')
        auth = auth_mock(token=token)
        setattr(request, 'auth', auth)

    def _make_authenticated_request_object(self, token, nfe_key, captcha=None):

        url = '/nfe/%s' % nfe_key
        url = url + '?captcha=%s' % captcha if captcha else url

        captcha_get_request = APIRequestFactory().get(url)
        captcha_get_request = APIView().initialize_request(captcha_get_request)
        self._mock_request_auth_token(captcha_get_request, token)
        return captcha_get_request

    @mock.patch('api.webdriver_threading.WebDriverThread.quit')
    @mock.patch('api.webdriver_threading.WebDriverThread.start')
    @mock.patch('api.navigator.NFeNavigator.get_captcha')
    @mock.patch('api.navigator.NFeNavigator.get_nfe')
    def test_should_get_nfe_with_using_same_webdriver(
            self, mock_nfe, mock_captcha, mock_thread, mock_quit):

        expected_number_of_drivers_in_scope = 1
        expected_token_key_in_scope = 'asdkj312313'

        mock_captcha.return_value = 'data:image/png;base64,asdkjdlasdsd='
        mock_nfe.return_value = {}

        # There is no need to really start the threaded web driver
        mock_thread.return_value = None
        mock_quit.return_value = None

        # NFe key
        nfe_key = '1' * 44

        captcha_get_request = self._make_authenticated_request_object(
            expected_token_key_in_scope, nfe_key)
        captcha_get_response = views._get_nfe(captcha_get_request, nfe_key)

        nfe_get_request = self._make_authenticated_request_object(
            expected_token_key_in_scope, nfe_key,
            captcha_get_response.data['captcha_src'])
        views._get_nfe(nfe_get_request, nfe_key)

        self.assertTrue(expected_token_key_in_scope in
                        views.application_webdrivers.keys())
        self.assertEquals(len(views.application_webdrivers.keys()),
                          expected_number_of_drivers_in_scope)


class NFeParserTestCase(TestCase):
    def setUp(self):
        asset_path = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'test_assets/nfe_multiple_items.html'
        )

        self.asset_nfe_html = open(asset_path, 'rt',
                                   encoding='iso-8859-1').read()

    def test_should_parse_nfe_html(self):
        expected = {
            'nfe': {
                'dados': {
                    'serie': 3,
                    'numero': '10611731',
                    'total': 47.90
                },
                'emitente': {
                    'cnpj': '00.776.574/0007-41',
                    'razao_social': 'B2W Companhia Digital',
                    'nome_fantasia': '',
                    'endereco': 'Estrada dos Alpes, 555, S/N',
                    'uf': 'SP',
                    'cidade': '3522505 - ITAPEVI'
                },
                'items': [
                    {
                        'indice': 1,
                        'descricao': 'Livro - 7 Habitos das Pessoas Altamente Eficazes',
                        'quantidade': 1.0,
                        'unidade': 'PC',
                        'valor': 26.90
                    },
                    {
                        'indice': 2,
                        'descricao': 'Livro - Vendendo o Invisivel',
                        'quantidade': 1.0,
                        'unidade': 'PC',
                        'valor': 21.0
                    }
                ]
            }
        }

        sut = NFeParser(self.asset_nfe_html)
        result = sut.parse_to_json()

        self.assertDictEqual(expected, result)


class NFeRoutesTestCase(TestCase):
    fixtures = ['oauth2_valid_token.json']

    def setUp(self):
        self.access_token = AccessToken.objects.last()

    def tearDown(self):
        thread = WebDriverThread.get_driver(
            views.application_webdrivers, self.access_token.token)
        thread.quit()

    @mock.patch('api.navigator.NFeNavigator.get_captcha')
    def test_should_get_a_valid_captcha(self, mock_captcha):
        nfe_key = '11223344556677889900112233445566778899112233'
        expected_captcha_src = 'data:image/png;base64,asdkjdlasdsd='

        mock_captcha.return_value = expected_captcha_src

        sut = Client(HTTP_AUTHORIZATION='Bearer ' + self.access_token.token)
        response = sut.get('/api/nfe/%s' % nfe_key)

        self.assertEquals(status.HTTP_200_OK, response.status_code)
        self.assertEquals(expected_captcha_src, response.data['captcha_src'])

    @mock.patch('selenium.webdriver.PhantomJS.find_element_by_id')
    def test_should_get_502_when_captcha_isnt_available(
            self, mock_find_element_by_id):
        nfe_key = '11223344556677889900112233445566778899112233'
        expected_error_message = {
            'errors': [
                {
                    'status': status.HTTP_502_BAD_GATEWAY,
                    'humanMessage': 'A pagina da receita sofreu '
                                    'modificacoes estruturais no HTML. '
                                    'Entre em contato com o desensolvedor '
                                    'desse modulo.',
                    'developerMessage': 'No captcha image found on target URL '
                                        'http://www.nfe.fazenda.gov.br/portal/'
                                        'consulta.aspx?tipoConsulta=completa&'
                                        'tipoConteudo=XbSeqxE8pl8= when trying'
                                        ' to search for element ctl00_'
                                        'ContentPlaceHolder1_imgCaptcha.'
                }
            ]
        }

        mock_find_element_by_id.side_effect = Exception()

        sut = Client(HTTP_AUTHORIZATION='Bearer ' + self.access_token.token)
        response = sut.get('/api/nfe/%s' % nfe_key)

        self.assertEquals(status.HTTP_502_BAD_GATEWAY, response.status_code)
        self.assertDictEqual(expected_error_message, response.data)

    @mock.patch('selenium.webdriver.PhantomJS.execute_script')
    def test_should_get_502_when_continue_button_isnt_available(
            self, mock_execute_script):
        nfe_key = '11223344556677889900112233445566778899112233'
        expected_error_message = {
            'errors': [
                {
                    'status': status.HTTP_502_BAD_GATEWAY,
                    'humanMessage': 'A pagina da receita sofreu '
                                    'modificacoes estruturais no HTML. '
                                    'Entre em contato com o desensolvedor '
                                    'desse modulo.',
                    'developerMessage': 'No Continue button found on target '
                                        'URL http://www.nfe.fazenda.gov.br/'
                                        'portal/consulta.aspx?tipoConsulta'
                                        '=completa&tipoConteudo=XbSeqxE8pl8= '
                                        'when trying to search for element '
                                        'ctl00_ContentPlaceHolder1_'
                                        'btnConsultar.'
                }
            ]
        }

        mock_execute_script.side_effect = Exception()

        sut = Client(HTTP_AUTHORIZATION='Bearer ' + self.access_token.token)
        response = sut.get('/api/nfe/%s' % nfe_key, data={'captcha': '123456'})

        self.assertEquals(status.HTTP_502_BAD_GATEWAY, response.status_code)
        self.assertDictEqual(expected_error_message, response.data)