diff --git a/backend/spellbook/parsers/variants_query_grammar.lark b/backend/spellbook/parsers/variants_query_grammar.lark index 8a40dbc7..35cd3f7b 100644 --- a/backend/spellbook/parsers/variants_query_grammar.lark +++ b/backend/spellbook/parsers/variants_query_grammar.lark @@ -79,7 +79,7 @@ RPAREN: ")" NEGATION_OPERATOR: "-" -LONG_LITERAL.10: /"(?:[^"\\]|\\")+"/ +LONG_LITERAL.10: /"(?:[^"\\]|\\\")+"/ SHORT_LITERAL.-1: /[a-zA-Z0-9\u00C0-\u00FF_\-',+!\.]+/ diff --git a/backend/spellbook/tests/test_views/test_variant_views.py b/backend/spellbook/tests/test_views/test_variant_views.py index c713bc88..c9bed739 100644 --- a/backend/spellbook/tests/test_views/test_variant_views.py +++ b/backend/spellbook/tests/test_views/test_variant_views.py @@ -133,6 +133,8 @@ def test_variants_detail_view(self): self.variant_assertions(result) def test_variants_list_view_query_by_card_name(self): + a_card = Card.objects.first() + assert a_card is not None for card, search in ((c, name) for c in Card.objects.all() for name in (c.name, c.name_unaccented, c.name_unaccented.replace('-', ''), c.name_unaccented.replace('-', ' '))): prefix_without_spaces = search.partition(' ')[0] search_without_underscores = search.replace('_', '').strip() @@ -161,6 +163,16 @@ def test_variants_list_view_query_by_card_name(self): self.assertSetEqual({v.id for v in result.results}, {v.id for v in variants}) for v in result.results: self.variant_assertions(v) + qq = f'{q} card:"{a_card.name}"' + with self.subTest(f'query by card name: {search} with additional card {a_card} and query {q}'): + response = self.client.get('/variants', data={'q': qq}, follow=True) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get('Content-Type'), 'application/json') + result = json.loads(response.content, object_hook=json_to_python_lambda) + variants = self.public_variants.filter(uses__id=card.id).filter(uses__id=a_card.id).distinct() + self.assertSetEqual({v.id for v in result.results}, {v.id for v in variants}) + for v in result.results: + self.variant_assertions(v) def test_variants_list_view_query_by_card_count(self): min_cards, max_cards = self.public_variants.aggregate(min_cards=models.Min('cards_count'), max_cards=models.Max('cards_count')).values() diff --git a/backend/spellbook/transformers/variants_query_transformer.py b/backend/spellbook/transformers/variants_query_transformer.py index 92beba68..aa900ecb 100644 --- a/backend/spellbook/transformers/variants_query_transformer.py +++ b/backend/spellbook/transformers/variants_query_transformer.py @@ -123,11 +123,11 @@ def variants_query_parser(base: QuerySet[Variant], query_string: str) -> QuerySe filtered_variants = filtered_variants.exclude(filter.q) if filter.negated else filtered_variants.filter(filter.q) for filter in filters.cards_filters: filtered_cards = CardInVariant.objects.filter(filter.q) - q = Q(pk__in=filtered_cards.values('variant').distinct()) + q = Q(pk__in=filtered_cards.values('variant_id').distinct()) filtered_variants = filtered_variants.exclude(q) if filter.negated else filtered_variants.filter(q) for filter in filters.results_filters: filtered_produces = FeatureProducedByVariant.objects.filter(filter.q) - q = Q(pk__in=filtered_produces.values('variant').distinct()) + q = Q(pk__in=filtered_produces.values('variant_id').distinct()) filtered_variants = filtered_variants.exclude(q) if filter.negated else filtered_variants.filter(q) return filtered_variants except UnexpectedToken as e: