diff --git a/.travis.yml b/.travis.yml
index 9d469a9b4..d3ba4e10e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,45 +1,23 @@
language: python
-sudo: required
python:
- - "3.4.3"
+ - 3.4.3
+
services:
- postgresql
-addons:
- postgresql: "9.3"
-
install:
- - sudo apt-get install git nginx python3-dev libpq-dev graphviz-dev graphviz pkg-config python-psycopg2 nodejs npm
- - sudo ln -s /usr/bin/node
- pip install -r requirements/test-requirements.txt
- - pip install --upgrade setuptools
-
-# Line 24 to 35 is a hack found in this link below
-# It was used to fix an error in database building
-# https://dockyard.com/blog/ruby/2013/03/29/running-postgresql-9-2-on-travis-ci
before_script:
- - sudo /etc/init.d/postgresql stop
- - sudo cp /etc/postgresql/9.2/main/pg_hba.conf ./
- - sudo apt-get remove postgresql postgresql-9.2 -qq --purge
- - source /etc/lsb-release
- - echo "deb http://apt.postgresql.org/pub/repos/apt/ $DISTRIB_CODENAME-pgdg main" > pgdg.list
- - sudo mv pgdg.list /etc/apt/sources.list.d/
- - wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add -
- - sudo apt-get update
- - sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install postgresql-9.3 postgresql-contrib-9.3 -qq
- - sudo /etc/init.d/postgresql stop
- - sudo cp ./pg_hba.conf /etc/postgresql/9.3/main
- - sudo /etc/init.d/postgresql start
- npm install -g bower
- - cp .env_dev .env
- - sed -i -e 's/getpass.getuser()/"postgres"/g' sapl/settings.py
- - psql -c 'create database sapl;' -U postgres
+ - cp sapl/.env_test sapl/.env
+ - psql -c "CREATE USER sapl WITH PASSWORD 'sapl'" -U postgres;
+ - psql -c "CREATE DATABASE sapl OWNER sapl;" -U postgres
script:
- ./manage.py migrate
- ./manage.py bower install
- - pip freeze
- - ./test_and_check_qa.sh
\ No newline at end of file
+ - py.test
+ # - ./test_and_check_qa.sh
\ No newline at end of file
diff --git a/README.rst b/README.rst
index 9770c0015..67d1e84db 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,5 @@
-.. image:: https://badge.waffle.io/interlegis/sapl.png?label=ready&title=Ready
- :target: https://waffle.io/interlegis/sapl
- :alt: 'Stories in Ready'
+.. image:: https://travis-ci.org/interlegis/sapl.svg?branch=master
+ :target: https://travis-ci.org/interlegis/sapl
***********************************************
SAPL - Sistema de Apoio ao Processo Legislativo
@@ -246,18 +245,18 @@ Boas Práticas
* Em caso de Implementação de modelo que envolva a classe ``django.contrib.auth.models.User``, não a use diretamente, use para isso a função ``get_settings_auth_user_model()`` de ``sapl.utils``. Exemplo:
- - no lugar de ``owner = models.ForeignKey(User, ... )``
- - use ``owner = models.ForeignKey(get_settings_auth_user_model(), ... )``
+ - no lugar de ``owner = models.ForeignKey(User, ... )``
+ - use ``owner = models.ForeignKey(get_settings_auth_user_model(), ... )``
- Não use em qualquer modelagem futura, ``ForeignKey`` com ``User`` ou mesmo ``settings.AUTH_USER_MODEL`` sem o import correto que não é o do projeto e sim o que está em ``sapl.utils``, ou seja (``from django.conf import settings``)
- - em https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#referencing-the-user-model é explicado por que ser dessa forma!
+ - em https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#referencing-the-user-model é explicado por que ser dessa forma!
- Já em qualquer uso em implementação de execução, ao fazer uma query, por exemplo:
- não use ``django.contrib.auth.models.User`` para utilizar as caracteristicas do model, para isso, use esta função: django.contrib.auth.get_user_model()
- - Seguir esses passos simplificará qualquer customização futura que venha a ser feita na autenticação do usuários ao evitar correções de inúmeros import's e ainda, desta forma, torna a funcionalidade de autenticação reimplementável por qualquer outro projeto que venha usar partes ou o todo do SAPL.
+ - Seguir esses passos simplificará qualquer customização futura que venha a ser feita na autenticação do usuários ao evitar correções de inúmeros import's e ainda, desta forma, torna a funcionalidade de autenticação reimplementável por qualquer outro projeto que venha usar partes ou o todo do SAPL.
Atenção:
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 44ef147c0..9c8faaa2d 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -1,4 +1,5 @@
dj-database-url==0.4.1
+django==1.9.7
django-admin-bootstrapped==2.5.7
django-bootstrap3==7.0.1
django-bower==5.1.0
@@ -10,8 +11,7 @@ django-extra-views==0.8.0
django-filter==0.13.0
django-floppyforms==1.6.2
django-model-utils==2.5
-django-sass-processor==0.4.0
-django==1.9.7
+django-sass-processor==0.4.6
djangorestframework
easy-thumbnails==2.3
git+git://github.com/interlegis/trml2pdf.git
diff --git a/.env_dev b/sapl/.env_test
similarity index 100%
rename from .env_dev
rename to sapl/.env_test
diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py
index 4f8370eac..ed1da8633 100644
--- a/sapl/base/templatetags/common_tags.py
+++ b/sapl/base/templatetags/common_tags.py
@@ -38,11 +38,6 @@ def isinst(value, class_str):
return classe == class_str
-@register.filter
-def to_class_name(value):
- return value.__class__.__name__.lower()
-
-
@register.filter
def get_add_perm(value, arg):
perm = value
diff --git a/sapl/comissoes/tests/test_comissoes.py b/sapl/comissoes/tests/test_comissoes.py
index af5e71da7..fee303192 100644
--- a/sapl/comissoes/tests/test_comissoes.py
+++ b/sapl/comissoes/tests/test_comissoes.py
@@ -44,14 +44,14 @@ def make_filiacao():
@pytest.mark.django_db(transaction=False)
-def test_incluir_parlamentar_errors(client):
+def test_incluir_parlamentar_errors(admin_client):
comissao = make_comissao()
composicao = make_composicao(comissao)
- response = client.post(reverse('sapl.comissoes:participacao_create',
- kwargs={'pk': composicao.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.comissoes:participacao_create',
+ kwargs={'pk': composicao.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['parlamentar'] ==
['Este campo é obrigatório.'])
@@ -62,18 +62,18 @@ def test_incluir_parlamentar_errors(client):
@pytest.mark.django_db(transaction=False)
-def test_incluir_comissao_submit(client):
+def test_incluir_comissao_submit(admin_client):
tipo = mommy.make(TipoComissao,
sigla='T',
nome='Teste')
- response = client.post(reverse('sapl.comissoes:comissao_create'),
- {'tipo': tipo.pk,
- 'nome': 'Comissão Teste',
- 'sigla': 'CT',
- 'data_criacao': '2016-03-22',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.comissoes:comissao_create'),
+ {'tipo': tipo.pk,
+ 'nome': 'Comissão Teste',
+ 'sigla': 'CT',
+ 'data_criacao': '2016-03-22',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
comissao = Comissao.objects.first()
@@ -82,11 +82,11 @@ def test_incluir_comissao_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_incluir_comissao_errors(client):
+def test_incluir_comissao_errors(admin_client):
- response = client.post(reverse('sapl.comissoes:comissao_create'),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.comissoes:comissao_create'),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
diff --git a/sapl/crispy_layout_mixin.py b/sapl/crispy_layout_mixin.py
index c6c4437a6..40f6b01e4 100644
--- a/sapl/crispy_layout_mixin.py
+++ b/sapl/crispy_layout_mixin.py
@@ -1,12 +1,12 @@
from math import ceil
-import rtyaml
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit
from django import template
from django.utils import formats
from django.utils.translation import ugettext as _
+import rtyaml
def heads_and_tails(list_of_lists):
@@ -50,8 +50,9 @@ class SaplFormLayout(Layout):
def get_field_display(obj, fieldname):
field = obj._meta.get_field(fieldname)
- verbose_name = str(field.verbose_name)
- if field.choices:
+ verbose_name = str(field.verbose_name)\
+ if hasattr(field, 'verbose_name') else ''
+ if hasattr(field, 'choices') and field.choices:
value = getattr(obj, 'get_%s_display' % fieldname)()
else:
value = getattr(obj, fieldname)
@@ -74,6 +75,14 @@ def get_field_display(obj, fieldname):
value.name.split('/')[-1:][0])
else:
display = ''
+ elif 'ManyRelatedManager' in str(type(value))\
+ or 'RelatedManager' in str(type(value)):
+ display = '
'
+ for v in value.all():
+ display += '- %s
' % str(v)
+ display += '
'
+ if not verbose_name:
+ verbose_name = str(field.related_model._meta.verbose_name_plural)
else:
display = str(value)
return verbose_name, display
@@ -147,7 +156,9 @@ class CrispyLayoutFormMixin:
def read_yaml_from_file(yaml_layout):
# TODO cache this at application level
t = template.loader.get_template(yaml_layout)
- rendered = t.render()
+ # aqui é importante converter para str pois, dependendo do ambiente,
+ # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream
+ rendered = str(t.render())
return rtyaml.load(rendered)
diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py
index 1386e294a..ce530185b 100644
--- a/sapl/materia/tests/test_materia.py
+++ b/sapl/materia/tests/test_materia.py
@@ -80,7 +80,7 @@ def make_materia_principal():
@pytest.mark.django_db(transaction=False)
-def test_materia_anexada_submit(client):
+def test_materia_anexada_submit(admin_client):
materia_principal = make_materia_principal()
# Cria a matéria que será anexada
@@ -99,14 +99,14 @@ def test_materia_anexada_submit(client):
materia_anexada = MateriaLegislativa.objects.get(numero=32, ano=2004)
# Testa POST
- response = client.post(reverse('sapl.materia:anexada_create',
- kwargs={'pk': materia_principal.pk}),
- {'tipo': materia_anexada.tipo.pk,
- 'numero': materia_anexada.numero,
- 'ano': materia_anexada.ano,
- 'data_anexacao': '2016-03-18',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:anexada_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'tipo': materia_anexada.tipo.pk,
+ 'numero': materia_anexada.numero,
+ 'ano': materia_anexada.ano,
+ 'data_anexacao': '2016-03-18',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
# Verifica se a matéria foi anexada corretamente
@@ -116,7 +116,7 @@ def test_materia_anexada_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_autoria_submit(client):
+def test_autoria_submit(admin_client):
materia_principal = make_materia_principal()
# Cria um tipo de Autor
@@ -126,14 +126,14 @@ def test_autoria_submit(client):
autor = mommy.make(Autor, tipo=tipo_autor, nome='Autor Teste')
# Testa POST
- response = client.post(reverse('sapl.materia:autoria_create',
- kwargs={'pk': materia_principal.pk}),
- {'autor': autor.pk,
- 'primeiro_autor': True,
- 'materia_id': materia_principal.pk,
- 'partido': '',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:autoria_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'autor': autor.pk,
+ 'primeiro_autor': True,
+ 'materia_id': materia_principal.pk,
+ 'partido': '',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
# Verifica se o autor foi realmente criado
@@ -144,7 +144,7 @@ def test_autoria_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_despacho_inicial_submit(client):
+def test_despacho_inicial_submit(admin_client):
materia_principal = make_materia_principal()
# Cria uma comissão
@@ -156,11 +156,11 @@ def test_despacho_inicial_submit(client):
data_criacao='2016-03-18')
# Testa POST
- response = client.post(reverse('sapl.materia:despachoinicial_create',
- kwargs={'pk': materia_principal.pk}),
- {'comissao': comissao.pk,
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:despachoinicial_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'comissao': comissao.pk,
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
# Verifica se o despacho foi criado
@@ -170,19 +170,19 @@ def test_despacho_inicial_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_numeracao_submit(client):
+def test_numeracao_submit(admin_client):
materia_principal = make_materia_principal()
materia = make_materia_principal()
# Testa POST
- response = client.post(reverse('sapl.materia:numeracao_create',
- kwargs={'pk': materia_principal.pk}),
- {'tipo_materia': materia.tipo.pk,
- 'numero_materia': materia.numero,
- 'ano_materia': materia.ano,
- 'data_materia': '2016-03-21',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:numeracao_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'tipo_materia': materia.tipo.pk,
+ 'numero_materia': materia.numero,
+ 'ano_materia': materia.ano,
+ 'data_materia': '2016-03-21',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
@@ -193,7 +193,7 @@ def test_numeracao_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_documento_acessorio_submit(client):
+def test_documento_acessorio_submit(admin_client):
materia_principal = make_materia_principal()
# Cria um tipo de Autor
@@ -207,15 +207,16 @@ def test_documento_acessorio_submit(client):
descricao='Teste')
# Testa POST
- response = client.post(reverse('sapl.materia:documentoacessorio_create',
- kwargs={'pk': materia_principal.pk}),
- {'tipo': tipo.pk,
- 'nome': 'teste_nome',
- 'data_materia': '2016-03-21',
- 'autor': autor,
- 'ementa': 'teste_ementa',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse(
+ 'sapl.materia:documentoacessorio_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'tipo': tipo.pk,
+ 'nome': 'teste_nome',
+ 'data_materia': '2016-03-21',
+ 'autor': autor,
+ 'ementa': 'teste_ementa',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
@@ -227,19 +228,20 @@ def test_documento_acessorio_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_legislacao_citada_submit(client):
+def test_legislacao_citada_submit(admin_client):
materia_principal = make_materia_principal()
norma = make_norma()
# Testa POST
- response = client.post(reverse('sapl.materia:legislacaocitada_create',
- kwargs={'pk': materia_principal.pk}),
- {'tipo': norma.tipo.pk,
- 'numero': norma.numero,
- 'ano': norma.ano,
- 'disposicao': 'disposicao',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.materia:legislacaocitada_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'tipo': norma.tipo.pk,
+ 'numero': norma.numero,
+ 'ano': norma.ano,
+ 'disposicao': 'disposicao',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
@@ -249,7 +251,7 @@ def test_legislacao_citada_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_tramitacao_submit(client):
+def test_tramitacao_submit(admin_client):
materia_principal = make_materia_principal()
# Cria status para tramitação
status_tramitacao = mommy.make(StatusTramitacao,
@@ -257,7 +259,7 @@ def test_tramitacao_submit(client):
sigla='ST',
descricao='Status_Teste')
# Testa POST
- response = client.post(
+ response = admin_client.post(
reverse('sapl.materia:tramitacao_create',
kwargs={'pk': materia_principal.pk}),
{'unidade_tramitacao_local': make_unidade_tramitacao(
@@ -283,12 +285,12 @@ def test_tramitacao_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_anexada(client):
+def test_form_errors_anexada(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:anexada_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:anexada_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
@@ -301,42 +303,43 @@ def test_form_errors_anexada(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_autoria(client):
+def test_form_errors_autoria(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:autoria_create',
- kwargs={'pk': materia_principal.pk}),
- {'materia_id': materia_principal.pk,
- 'partido': '',
- 'autor': '',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:autoria_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'materia_id': materia_principal.pk,
+ 'partido': '',
+ 'autor': '',
+ 'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['autor'] ==
['Este campo é obrigatório.'])
@pytest.mark.django_db(transaction=False)
-def test_form_errors_despacho_inicial(client):
+def test_form_errors_despacho_inicial(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:despachoinicial_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:despachoinicial_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['comissao'] ==
['Este campo é obrigatório.'])
@pytest.mark.django_db(transaction=False)
-def test_form_errors_documento_acessorio(client):
+def test_form_errors_documento_acessorio(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:documentoacessorio_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.materia:documentoacessorio_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
@@ -345,13 +348,14 @@ def test_form_errors_documento_acessorio(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_legislacao_citada(client):
+def test_form_errors_legislacao_citada(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:legislacaocitada_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.materia:legislacaocitada_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
@@ -362,13 +366,13 @@ def test_form_errors_legislacao_citada(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_numeracao(client):
+def test_form_errors_numeracao(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:numeracao_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:numeracao_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo_materia'] ==
['Este campo é obrigatório.'])
@@ -381,13 +385,14 @@ def test_form_errors_numeracao(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_tramitacao(client):
+def test_form_errors_tramitacao(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:tramitacao_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.materia:tramitacao_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['data_tramitacao'] ==
['Este campo é obrigatório.'])
@@ -402,13 +407,14 @@ def test_form_errors_tramitacao(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_relatoria(client):
+def test_form_errors_relatoria(admin_client):
materia_principal = make_materia_principal()
- response = client.post(reverse('sapl.materia:relatoria_create',
- kwargs={'pk': materia_principal.pk}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.materia:relatoria_create',
+ kwargs={'pk': materia_principal.pk}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['data_designacao_relator'] ==
['Este campo é obrigatório.'])
@@ -417,12 +423,12 @@ def test_form_errors_relatoria(client):
@pytest.mark.django_db(transaction=False)
-def test_proposicao_submit(client):
- response = client.post(reverse('sapl.materia:proposicao_create'),
- {'tipo': mommy.make(TipoProposicao, pk=3).pk,
- 'descricao': 'Teste proposição',
- 'salvar': 'salvar'},
- follow=True)
+def test_proposicao_submit(admin_client):
+ response = admin_client.post(reverse('sapl.materia:proposicao_create'),
+ {'tipo': mommy.make(TipoProposicao, pk=3).pk,
+ 'descricao': 'Teste proposição',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
@@ -432,11 +438,11 @@ def test_proposicao_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_proposicao(client):
+def test_form_errors_proposicao(admin_client):
- response = client.post(reverse('sapl.materia:proposicao_create'),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.materia:proposicao_create'),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
assert (response.context_data['form'].errors['descricao'] ==
diff --git a/sapl/norma/tests/test_norma.py b/sapl/norma/tests/test_norma.py
index 16c980d15..65c0f28b1 100644
--- a/sapl/norma/tests/test_norma.py
+++ b/sapl/norma/tests/test_norma.py
@@ -6,22 +6,22 @@ from sapl.norma.models import NormaJuridica, TipoNormaJuridica
@pytest.mark.django_db(transaction=False)
-def test_incluir_norma_submit(client):
+def test_incluir_norma_submit(admin_client):
# Cria um tipo de norma
tipo = mommy.make(TipoNormaJuridica,
sigla='T',
descricao='Teste')
# Testa POST
- response = client.post(reverse('sapl.norma:normajuridica_create'),
- {'tipo': tipo.pk,
- 'numero': '1',
- 'ano': '2016',
- 'data': '2016-03-22',
- 'esfera_federacao': 'E',
- 'ementa': 'Teste_Ementa',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.norma:normajuridica_create'),
+ {'tipo': tipo.pk,
+ 'numero': '1',
+ 'ano': '2016',
+ 'data': '2016-03-22',
+ 'esfera_federacao': 'E',
+ 'ementa': 'Teste_Ementa',
+ 'salvar': 'salvar'},
+ follow=True)
assert response.status_code == 200
norma = NormaJuridica.objects.first()
@@ -31,11 +31,11 @@ def test_incluir_norma_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_incluir_norma_errors(client):
+def test_incluir_norma_errors(admin_client):
- response = client.post(reverse('sapl.norma:normajuridica_create'),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.norma:normajuridica_create'),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['tipo'] ==
['Este campo é obrigatório.'])
diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py
index 2739dcd62..16b0fb158 100644
--- a/sapl/parlamentares/tests/test_parlamentares.py
+++ b/sapl/parlamentares/tests/test_parlamentares.py
@@ -8,20 +8,20 @@ from sapl.parlamentares.models import (Dependente, Filiacao, Legislatura,
@pytest.mark.django_db(transaction=False)
-def test_cadastro_parlamentar(client):
+def test_cadastro_parlamentar(admin_client):
legislatura = mommy.make(Legislatura)
url = reverse('sapl.parlamentares:parlamentar_create')
- response = client.get(url)
+ response = admin_client.get(url)
assert response.status_code == 200
- response = client.post(url, {'nome_completo': 'Teresa Barbosa',
- 'nome_parlamentar': 'Terezinha',
- 'sexo': 'F',
- 'ativo': 'True',
- 'legislatura': legislatura.id,
- 'data_expedicao_diploma': '2001-01-01'},
- follow=True)
+ response = admin_client.post(url, {'nome_completo': 'Teresa Barbosa',
+ 'nome_parlamentar': 'Terezinha',
+ 'sexo': 'F',
+ 'ativo': 'True',
+ 'legislatura': legislatura.id,
+ 'data_expedicao_diploma': '2001-01-01'},
+ follow=True)
[parlamentar] = Parlamentar.objects.all()
assert parlamentar.nome_parlamentar == 'Terezinha'
@@ -36,9 +36,9 @@ def test_cadastro_parlamentar(client):
@pytest.mark.django_db(transaction=False)
-def test_incluir_parlamentar_errors(client):
+def test_incluir_parlamentar_errors(admin_client):
url = reverse('sapl.parlamentares:parlamentar_create')
- response = client.post(url)
+ response = admin_client.post(url)
erros_esperados = {campo: ['Este campo é obrigatório.']
for campo in ['legislatura',
'data_expedicao_diploma',
@@ -50,34 +50,34 @@ def test_incluir_parlamentar_errors(client):
@pytest.mark.django_db(transaction=False)
-def test_filiacao_submit(client):
+def test_filiacao_submit(admin_client):
mommy.make(Parlamentar, pk=14)
mommy.make(Partido, pk=32)
- client.post(reverse('sapl.parlamentares:filiacao_create',
- kwargs={'pk': 14}),
- {'partido': 32,
- 'data': '2016-03-22',
- 'salvar': 'salvar'},
- follow=True)
+ admin_client.post(reverse('sapl.parlamentares:filiacao_create',
+ kwargs={'pk': 14}),
+ {'partido': 32,
+ 'data': '2016-03-22',
+ 'salvar': 'salvar'},
+ follow=True)
filiacao = Filiacao.objects.first()
assert 32 == filiacao.partido.pk
@pytest.mark.django_db(transaction=False)
-def test_dependente_submit(client):
+def test_dependente_submit(admin_client):
mommy.make(Parlamentar, pk=14)
mommy.make(Partido, pk=32)
mommy.make(TipoDependente, pk=3)
- client.post(reverse('sapl.parlamentares:dependente_create',
- kwargs={'pk': 14}),
- {'nome': 'Eduardo',
- 'tipo': 3,
- 'sexo': 'M',
- 'salvar': 'salvar'},
- follow=True)
+ admin_client.post(reverse('sapl.parlamentares:dependente_create',
+ kwargs={'pk': 14}),
+ {'nome': 'Eduardo',
+ 'tipo': 3,
+ 'sexo': 'M',
+ 'salvar': 'salvar'},
+ follow=True)
dependente = Dependente.objects.first()
assert 3 == dependente.tipo.pk
@@ -85,12 +85,13 @@ def test_dependente_submit(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_dependente(client):
+def test_form_errors_dependente(admin_client):
mommy.make(Parlamentar, pk=14)
- response = client.post(reverse('sapl.parlamentares:dependente_create',
- kwargs={'pk': 14}),
- {'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(
+ reverse('sapl.parlamentares:dependente_create',
+ kwargs={'pk': 14}),
+ {'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['nome'] ==
['Este campo é obrigatório.'])
@@ -101,14 +102,14 @@ def test_form_errors_dependente(client):
@pytest.mark.django_db(transaction=False)
-def test_form_errors_filiacao(client):
+def test_form_errors_filiacao(admin_client):
mommy.make(Parlamentar, pk=14)
- response = client.post(reverse('sapl.parlamentares:filiacao_create',
- kwargs={'pk': 14}),
- {'partido': '',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.parlamentares:filiacao_create',
+ kwargs={'pk': 14}),
+ {'partido': '',
+ 'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['partido'] ==
['Este campo é obrigatório.'])
@@ -117,31 +118,31 @@ def test_form_errors_filiacao(client):
@pytest.mark.django_db(transaction=False)
-def test_mandato_submit(client):
+def test_mandato_submit(admin_client):
mommy.make(Parlamentar, pk=14)
mommy.make(Legislatura, pk=5)
- client.post(reverse('sapl.parlamentares:mandato_create',
- kwargs={'pk': 14}),
- {'legislatura': 5,
- 'data_fim_mandato': '2016-01-01',
- 'data_expedicao_diploma': '2016-03-22',
- 'observacao': 'Observação do mandato',
- 'salvar': 'salvar'},
- follow=True)
+ admin_client.post(reverse('sapl.parlamentares:mandato_create',
+ kwargs={'pk': 14}),
+ {'legislatura': 5,
+ 'data_fim_mandato': '2016-01-01',
+ 'data_expedicao_diploma': '2016-03-22',
+ 'observacao': 'Observação do mandato',
+ 'salvar': 'salvar'},
+ follow=True)
mandato = Mandato.objects.first()
assert 'Observação do mandato' == mandato.observacao
@pytest.mark.django_db(transaction=False)
-def test_form_errors_mandato(client):
+def test_form_errors_mandato(admin_client):
mommy.make(Parlamentar, pk=14)
- response = client.post(reverse('sapl.parlamentares:mandato_create',
- kwargs={'pk': 14}),
- {'legislatura': '',
- 'salvar': 'salvar'},
- follow=True)
+ response = admin_client.post(reverse('sapl.parlamentares:mandato_create',
+ kwargs={'pk': 14}),
+ {'legislatura': '',
+ 'salvar': 'salvar'},
+ follow=True)
assert (response.context_data['form'].errors['legislatura'] ==
['Este campo é obrigatório.'])
diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py
index 40dccb2dc..b4d39942e 100644
--- a/sapl/protocoloadm/tests/test_protocoloadm.py
+++ b/sapl/protocoloadm/tests/test_protocoloadm.py
@@ -8,22 +8,22 @@ from sapl.protocoloadm.models import Protocolo
@pytest.mark.django_db(transaction=False)
-def test_anular_protocolo_acessivel(client):
- response = client.get(reverse('sapl.protocoloadm:anular_protocolo'))
+def test_anular_protocolo_acessivel(admin_client):
+ response = admin_client.get(reverse('sapl.protocoloadm:anular_protocolo'))
assert response.status_code == 200
@pytest.mark.django_db(transaction=False)
-def test_anular_protocolo_submit(client):
+def test_anular_protocolo_submit(admin_client):
mommy.make(Protocolo, numero='76', ano='2016', anulado=False)
# TODO: setar usuario e IP
- response = client.post(reverse('sapl.protocoloadm:anular_protocolo'),
- {'numero': '76',
- 'ano': '2016',
- 'justificativa_anulacao': 'TESTE',
- 'salvar': 'Anular'},
- follow=True)
+ response = admin_client.post(reverse('sapl.protocoloadm:anular_protocolo'),
+ {'numero': '76',
+ 'ano': '2016',
+ 'justificativa_anulacao': 'TESTE',
+ 'salvar': 'Anular'},
+ follow=True)
assert response.status_code == 200
diff --git a/sapl/settings.py b/sapl/settings.py
index 96dee01eb..fb7fc4bb9 100644
--- a/sapl/settings.py
+++ b/sapl/settings.py
@@ -38,6 +38,7 @@ LOGIN_URL = '/login/?next='
# SAPL business apps in dependency order
SAPL_APPS = (
'sapl.base',
+ 'sapl.crud',
'sapl.parlamentares',
'sapl.comissoes',
'sapl.materia',
diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss
index e4163a499..901f7286c 100644
--- a/sapl/static/styles/app.scss
+++ b/sapl/static/styles/app.scss
@@ -131,13 +131,11 @@ body {
}
}
-
fieldset {
-
fieldset {
font-size: 95%;
legend {
font-size: 18px;
}
}
-}
\ No newline at end of file
+}
diff --git a/sapl/utils.py b/sapl/utils.py
index 088319563..5b1bee282 100644
--- a/sapl/utils.py
+++ b/sapl/utils.py
@@ -261,7 +261,7 @@ def permissoes_parlamentares():
def permissoes_protocoloadm():
lista_permissoes = []
perms_protocolo = Permission.objects.filter(
- group__name='Operador de Protocolo')
+ group__name='Operador de Protocolo Administrativo')
for p in perms_protocolo:
lista_permissoes.append('protocoloadm.' + p.codename)
return set(lista_permissoes)
@@ -270,7 +270,7 @@ def permissoes_protocoloadm():
def permissoes_adm():
lista_permissoes = []
perms_adm = Permission.objects.filter(
- group__name='Operador de Administração')
+ group__name='Operador Administrativo')
for p in perms_adm:
lista_permissoes.append('protocoloadm.' + p.codename)
return set(lista_permissoes)
@@ -279,7 +279,7 @@ def permissoes_adm():
def permissoes_sessao():
lista_permissoes = []
perms_sessao = list(Permission.objects.filter(
- group__name='Operador de Sessão'))
+ group__name='Operador de Sessão Plenária'))
for p in perms_sessao:
lista_permissoes.append('sessao.' + p.codename)
return set(lista_permissoes)
@@ -288,7 +288,7 @@ def permissoes_sessao():
def permissoes_painel():
lista_permissoes = []
perms_painel = list(Permission.objects.filter(
- group__name='Operador de Painel'))
+ group__name='Operador de Painel Eletrônico'))
for p in perms_painel:
lista_permissoes.append('painel.' + p.codename)
return set(lista_permissoes)
diff --git a/scripts/inicializa_grupos_autorizacoes.py b/scripts/inicializa_grupos_autorizacoes.py
index 21d43808f..65f27f880 100644
--- a/scripts/inicializa_grupos_autorizacoes.py
+++ b/scripts/inicializa_grupos_autorizacoes.py
@@ -1,188 +1,114 @@
+from django.apps import apps
from django.contrib.auth.models import Group, Permission, User
from django.contrib.contenttypes.models import ContentType
-def cria_grupos_permissoes():
-
- if not Group.objects.filter("Teste"):
- pass
-
- # Cria todos os grupos necessários para a aplicação
-
- op_geral = Group.objects.get_or_create(name="Operador Geral")
- op_prot = Group.objects.get_or_create(name="Operador de Protocolo")
- op_sessao = Group.objects.get_or_create(name="Operador de Sessão")
- op_comissao = Group.objects.get_or_create(name="Operador de Comissão")
- op_adm = Group.objects.get_or_create(name="Operador de Administração")
- op_norma = Group.objects.get_or_create(name="Operador de Norma Jurídica")
- op_materia = Group.objects.get_or_create(
- name="Operador de Matéria Legislativa")
- op_painel = Group.objects.get_or_create(name="Operador de Painel")
- op_autor = Group.objects.get_or_create(name="Autor")
-
- op_geral = op_geral[0]
- op_prot = op_prot[0]
- op_sessao = op_sessao[0]
- op_comissao = op_comissao[0]
- op_adm = op_adm[0]
- op_norma = op_norma[0]
- op_materia = op_materia[0]
- op_painel = op_painel[0]
- op_autor = op_autor[0]
-
- # Base
-
- permissao_add_cl = Permission.objects.get(
- name="Can add Casa Legislativa")
- permissao_edit_cl = Permission.objects.get(
- name="Can change Casa Legislativa")
- permissao_remove_cl = Permission.objects.get(
- name="Can delete Casa Legislativa")
-
- permissoes_base = [permissao_add_cl,
- permissao_edit_cl,
- permissao_remove_cl]
+def cria_ou_reseta_grupo(nome):
+ grupo = Group.objects.get_or_create(name=nome)[0]
+ for p in list(grupo.permissions.all()):
+ grupo.permissions.remove(p)
+ return grupo
- # Comissao
- cts = ContentType.objects.filter(app_label='comissoes')
- perms_comissoes = list(Permission.objects.filter(content_type__in=cts))
+def cria_usuario(nome, grupo):
+ nome_usuario = nome
+ usuario = User.objects.get_or_create(username=nome_usuario)[0]
+ usuario.set_password('interlegis')
+ usuario.save()
+ grupo.user_set.add(usuario)
- # Materia
- cts = ContentType.objects.filter(app_label='materia')
- perms_materia = list(Permission.objects.filter(content_type__in=cts))
-
- # Norma
-
- cts = ContentType.objects.filter(app_label='norma')
- perms_norma = list(Permission.objects.filter(content_type__in=cts))
-
- # Painel
-
- cts = ContentType.objects.filter(app_label='painel')
- perms_painel = list(Permission.objects.filter(content_type__in=cts))
-
- # Parlamentares
+def cria_grupos_permissoes():
- cts = ContentType.objects.filter(app_label='parlamentares')
- perms_parlamentares = list(Permission.objects.filter(content_type__in=cts))
+ nomes_apps = ['base', 'parlamentares', 'comissoes',
+ 'materia', 'norma', 'sessao', 'painel']
- # ProtocoloADM e DOCADM
+ permissoes = {app: list(Permission.objects.filter(
+ content_type__in=ContentType.objects.filter(app_label=app)))
+ for app in nomes_apps}
+ # permissoes específicas para protocolo e documento administrativo
cts = ContentType.objects.filter(app_label='protocoloadm')
- perms_docadm = list(Permission.objects.filter(content_type__in=cts))
-
- cts_exc1 = cts.filter(model__icontains='tramitacao')
- cts_exc2 = cts.filter(model__icontains='documentoadministrativo')
-
- cts = cts.exclude(id__in=[o.id for o in cts_exc1])
- cts = cts.exclude(id__in=[o.id for o in cts_exc2])
-
- perms_protocoloadm = list(Permission.objects.filter(content_type__in=cts))
-
- # Sessao
-
- cts = ContentType.objects.filter(app_label='sessao')
- perms_sessao = list(Permission.objects.filter(content_type__in=cts))
-
- # Painel
-
- cts = ContentType.objects.filter(app_label='painel')
- perms_painel = list(Permission.objects.filter(content_type__in=cts))
+ # documento administrativo
+ permissoes['documento_administrativo'] = list(
+ Permission.objects.filter(content_type__in=cts))
+ nome_grupo = 'Operador Administrativo'
+ grupo = cria_ou_reseta_grupo(nome_grupo)
+ for p in permissoes['documento_administrativo']:
+ grupo.permissions.add(p)
+
+ nome_usuario = 'operador_administrativo'
+ cria_usuario(nome_usuario, grupo)
+
+ # prolocolo administrativo
+ cts = cts.exclude(model__icontains='tramitacao').exclude(
+ model__icontains='documentoadministrativo')
+ permissoes['protocoloadm'] = list(
+ Permission.objects.filter(content_type__in=cts))
+ nome_grupo = 'Operador de Protocolo Administrativo'
+ grupo = cria_ou_reseta_grupo(nome_grupo)
+ for p in permissoes['protocoloadm']:
+ grupo.permissions.add(p)
+
+ nome_usuario = 'operador_protocoloadm'
+ cria_usuario(nome_usuario, grupo)
+
+ # permissoes do base
+ cts = ContentType.objects.filter(app_label='base')
+ permissoes['base'] = list(
+ Permission.objects.filter(content_type__in=cts))
+
+ for nome_app in nomes_apps:
+
+ if nome_app not in {'base', 'parlamentares'}:
+ # Elimina casos especificos
+
+ # Cria Grupo
+ nome_grupo = 'Operador de %s' % apps.get_app_config(
+ nome_app).verbose_name
+ grupo = cria_ou_reseta_grupo(nome_grupo)
+
+ # Elimina o acesso a proposicoes pelo Operador de Matérias
+ if nome_app == 'materia':
+ cts = ContentType.objects.filter(
+ app_label='materia').exclude(model='proposicao')
+ permissoes['materia'] = list(
+ Permission.objects.filter(content_type__in=cts))
+
+ # Configura as permissoes
+ for p in permissoes[nome_app]:
+ grupo.permissions.add(p)
+
+ # Cria o Usuario
+ nome_usuario = 'operador_%s' % nome_app
+ usuario = User.objects.get_or_create(username=nome_usuario)[0]
+ usuario.set_password('interlegis')
+ usuario.save()
+ grupo.user_set.add(usuario)
+
+ # Operador Geral
+ grupo_geral = cria_ou_reseta_grupo('Operador Geral')
+ for lista in permissoes.values():
+ for p in lista:
+ grupo_geral.permissions.add(p)
+
+ nome_usuario = 'operador_geral'
+ cria_usuario(nome_usuario, grupo_geral)
# Autor
-
- perms_autor = Permission.objects.get(name="Can add Proposição")
-
- # Configura Permissoes Operador de Protocolo
- for p in perms_protocoloadm:
- op_prot.permissions.add(p)
-
- # Configura Permissoes Operador de Sessao
- for p in perms_sessao:
- op_sessao.permissions.add(p)
-
- # Configura Permissoes Operador de Comissao
- for p in perms_comissoes:
- op_comissao.permissions.add(p)
-
- # Configura Permissoes Operador de Administracao
- for p in perms_docadm:
- op_adm.permissions.add(p)
-
- # Configura Permissoes Operador de Norma
- for p in perms_norma:
- op_norma.permissions.add(p)
-
- # Configura Permissoes Operador de Materia
- for p in perms_materia:
- op_materia.permissions.add(p)
-
- # Configura Permissoes Operador de Painel
- for p in perms_painel:
- op_painel.permissions.add(p)
+ perms_autor = []
+ perms_autor.append(Permission.objects.get(name='Can add Proposição'))
+ perms_autor.append(Permission.objects.get(name='Can change Proposição'))
+ perms_autor.append(Permission.objects.get(name='Can delete Proposição'))
# Configura Permissoes Autor
- op_autor.permissions.add(perms_autor)
-
- # Configura Permissoes Operador Geral
- perms_op_geral = perms_protocoloadm + perms_sessao + perms_comissoes
- perms_op_geral = perms_op_geral + perms_docadm + perms_norma
- perms_op_geral = perms_op_geral + perms_materia
- perms_op_geral = perms_op_geral + perms_parlamentares + perms_painel
- perms_op_geral = perms_op_geral + permissoes_base
-
- for p in perms_op_geral:
- op_geral.permissions.add(p)
- op_geral.permissions.add(perms_autor)
-
- # Cria usuarios
- op_geral_user = User.objects.get_or_create(username='op_geral')[0]
- op_geral_user.set_password('interlegis')
- op_geral_user.save()
- op_geral.user_set.add(op_geral_user)
-
- op_materia_user = User.objects.get_or_create(username='op_materia')[0]
- op_materia_user.set_password('interlegis')
- op_materia_user.save()
- op_materia.user_set.add(op_materia_user)
-
- op_prot_user = User.objects.get_or_create(username='op_protocolo')[0]
- op_prot_user.set_password('interlegis')
- op_prot_user.save()
- op_prot.user_set.add(op_prot_user)
-
- op_sessao_user = User.objects.get_or_create(username='op_sessao')[0]
- op_sessao_user.set_password('interlegis')
- op_sessao_user.save()
- op_sessao.user_set.add(op_sessao_user)
-
- op_comissao_user = User.objects.get_or_create(username='op_comissao')[0]
- op_comissao_user.set_password('interlegis')
- op_comissao_user.save()
- op_comissao.user_set.add(op_comissao_user)
-
- op_adm_user = User.objects.get_or_create(username='op_adm')[0]
- op_adm_user.set_password('interlegis')
- op_adm_user.save()
- op_adm.user_set.add(op_adm_user)
-
- op_norma_user = User.objects.get_or_create(username='op_norma')[0]
- op_norma_user.set_password('interlegis')
- op_norma_user.save()
- op_norma.user_set.add(op_norma_user)
-
- op_painel_user = User.objects.get_or_create(username='op_painel')[0]
- op_painel_user.set_password('interlegis')
- op_painel_user.save()
- op_painel.user_set.add(op_norma_user)
-
- op_autor_user = User.objects.get_or_create(username='op_autor')[0]
- op_autor_user.set_password('interlegis')
- op_autor_user.save()
- op_autor.user_set.add(op_autor_user)
+ grupo = cria_ou_reseta_grupo('Autor')
+ for p in perms_autor:
+ grupo.permissions.add(p)
+
+ nome_usuario = 'operador_autor'
+ cria_usuario(nome_usuario, grupo_geral)
if __name__ == '__main__':
cria_grupos_permissoes()
diff --git a/scripts/test_inicializa_grupos_autorizacoes.py b/scripts/test_inicializa_grupos_autorizacoes.py
new file mode 100644
index 000000000..a8e9064a0
--- /dev/null
+++ b/scripts/test_inicializa_grupos_autorizacoes.py
@@ -0,0 +1,47 @@
+import pytest
+from django.apps import apps
+from django.contrib.auth.models import Group, Permission
+from django.contrib.contenttypes.models import ContentType
+
+from inicializa_grupos_autorizacoes import cria_grupos_permissoes
+
+pytestmark = pytest.mark.django_db
+
+apps_com_permissao_padrao = [
+ 'comissoes', 'norma', 'sessao', 'painel']
+
+
+@pytest.mark.parametrize('app_label', apps_com_permissao_padrao)
+def test_grupo_padrao_tem_permissoes_sobre_todo_o_app(app_label):
+
+ app = apps.get_app_config(app_label)
+
+ # código testado
+ cria_grupos_permissoes()
+
+ def gerar_permissoes(app):
+ for model in app.get_models():
+ for op in ['add', 'change', 'delete']:
+ yield model, 'Can %s %s' % (op, model._meta.verbose_name)
+ grupo = Group.objects.get(name='Operador de %s' % app.verbose_name)
+ esperado = set(gerar_permissoes(app))
+
+ real = set((p.content_type.model_class(), p.name)
+ for p in grupo.permissions.all())
+ assert real == esperado
+
+
+@pytest.mark.parametrize('app_label', apps_com_permissao_padrao)
+def test_permissoes_extras_sao_apagadas(app_label):
+
+ app = apps.get_app_config(app_label)
+ grupo = Group.objects.create(name='Operador de %s' % app.verbose_name)
+
+ permissao_errada = Permission.objects.create(
+ name='STUB', content_type=ContentType.objects.first())
+ grupo.permissions.add(permissao_errada)
+
+ # código testado
+ cria_grupos_permissoes()
+
+ assert not grupo.permissions.filter(id=permissao_errada.id).exists()