|
13 | 13 | import simcore_service_webserver.products
|
14 | 14 | import sqlalchemy as sa
|
15 | 15 | from faker import Faker
|
| 16 | +from models_library.basic_regex import TWILIO_ALPHANUMERIC_SENDER_ID_RE |
16 | 17 | from models_library.products import ProductName
|
17 |
| -from pydantic import BaseModel |
| 18 | +from pydantic import BaseModel, ValidationError |
18 | 19 | from pytest_simcore.helpers.faker_factories import random_product
|
19 | 20 | from pytest_simcore.pydantic_models import (
|
20 | 21 | assert_validation_model,
|
21 | 22 | walk_model_examples_in_package,
|
22 | 23 | )
|
23 | 24 | from simcore_postgres_database.models.products import products as products_table
|
24 |
| -from simcore_service_webserver.constants import FRONTEND_APP_DEFAULT |
25 |
| -from simcore_service_webserver.products._models import Product |
| 25 | +from simcore_service_webserver.constants import ( |
| 26 | + FRONTEND_APP_DEFAULT, |
| 27 | + FRONTEND_APPS_AVAILABLE, |
| 28 | +) |
| 29 | +from simcore_service_webserver.products.models import Product |
26 | 30 | from sqlalchemy import String
|
27 | 31 | from sqlalchemy.dialects import postgresql
|
28 | 32 |
|
29 | 33 |
|
| 34 | +@pytest.fixture(scope="session") |
| 35 | +def product_name() -> ProductName: |
| 36 | + return ProductName(FRONTEND_APP_DEFAULT) |
| 37 | + |
| 38 | + |
30 | 39 | @pytest.mark.parametrize(
|
31 | 40 | "model_cls, example_name, example_data",
|
32 | 41 | chain(walk_model_examples_in_package(simcore_service_webserver.products)),
|
@@ -109,43 +118,82 @@ def test_product_host_regex_with_spaces():
|
109 | 118 | assert product. support_email == "[email protected]"
|
110 | 119 |
|
111 | 120 |
|
112 |
| -@pytest.fixture(scope="session") |
113 |
| -def product_name() -> ProductName: |
114 |
| - return ProductName(FRONTEND_APP_DEFAULT) |
| 121 | +@pytest.fixture |
| 122 | +def fake_product_from_db(faker: Faker, product_name: ProductName) -> dict[str, Any]: |
| 123 | + server_defaults = {} |
| 124 | + for c in products_table.columns: |
| 125 | + if c.server_default is not None: |
| 126 | + if isinstance(c.type, String): |
| 127 | + server_defaults[c.name] = c.server_default.arg |
| 128 | + elif isinstance(c.type, postgresql.JSONB): |
| 129 | + m = re.match(r"^'(.+)'::jsonb$", c.server_default.arg.text) |
| 130 | + if m: |
| 131 | + server_defaults[c.name] = json.loads(m.group(1)) |
| 132 | + return random_product( |
| 133 | + name=product_name, |
| 134 | + fake=faker, |
| 135 | + **server_defaults, |
| 136 | + ) |
115 | 137 |
|
116 | 138 |
|
117 | 139 | def test_safe_load_empty_blanks_on_string_cols_from_db(
|
118 |
| - faker: Faker, product_name: ProductName |
| 140 | + fake_product_from_db: dict[str, Any] |
119 | 141 | ):
|
120 |
| - def _get_server_defaults(): |
121 |
| - server_defaults = {} |
122 |
| - for c in products_table.columns: |
123 |
| - if c.server_default is not None: |
124 |
| - if isinstance(c.type, String): |
125 |
| - server_defaults[c.name] = c.server_default.arg |
126 |
| - elif isinstance(c.type, postgresql.JSONB): |
127 |
| - m = re.match(r"^'(.+)'::jsonb$", c.server_default.arg.text) |
128 |
| - if m: |
129 |
| - server_defaults[c.name] = json.loads(m.group(1)) |
130 |
| - |
131 |
| - return server_defaults |
132 |
| - |
133 | 142 | nullable_strings_column_names = [
|
134 | 143 | c.name
|
135 | 144 | for c in products_table.columns
|
136 | 145 | if isinstance(c.type, sa.String) and c.nullable
|
137 | 146 | ]
|
138 | 147 |
|
139 |
| - server_defaults = _get_server_defaults() |
140 |
| - |
141 |
| - product_row_from_db = random_product( |
142 |
| - name=product_name, |
143 |
| - fake=faker, |
144 |
| - **{name: " " * len(name) for name in nullable_strings_column_names} |
| 148 | + fake_product_from_db.update( |
| 149 | + {name: " " * len(name) for name in nullable_strings_column_names} |
145 | 150 | )
|
146 | 151 |
|
147 |
| - product = Product.model_validate(product_row_from_db) |
| 152 | + product = Product.model_validate(fake_product_from_db) |
148 | 153 |
|
149 | 154 | assert product.model_dump(include=set(nullable_strings_column_names)) == {
|
150 | 155 | name: None for name in nullable_strings_column_names
|
151 | 156 | }
|
| 157 | + |
| 158 | + |
| 159 | +@pytest.mark.parametrize("product_name", list(FRONTEND_APPS_AVAILABLE)) |
| 160 | +def test_product_name_needs_front_end( |
| 161 | + product_name: ProductName, fake_product_from_db: dict[str, Any] |
| 162 | +): |
| 163 | + fake_product_from_db.update(name=product_name) |
| 164 | + product = Product.model_validate(fake_product_from_db) |
| 165 | + assert product.name == product_name |
| 166 | + |
| 167 | + |
| 168 | +def test_product_name_invalid(fake_product_from_db: dict[str, Any]): |
| 169 | + # Test with an invalid name |
| 170 | + fake_product_from_db.update(name="invalid name") |
| 171 | + with pytest.raises(ValidationError): |
| 172 | + Product.model_validate(fake_product_from_db) |
| 173 | + |
| 174 | + |
| 175 | +def test_twilio_sender_id_is_truncated(fake_product_from_db: dict[str, Any]): |
| 176 | + fake_product_from_db.update(short_name=None, display_name="very long name" * 12) |
| 177 | + product = Product.model_validate(fake_product_from_db) |
| 178 | + |
| 179 | + assert re.match( |
| 180 | + TWILIO_ALPHANUMERIC_SENDER_ID_RE, product.twilio_alpha_numeric_sender_id |
| 181 | + ) |
| 182 | + |
| 183 | + |
| 184 | +def test_template_names_from_file(fake_product_from_db: dict[str, Any]): |
| 185 | + fake_product_from_db.update(registration_email_template="some_template_name_id") |
| 186 | + product = Product.model_validate(fake_product_from_db) |
| 187 | + |
| 188 | + assert ( |
| 189 | + product.get_template_name_for(filename="registration_email.jinja2") |
| 190 | + == "some_template_name_id" |
| 191 | + ) |
| 192 | + assert product.get_template_name_for(filename="other_template.jinja2") is None |
| 193 | + |
| 194 | + fake_product_from_db.update(registration_email_template=None) |
| 195 | + product = Product.model_validate(fake_product_from_db) |
| 196 | + assert ( |
| 197 | + product.get_template_name_for(filename="registration_email_template.jinja2") |
| 198 | + is None |
| 199 | + ) |
0 commit comments