Projet

Général

Profil

0001-wcs-add-categories-field-to-CareForms-cell-53213.patch

Lauréline Guérin, 27 avril 2021 15:11

Télécharger (13,4 ko)

Voir les différences:

Subject: [PATCH 1/2] wcs: add categories field to CareForms cell (#53213)

 combo/apps/wcs/forms.py                       |  12 ++
 .../migrations/0027_careforms_categories.py   |  17 +++
 combo/apps/wcs/models.py                      |  57 +++++++++-
 .../wcs/templates/combo/wcs/care_forms.html   |   2 +-
 tests/test_wcs.py                             | 103 +++++++++++++++++-
 5 files changed, 179 insertions(+), 12 deletions(-)
 create mode 100644 combo/apps/wcs/migrations/0027_careforms_categories.py
combo/apps/wcs/forms.py
23 23
from .models import (
24 24
    WcsCardInfosCell,
25 25
    WcsCardsCell,
26
    WcsCareFormsCell,
26 27
    WcsCategoryCell,
27 28
    WcsCurrentDraftsCell,
28 29
    WcsCurrentFormsCell,
......
153 154
        self._init_categories()
154 155

  
155 156

  
157
class WcsCareFormsCellForm(WcsFormsMixin, forms.ModelForm):
158
    class Meta:
159
        model = WcsCareFormsCell
160
        fields = ['wcs_site', 'categories']
161

  
162
    def __init__(self, *args, **kwargs):
163
        super().__init__(*args, **kwargs)
164
        self._init_wcs_site()
165
        self._init_categories()
166

  
167

  
156 168
class BackofficeSubmissionCellForm(WcsFormsMixin, forms.ModelForm):
157 169
    class Meta:
158 170
        model = WcsCurrentDraftsCell
combo/apps/wcs/migrations/0027_careforms_categories.py
1
import jsonfield.fields
2
from django.db import migrations
3

  
4

  
5
class Migration(migrations.Migration):
6

  
7
    dependencies = [
8
        ('wcs', '0026_text_to_jsonb'),
9
    ]
10

  
11
    operations = [
12
        migrations.AddField(
13
            model_name='wcscareformscell',
14
            name='categories',
15
            field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Categories'),
16
        ),
17
    ]
combo/apps/wcs/models.py
16 16
# You should have received a copy of the GNU Affero General Public License
17 17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 18

  
19
import collections
19 20
import copy
20 21
import logging
21 22

  
......
279 280
    def get_api_url(self, context):
280 281
        return self.api_url
281 282

  
283
    def get_api_url_for_site(self, context, wcs_slug):
284
        return self.get_api_url(context)
285

  
282 286
    def get_data(self, context):
283 287
        if context.get('placeholder_search_mode'):
284 288
            # don't call webservices when we're just looking for placeholders
......
292 296
        else:
293 297
            wcs_sites = get_wcs_services()
294 298

  
295
        wcs_sites = copy.deepcopy(wcs_sites)
299
        result = {}
296 300
        returns = set([])
297
        api_url = self.get_api_url(context)
298
        for wcs_slug, wcs_site in wcs_sites.items():
299
            url = wcs_site.get('url')
301
        for wcs_slug, _wcs_site in wcs_sites.items():
302
            api_url = self.get_api_url_for_site(context, wcs_slug)
303
            if not api_url:
304
                # nothing to call for this site
305
                continue
306
            url = _wcs_site.get('url')
300 307
            if not url.endswith('/'):
301 308
                url += '/'
309
            wcs_site = copy.deepcopy(_wcs_site)
310
            result[wcs_slug] = wcs_site
302 311
            wcs_site['base_url'] = url
303 312
            wcs_site['slug'] = wcs_slug
304 313

  
......
335 344
        else:
336 345
            self.mark_as_valid()
337 346

  
338
        return wcs_sites
347
        return result
339 348

  
340 349
    def get_cell_extra_context(self, context):
341 350
        return {self.variable_name: self.get_data(context)}
......
693 702

  
694 703

  
695 704
@register_cell_class
696
class WcsCareFormsCell(WcsDataBaseCell):
705
class WcsCareFormsCell(WcsDataBaseCell, CategoriesValidityMixin):
706
    categories = JSONField(_('Categories'), blank=True)
707

  
697 708
    api_url = '/api/forms/?limit=10'
698 709
    variable_name = 'care_forms'
699 710
    template_name = 'combo/wcs/care_forms.html'
......
703 714
    class Meta:
704 715
        verbose_name = _('Forms to process')
705 716

  
717
    def get_default_form_class(self):
718
        from .forms import WcsCareFormsCellForm
719

  
720
        return WcsCareFormsCellForm
721

  
722
    def get_api_url_for_site(self, context, wcs_slug):
723
        url = self.get_api_url(context)
724

  
725
        if self.categories and self.categories.get('data') or []:
726
            categories_by_site = collections.defaultdict(list)
727
            for category in self.categories['data']:
728
                key, slug = category.split(':')
729
                categories_by_site[key].append(slug)
730
            if not categories_by_site.get(wcs_slug):
731
                return None
732
            url += '&category_slugs=%s' % ','.join(categories_by_site.get(wcs_slug))
733

  
734
        return url
735

  
736
    def get_cell_extra_context(self, context):
737
        context = super().get_cell_extra_context(context)
738

  
739
        categories_filter = []
740
        if self.categories:
741
            for category in self.categories.get('data', []):
742
                categories_filter.append(tuple(category.split(':')))
743

  
744
        for wcs_site in context['care_forms']:
745
            if not context['care_forms'].get(wcs_site):
746
                continue
747
            context['care_forms'][wcs_site]['categories'] = [v for k, v in categories_filter if k == wcs_site]
748

  
749
        return context
750

  
706 751

  
707 752
@register_cell_class
708 753
class CategoriesCell(WcsDataBaseCell):
combo/apps/wcs/templates/combo/wcs/care_forms.html
26 26
    </tbody>
27 27
  </table>
28 28
  {% endif %}
29
  <p><a class="pk-button" href="{{ forms.url }}backoffice/management/">{% trans "See all forms" %}</a></p>
29
  <p><a class="pk-button" href="{{ forms.url }}backoffice/management/listing{% if forms.categories %}?category_slugs={{ forms.categories|join:"," }}{% endif %}">{% trans "See all forms" %}</a></p>
30 30
{% endfor %}
31 31
{% endblock %}
tests/test_wcs.py
719 719

  
720 720
    assert 'http://127.0.0.1:8999/backoffice/management/foobar/1' in result
721 721
    assert 'http://127.0.0.1:8999/backoffice/management/foobar/2' in result
722
    assert '"http://127.0.0.1:8999/backoffice/management/"' in result
722
    assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
723 723
    assert 'http://127.0.0.2:8999/backoffice/management/foobar/1' in result
724 724
    assert 'http://127.0.0.2:8999/backoffice/management/foobar/2' in result
725
    assert '"http://127.0.0.2:8999/backoffice/management/"' in result
725
    assert '"http://127.0.0.2:8999/backoffice/management/listing"' in result
726 726

  
727 727
    data = cell.get_data(context)
728 728
    assert 'default' in data
729 729
    assert 'other' in data
730 730

  
731
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
732
        mock_json = mock.Mock(status_code=200)
733
        requests_get.return_value = mock_json
734
        cell.render(context)
735
    assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10'
736
    assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10'
737

  
738
    # limit to a list of categories
739
    cell.categories = {'data': ['default:test-3', 'other:test-4']}
740

  
741
    result = cell.render(context)
742
    assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result
743
    assert '"http://127.0.0.2:8999/backoffice/management/listing?category_slugs=test-4"' in result
744

  
745
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
746
        mock_json = mock.Mock(status_code=200)
747
        requests_get.return_value = mock_json
748
        cell.render(context)
749
    assert len(requests_get.call_args_list) == 2
750
    assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3'
751
    assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
752
    assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10&category_slugs=test-4'
753
    assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
754

  
755
    # limit to a single category
756
    cell.categories = {'data': ['default:test-3']}
757

  
758
    result = cell.render(context)
759
    assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result
760
    assert '"http://127.0.0.2:8999/backoffice/management/listing' not in result
761

  
762
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
763
        mock_json = mock.Mock(status_code=200)
764
        requests_get.return_value = mock_json
765
        cell.render(context)
766
    assert len(requests_get.call_args_list) == 1
767
    assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3'
768
    assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
769

  
770
    # no category selected: call all sites
771
    cell.categories = {'data': []}
772
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
773
        mock_json = mock.Mock(status_code=200)
774
        requests_get.return_value = mock_json
775
        cell.render(context)
776
    assert len(requests_get.call_args_list) == 2
777

  
731 778

  
732 779
def test_care_forms_cell_validity(context):
733 780
    page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
......
767 814
    assert validity_info.invalid_since is not None
768 815

  
769 816

  
817
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
818
def test_care_forms_cell_check_validity(mock_send, context):
819
    page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
820
    cell = WcsCareFormsCell.objects.create(page=page, placeholder='content', order=0)
821

  
822
    # no category
823
    cell.check_validity()
824
    assert ValidityInfo.objects.exists() is False
825

  
826
    # valid categories
827
    cell.categories = {'data': ['default:test-3', 'default:test-9']}
828
    cell.save()
829
    cell.check_validity()
830
    assert ValidityInfo.objects.exists() is False
831

  
832
    # can not retrieve data, don't set cell as invalid
833
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
834
        mock_resp = Response()
835
        mock_resp.status_code = 500
836
        requests_get.return_value = mock_resp
837
        cell.check_validity()
838
    assert ValidityInfo.objects.exists() is False
839
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
840
        requests_get.side_effect = ConnectionError()
841
        cell.check_validity()
842
    assert ValidityInfo.objects.exists() is False
843

  
844
    # can not retrieve categories, don't set cell as invalid
845
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
846
        mock_resp = Response()
847
        mock_resp.status_code = 404
848
        requests_get.return_value = mock_resp
849
        cell.check_validity()
850
    assert ValidityInfo.objects.exists() is False
851

  
852
    # invalid category
853
    cell.categories = {'data': ['default:foobar', 'default:test-9']}
854
    cell.save()
855
    cell.check_validity()
856
    validity_info = ValidityInfo.objects.latest('pk')
857
    assert validity_info.invalid_reason_code == 'wcs_category_not_found'
858
    assert validity_info.invalid_since is not None
859

  
860

  
770 861
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
771 862
def test_care_forms_cell_render_single_site(mock_send, context):
772 863
    page = Page(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
......
785 876
    context['synchronous'] = True  # to get fresh content
786 877

  
787 878
    result = cell.render(context)
788
    assert '"http://127.0.0.1:8999/backoffice/management/"' in result
789
    assert '"http://127.0.0.2:8999/backoffice/management/"' not in result
879
    assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
880
    assert '"http://127.0.0.2:8999/backoffice/management/listing"' not in result
790 881

  
791 882
    data = cell.get_data(context)
792 883
    assert 'default' in data
......
1065 1156
    assert resp.status_int == 302
1066 1157

  
1067 1158

  
1068
def test_manager_current_forms(app, admin_user):
1159
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
1160
def test_manager_current_forms(mock_send, app, admin_user):
1069 1161
    page = Page(title='One', slug='one', template_name='standard')
1070 1162
    page.save()
1071 1163
    app = login(app)
......
2017 2109
        klass.objects.create(page=page, placeholder='content', order=0)
2018 2110
    for klass in cell_classes:
2019 2111
        if klass in [
2112
            WcsCareFormsCell,
2020 2113
            WcsCurrentFormsCell,
2021 2114
            WcsCurrentDraftsCell,
2022 2115
            WcsFormsOfCategoryCell,
2023
-