From 8ec9efbb351c852a8cccd28a1275d0aeec5e0254 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 11 Jul 2022 12:15:16 +0200
Subject: [PATCH] wcs: fix card cell global context with misordered cells
 (#67214)

---
 combo/apps/wcs/models.py |  2 +-
 combo/public/views.py    | 12 ++++++++++--
 tests/test_wcs.py        | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index 7fa1a4bd..a20df2c1 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -1287,7 +1287,7 @@ class WcsCardInfosCell(CardMixin, CellBase):
         if repeat_index is not None:
             try:
                 return context.get(self.global_context_key)[repeat_index]
-            except IndexError:
+            except (IndexError, TypeError):
                 return None
 
     def get_extra_manager_context(self):
diff --git a/combo/public/views.py b/combo/public/views.py
index a6984ec9..5b853d81 100644
--- a/combo/public/views.py
+++ b/combo/public/views.py
@@ -189,7 +189,11 @@ def render_cell(request, cell):
             )
         other_cells = [x for x in other_cells if x.is_visible(request)]
         other_cells.sort(key=lambda x: x.order)
-        for other_cell in other_cells:
+        # first, cells with slugs: other cells may need context from cells with slugs
+        # (for example, cards cells with related ids)
+        other_cells_with_slug = [c for c in other_cells if c.slug]
+        other_cells_without_slug = [c for c in other_cells if not c.slug]
+        for other_cell in other_cells_with_slug + other_cells_without_slug:
             if other_cell.get_reference() != cell.get_reference():
                 other_cell.modify_global_context(context, request)
             elif cell.modify_global_context:
@@ -587,7 +591,11 @@ def publish_page(request, page, status=200, template_name=None):
     if getattr(settings, 'COMBO_TEST_ALWAYS_RENDER_CELLS_SYNCHRONOUSLY', False):
         ctx['synchronous'] = True
 
-    for cell in cells:
+    # first, cells with slugs: other cells may need context from cells with slugs
+    # (for example, cards cells with related ids)
+    cells_with_slug = [c for c in cells if c.slug]
+    cells_without_slug = [c for c in cells if not c.slug]
+    for cell in cells_with_slug + cells_without_slug:
         if cell.modify_global_context:
             cell.modify_global_context(ctx, request)
 
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index d4757977..e47a8530 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -3446,7 +3446,41 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
         ]
     )
 
+    # change cell ordering - cell with slug is after cell with related
+    cell.order = 42
+    cell.save()
+    # no error, but it does not work as expected: both cells has slug.
+    app.get(page.get_online_url(), status=200)
+    # remove slug of second cell
+    cell2.slug = ''
+    cell2.save()
+    urls = [
+        # get first cell data
+        '/api/cards/card_a/1/',
+        # get card_c schema
+        '/api/cards/card_c/@schema',
+        # follow cardc relation
+        '/api/cards/card_c/6/',
+        # and follow cardb relation
+        '/api/cards/card_b/7/',
+    ]
+    resp = app.get(page.get_online_url())
+    assert len(resp.context['cells']) == 2
+    assert resp.context['cells'][0].pk == cell2.pk
+    assert resp.context['cells'][0].repeat_index == 0
+    assert resp.context['cells'][1].pk == cell.pk
+    extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
+    mock_send.reset_mock()
+    cell_resp = app.get(cell2_url + '?ctx=' + extra_ctx[0])
+    assert cell_resp.context['repeat_index'] == 0
+    assert len(mock_send.call_args_list) == len(urls)
+    for j, url in enumerate(urls):
+        assert url in mock_send.call_args_list[j][0][0].url
+
+    cell.order = 0  # reset
+    cell.save()
     # direct and multiple relation (items)
+    cell2.slug = 'slugb'  # reset
     cell2.related_card_path = 'sluga/cardsb'
     cell2.save()
     multiple(
-- 
2.35.1

