<commit_before>import datetime
import time

from django.test import SimpleTestCase, TestCase

from jsonobject.exceptions import BadValueError
from unittest.mock import patch

from corehq.apps.userreports.exceptions import BadSpecError
from corehq.apps.userreports.models import DataSourceConfiguration
from corehq.apps.userreports.tests.utils import (
    get_sample_data_source,
    get_sample_doc_and_indicators,
)
from corehq.sql_db.connections import UCR_ENGINE_ID


class DataSourceConfigurationTest(SimpleTestCase):

    def setUp(self):
        self.config = get_sample_data_source()

    def test_metadata(self):
        # metadata
        self.assertEqual('user-reports', self.config.domain)
        self.assertEqual('CommCareCase', self.config.referenced_doc_type)
        self.assertEqual('CommBugz', self.config.display_name)
        self.assertEqual('sample', self.config.table_id)
        self.assertEqual(UCR_ENGINE_ID, self.config.engine_id)

    def test_filters(self):
        # filters
        not_matching = [
            dict(doc_type="NotCommCareCase", domain='user-reports', type='ticket'),
            dict(doc_type="CommCareCase", domain='not-user-reports', type='ticket'),<commit_msg>add tests for ucr expressions validation<commit_after>import datetime
import time

from django.test import SimpleTestCase, TestCase

from jsonobject.exceptions import BadValueError
from unittest.mock import patch
from corehq.apps.domain.models import AllowedUCRExpressionSettings

from corehq.apps.userreports.exceptions import BadSpecError
from corehq.apps.userreports.models import DataSourceConfiguration
from corehq.apps.userreports.tests.utils import (
    get_sample_data_source,
    get_sample_doc_and_indicators,
)
from corehq.sql_db.connections import UCR_ENGINE_ID


class TestDataSourceConfigAllowedExpressionsValidation(TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        AllowedUCRExpressionSettings.save_allowed_ucr_expressions('domain_nopermission', [])
        AllowedUCRExpressionSettings.save_allowed_ucr_expressions('domain_baseitem', ['base_item_expression'])
        AllowedUCRExpressionSettings.save_allowed_ucr_expressions('domain_related_doc', ['related_doc'])
        AllowedUCRExpressionSettings.save_allowed_ucr_expressions(
            'domain_both',
            ['related_doc', 'base_item_expression']
        )
        cls.config = get_sample_data_source()
        cls.config = cls.config.to_json()
        cls.config['configured_indicators'].append({
            "type": "expression",
            "is_primary_key": False,
            "is_nullable": True,
            "datatype": "string",
            "expression": {
                "value_expression": {
                    "datatype": None,
                    "type": "property_name",
                    "property_name": "name"
                },
                "type": "related_doc",
                "related_doc_type": "Location",
                "doc_id_expression": {
                    "datatype": None,
                    "type": "property_name",
                    "property_name": "health_post_id"
                }
            },
            "column_id": "health_post_name"
        })
        cls.config['base_item_expression'] = {
            "datatype": None,
            "property_name": "actions",
            "type": "property_name"
        }
        cls.config = DataSourceConfiguration.wrap(cls.config)
        return super().setUpClass()

    def test_raises_when_domain_has_no_permission(self):
        self.config.domain = 'domain_nopermission'
        err_msg = f'base_item_expression is not allowed for domain {self.config.domain}'
        with self.assertRaisesMessage(BadSpecError, err_msg):
            self.config.validate()

    def test_raises_when_related_doc_used_without_permission(self):
        self.config.domain = 'domain_baseitem'
        err_msg = f'related_doc is not allowed for domain {self.config.domain}'
        with self.assertRaisesMessage(BadSpecError, err_msg):
            self.config.validate()

    def test_raises_when_domain_has_only_related_doc(self):
        self.config.domain = 'domain_related_doc'
        err_msg = f'base_item_expression is not allowed for domain {self.config.domain}'
        with self.assertRaisesMessage(BadSpecError, err_msg):
            self.config.validate()

    def test_does_not_raise_with_permissions(self):
        self.config.domain = 'domain_both'
        self.assertIsNone(self.config.validate())

    def test_allows_domains_with_no_explicit_permissions(self):
        self.config.domain = 'random_domain'
        self.assertIsNone(self.config.validate())


class DataSourceConfigurationTest(SimpleTestCase):

    def setUp(self):
        self.config = get_sample_data_source()

    def test_metadata(self):
        # metadata
        self.assertEqual('user-reports', self.config.domain)
        self.assertEqual('CommCareCase', self.config.referenced_doc_type)
        self.assertEqual('CommBugz', self.config.display_name)
        self.assertEqual('sample', self.config.table_id)
        self.assertEqual(UCR_ENGINE_ID, self.config.engine_id)

    def test_filters(self):
        # filters
        not_matching = [
            dict(doc_type="NotCommCareCase", domain='user-reports', type='ticket'),
            dict(doc_type="CommCareCase", domain='not-user-reports', type='ticket'),
{'fraction_non_alphanumeric': 0.09625370919881306, 'fraction_numerical': 0.0, 'mean_word_length': 3.1548536209553157, 'pattern_counts': {'":': 19, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7246256', 'n_tokens_mistral': 1580, 'n_tokens_neox': 1515, 'n_words': 252}