planar 0.10.0__py3-none-any.whl → 0.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- planar/app.py +26 -6
- planar/cli.py +26 -0
- planar/data/__init__.py +1 -0
- planar/data/config.py +12 -1
- planar/data/connection.py +89 -4
- planar/data/dataset.py +13 -7
- planar/data/utils.py +145 -25
- planar/db/alembic/env.py +68 -57
- planar/db/alembic.ini +1 -1
- planar/files/storage/config.py +7 -1
- planar/routers/dataset_router.py +5 -1
- planar/routers/info.py +79 -36
- planar/scaffold_templates/pyproject.toml.j2 +1 -1
- planar/testing/fixtures.py +7 -4
- planar/testing/planar_test_client.py +8 -0
- planar/version.py +27 -0
- planar-0.12.0.dist-info/METADATA +202 -0
- {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/RECORD +20 -71
- planar/ai/test_agent_serialization.py +0 -229
- planar/ai/test_agent_tool_step_display.py +0 -78
- planar/data/test_dataset.py +0 -358
- planar/files/storage/test_azure_blob.py +0 -435
- planar/files/storage/test_local_directory.py +0 -162
- planar/files/storage/test_s3.py +0 -299
- planar/files/test_files.py +0 -282
- planar/human/test_human.py +0 -385
- planar/logging/test_formatter.py +0 -327
- planar/modeling/mixins/test_auditable.py +0 -97
- planar/modeling/mixins/test_timestamp.py +0 -134
- planar/modeling/mixins/test_uuid_primary_key.py +0 -52
- planar/routers/test_agents_router.py +0 -174
- planar/routers/test_dataset_router.py +0 -429
- planar/routers/test_files_router.py +0 -49
- planar/routers/test_object_config_router.py +0 -367
- planar/routers/test_routes_security.py +0 -168
- planar/routers/test_rule_router.py +0 -470
- planar/routers/test_workflow_router.py +0 -564
- planar/rules/test_data/account_dormancy_management.json +0 -223
- planar/rules/test_data/airline_loyalty_points_calculator.json +0 -262
- planar/rules/test_data/applicant_risk_assessment.json +0 -435
- planar/rules/test_data/booking_fraud_detection.json +0 -407
- planar/rules/test_data/cellular_data_rollover_system.json +0 -258
- planar/rules/test_data/clinical_trial_eligibility_screener.json +0 -437
- planar/rules/test_data/customer_lifetime_value.json +0 -143
- planar/rules/test_data/import_duties_calculator.json +0 -289
- planar/rules/test_data/insurance_prior_authorization.json +0 -443
- planar/rules/test_data/online_check_in_eligibility_system.json +0 -254
- planar/rules/test_data/order_consolidation_system.json +0 -375
- planar/rules/test_data/portfolio_risk_monitor.json +0 -471
- planar/rules/test_data/supply_chain_risk.json +0 -253
- planar/rules/test_data/warehouse_cross_docking.json +0 -237
- planar/rules/test_rules.py +0 -1494
- planar/security/tests/test_auth_middleware.py +0 -162
- planar/security/tests/test_authorization_context.py +0 -78
- planar/security/tests/test_cedar_basics.py +0 -41
- planar/security/tests/test_cedar_policies.py +0 -158
- planar/security/tests/test_jwt_principal_context.py +0 -179
- planar/test_app.py +0 -142
- planar/test_cli.py +0 -394
- planar/test_config.py +0 -515
- planar/test_object_config.py +0 -527
- planar/test_object_registry.py +0 -14
- planar/test_sqlalchemy.py +0 -193
- planar/test_utils.py +0 -105
- planar/testing/test_memory_storage.py +0 -143
- planar/workflows/test_concurrency_detection.py +0 -120
- planar/workflows/test_lock_timeout.py +0 -140
- planar/workflows/test_serialization.py +0 -1203
- planar/workflows/test_suspend_deserialization.py +0 -231
- planar/workflows/test_workflow.py +0 -2005
- planar-0.10.0.dist-info/METADATA +0 -323
- {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/WHEEL +0 -0
- {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/entry_points.txt +0 -0
@@ -1,470 +0,0 @@
|
|
1
|
-
from decimal import Decimal
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
from pydantic import BaseModel
|
5
|
-
|
6
|
-
from planar.app import PlanarApp
|
7
|
-
from planar.config import sqlite_config
|
8
|
-
from planar.rules import rule
|
9
|
-
from planar.testing.planar_test_client import PlanarTestClient
|
10
|
-
|
11
|
-
|
12
|
-
class ExpenseRuleInput(BaseModel):
|
13
|
-
title: str
|
14
|
-
amount: float
|
15
|
-
description: str
|
16
|
-
status: str
|
17
|
-
category: str
|
18
|
-
|
19
|
-
|
20
|
-
class RuleOutput(BaseModel):
|
21
|
-
reason: str
|
22
|
-
approved: bool
|
23
|
-
|
24
|
-
|
25
|
-
class TransactionVolumeRow(BaseModel):
|
26
|
-
period: str
|
27
|
-
country: str
|
28
|
-
currency: str
|
29
|
-
completed_count: int
|
30
|
-
rejected_count: int
|
31
|
-
|
32
|
-
|
33
|
-
class TransactionVolume(BaseModel):
|
34
|
-
rows: list[TransactionVolumeRow]
|
35
|
-
total_completed_count: int
|
36
|
-
total_rejected_count: int
|
37
|
-
|
38
|
-
|
39
|
-
class PricingInput(BaseModel):
|
40
|
-
rows: list[TransactionVolumeRow]
|
41
|
-
|
42
|
-
|
43
|
-
class TransactionPricingLine(TransactionVolumeRow):
|
44
|
-
completed_price_per_transaction_usd: Decimal
|
45
|
-
rejected_price_per_transaction_usd: Decimal
|
46
|
-
|
47
|
-
|
48
|
-
class PricingRuleOutput(BaseModel):
|
49
|
-
line_items: list[TransactionPricingLine]
|
50
|
-
|
51
|
-
|
52
|
-
class PricingRuleOutputWrongType(BaseModel):
|
53
|
-
line_items: list[TransactionPricingLine]
|
54
|
-
some_other_field: str
|
55
|
-
|
56
|
-
|
57
|
-
@rule(description="Complex business rule")
|
58
|
-
def complex_business_rule(input: ExpenseRuleInput) -> RuleOutput:
|
59
|
-
"""
|
60
|
-
A complex business rule that determines if the expense should be approved
|
61
|
-
"""
|
62
|
-
# input and output must be json serializable objects for the zen / gorules lib to work
|
63
|
-
return RuleOutput(reason="The widgets look fantastic", approved=True)
|
64
|
-
|
65
|
-
|
66
|
-
@rule(description="Calculates fees based on tiered, total transaction volume.")
|
67
|
-
def pricing_rule(
|
68
|
-
input: PricingInput,
|
69
|
-
) -> PricingRuleOutput:
|
70
|
-
"""
|
71
|
-
Calculates fees based on country, currency, and tiered volume.
|
72
|
-
"""
|
73
|
-
return PricingRuleOutput(line_items=[])
|
74
|
-
|
75
|
-
|
76
|
-
@rule(
|
77
|
-
description="Calculates fees based on tiered, total transaction volume with wrong type"
|
78
|
-
)
|
79
|
-
def pricing_rule_with_wrong_type(
|
80
|
-
input: PricingInput,
|
81
|
-
) -> PricingRuleOutputWrongType:
|
82
|
-
return PricingRuleOutputWrongType(line_items=[], some_other_field="test")
|
83
|
-
|
84
|
-
|
85
|
-
@pytest.fixture(name="app")
|
86
|
-
def app_fixture(tmp_db_path: str):
|
87
|
-
app = PlanarApp(
|
88
|
-
config=sqlite_config(tmp_db_path),
|
89
|
-
title="Test app for agent router",
|
90
|
-
description="Testing agent endpoints",
|
91
|
-
)
|
92
|
-
|
93
|
-
app.register_rule(complex_business_rule)
|
94
|
-
app.register_rule(pricing_rule_with_wrong_type)
|
95
|
-
app.register_rule(pricing_rule)
|
96
|
-
return app
|
97
|
-
|
98
|
-
|
99
|
-
EXPENSE_RULE_JDM = {
|
100
|
-
"nodes": [
|
101
|
-
{
|
102
|
-
"id": "7e51efb8-7463-4775-ad69-180442a34444",
|
103
|
-
"type": "inputNode",
|
104
|
-
"name": "Input",
|
105
|
-
"content": {
|
106
|
-
"schema": '{"properties": {"title": {"title": "Title", "type": "string"}, "amount": {"title": "Amount", "type": "number"}, "description": {"title": "Description", "type": "string"}, "status": {"title": "Status", "type": "string"}, "category": {"title": "Category", "type": "string"}}, "required": ["title", "amount", "description", "status", "category"], "title": "ExpenseRuleInput", "type": "object"}'
|
107
|
-
},
|
108
|
-
"position": {"x": 100, "y": 100},
|
109
|
-
},
|
110
|
-
{
|
111
|
-
"id": "abf8c265-da42-4b81-b7bf-349d3e248294",
|
112
|
-
"type": "decisionTableNode",
|
113
|
-
"name": "decisionTable1",
|
114
|
-
"content": {
|
115
|
-
"hitPolicy": "first",
|
116
|
-
"rules": [
|
117
|
-
{
|
118
|
-
"_id": "9fc59e78-58be-412b-9d2b-79c22bcfefe4",
|
119
|
-
"2a5ac809-24db-431b-a228-7bc318cd0a3f": "",
|
120
|
-
"25f2e0b6-c02b-43a2-a9cd-d40e5c1ca709": '"default value"',
|
121
|
-
"4b09e532-bb42-453b-9c00-26af89f70a03": "true",
|
122
|
-
}
|
123
|
-
],
|
124
|
-
"inputs": [
|
125
|
-
{
|
126
|
-
"id": "2a5ac809-24db-431b-a228-7bc318cd0a3f",
|
127
|
-
"name": "Input",
|
128
|
-
"field": "",
|
129
|
-
}
|
130
|
-
],
|
131
|
-
"outputs": [
|
132
|
-
{
|
133
|
-
"id": "25f2e0b6-c02b-43a2-a9cd-d40e5c1ca709",
|
134
|
-
"field": "reason",
|
135
|
-
"name": "reason",
|
136
|
-
},
|
137
|
-
{
|
138
|
-
"id": "4b09e532-bb42-453b-9c00-26af89f70a03",
|
139
|
-
"field": "approved",
|
140
|
-
"name": "approved",
|
141
|
-
},
|
142
|
-
],
|
143
|
-
"passThrough": True,
|
144
|
-
"passThorough": False,
|
145
|
-
"inputField": None,
|
146
|
-
"outputPath": None,
|
147
|
-
"executionMode": "single",
|
148
|
-
},
|
149
|
-
"position": {"x": 405, "y": 120},
|
150
|
-
},
|
151
|
-
{
|
152
|
-
"id": "40abc689-6e0e-40ee-bc76-df51065e6ff5",
|
153
|
-
"type": "outputNode",
|
154
|
-
"name": "Output",
|
155
|
-
"content": {
|
156
|
-
"schema": '{"properties": {"reason": {"title": "Reason", "type": "string"}, "approved": {"title": "Approved", "type": "boolean"}}, "required": ["reason", "approved"], "title": "RuleOutput", "type": "object"}'
|
157
|
-
},
|
158
|
-
"position": {"x": 885, "y": 130},
|
159
|
-
},
|
160
|
-
{
|
161
|
-
"id": "a5385f35-5ba7-4cbf-a5b8-f87bca6fd95c",
|
162
|
-
"type": "expressionNode",
|
163
|
-
"name": "expression1",
|
164
|
-
"content": {
|
165
|
-
"expressions": [],
|
166
|
-
"passThrough": True,
|
167
|
-
"inputField": None,
|
168
|
-
"outputPath": None,
|
169
|
-
"executionMode": "single",
|
170
|
-
},
|
171
|
-
"position": {"x": 590, "y": 350},
|
172
|
-
},
|
173
|
-
{
|
174
|
-
"id": "0689381e-0650-4ba5-b4ba-1a1800f035ca",
|
175
|
-
"type": "decisionTableNode",
|
176
|
-
"name": "decisionTable2",
|
177
|
-
"content": {
|
178
|
-
"hitPolicy": "first",
|
179
|
-
"rules": [],
|
180
|
-
"inputs": [
|
181
|
-
{
|
182
|
-
"id": "4caf4578-a643-4a3c-bc6e-2bdf8559e601",
|
183
|
-
"name": "Input",
|
184
|
-
"field": "",
|
185
|
-
}
|
186
|
-
],
|
187
|
-
"outputs": [
|
188
|
-
{
|
189
|
-
"id": "4ec07a83-70ca-46ec-aee7-331c44a8da76",
|
190
|
-
"field": "output",
|
191
|
-
"name": "Output",
|
192
|
-
}
|
193
|
-
],
|
194
|
-
"passThrough": True,
|
195
|
-
"passThorough": None,
|
196
|
-
"inputField": None,
|
197
|
-
"outputPath": None,
|
198
|
-
"executionMode": "single",
|
199
|
-
},
|
200
|
-
"position": {"x": 885, "y": 500},
|
201
|
-
},
|
202
|
-
],
|
203
|
-
"edges": [
|
204
|
-
{
|
205
|
-
"id": "cd19ba68-3f39-4b50-8014-85f01258fbe3",
|
206
|
-
"type": "edge",
|
207
|
-
"sourceId": "7e51efb8-7463-4775-ad69-180442a34444",
|
208
|
-
"targetId": "abf8c265-da42-4b81-b7bf-349d3e248294",
|
209
|
-
},
|
210
|
-
{
|
211
|
-
"id": "7c26024c-0f02-4393-8cf0-0f5097cd21d0",
|
212
|
-
"type": "edge",
|
213
|
-
"sourceId": "abf8c265-da42-4b81-b7bf-349d3e248294",
|
214
|
-
"targetId": "40abc689-6e0e-40ee-bc76-df51065e6ff5",
|
215
|
-
},
|
216
|
-
{
|
217
|
-
"id": "66d1a27e-2cf2-4b2e-862d-b65dc554c320",
|
218
|
-
"type": "edge",
|
219
|
-
"sourceId": "abf8c265-da42-4b81-b7bf-349d3e248294",
|
220
|
-
"targetId": "a5385f35-5ba7-4cbf-a5b8-f87bca6fd95c",
|
221
|
-
},
|
222
|
-
{
|
223
|
-
"id": "abf1329e-c27d-4655-b1a7-d410ea03b998",
|
224
|
-
"type": "edge",
|
225
|
-
"sourceId": "a5385f35-5ba7-4cbf-a5b8-f87bca6fd95c",
|
226
|
-
"targetId": "40abc689-6e0e-40ee-bc76-df51065e6ff5",
|
227
|
-
},
|
228
|
-
{
|
229
|
-
"id": "d56e19e6-2303-4272-b7df-49e3df75c62f",
|
230
|
-
"type": "edge",
|
231
|
-
"sourceId": "a5385f35-5ba7-4cbf-a5b8-f87bca6fd95c",
|
232
|
-
"targetId": "0689381e-0650-4ba5-b4ba-1a1800f035ca",
|
233
|
-
},
|
234
|
-
],
|
235
|
-
}
|
236
|
-
|
237
|
-
|
238
|
-
async def test_save_rule_endpoints(client: PlanarTestClient, app: PlanarApp):
|
239
|
-
response = await client.get("/planar/v1/rules/complex_business_rule")
|
240
|
-
|
241
|
-
assert response.status_code == 200
|
242
|
-
|
243
|
-
data = response.json()
|
244
|
-
|
245
|
-
assert len(data["configs"]) == 1
|
246
|
-
|
247
|
-
# save the rule
|
248
|
-
response = await client.post(
|
249
|
-
"/planar/v1/rules/complex_business_rule", json=EXPENSE_RULE_JDM
|
250
|
-
)
|
251
|
-
|
252
|
-
assert response.status_code == 200, response.text
|
253
|
-
|
254
|
-
data = response.json()
|
255
|
-
|
256
|
-
assert len(data["configs"]) == 2
|
257
|
-
|
258
|
-
|
259
|
-
PRICING_RULE_JDM = {
|
260
|
-
"nodes": [
|
261
|
-
{
|
262
|
-
"id": "6cc036d3-3350-449e-9b2c-1569b8f86ffc",
|
263
|
-
"type": "inputNode",
|
264
|
-
"name": "Input",
|
265
|
-
"content": {
|
266
|
-
"schema": '{"$defs": {"TransactionVolumeRow": {"properties": {"period": {"title": "Period", "type": "string"}, "country": {"title": "Country", "type": "string"}, "currency": {"title": "Currency", "type": "string"}, "completed_count": {"title": "Completed Count", "type": "integer"}, "rejected_count": {"title": "Rejected Count", "type": "integer"}}, "required": ["period", "country", "currency", "completed_count", "rejected_count"], "title": "TransactionVolumeRow", "type": "object"}}, "properties": {"rows": {"items": {"$ref": "#/$defs/TransactionVolumeRow"}, "title": "Rows", "type": "array"}}, "required": ["rows"], "title": "PricingInput", "type": "object"}'
|
267
|
-
},
|
268
|
-
"position": {"x": 100, "y": 100},
|
269
|
-
},
|
270
|
-
{
|
271
|
-
"id": "3921e9d3-02e3-4a72-b74d-037c80f97eaa",
|
272
|
-
"type": "decisionTableNode",
|
273
|
-
"name": "decisionTable1",
|
274
|
-
"content": {
|
275
|
-
"hitPolicy": "first",
|
276
|
-
"rules": [
|
277
|
-
{
|
278
|
-
"_id": "15d4429c-39bc-448d-a7f4-187eaea4493a",
|
279
|
-
"e5688083-30b9-449e-adaf-bf8ff69eb2ac": '"ARS"',
|
280
|
-
"42c29309-9aa4-4441-bd1a-b1b57d1b628e": "<= 6000",
|
281
|
-
"71b9d121-5b37-4b0b-b4c2-d29a868fed35": '"Argentina"',
|
282
|
-
"662e29e1-d0b8-4cf4-a443-3e92f2157054": "100",
|
283
|
-
"_description": "",
|
284
|
-
},
|
285
|
-
{
|
286
|
-
"_id": "9ef47884-004d-4314-a61c-38778ed7b7d7",
|
287
|
-
"e5688083-30b9-449e-adaf-bf8ff69eb2ac": "",
|
288
|
-
"42c29309-9aa4-4441-bd1a-b1b57d1b628e": "",
|
289
|
-
"71b9d121-5b37-4b0b-b4c2-d29a868fed35": "",
|
290
|
-
"662e29e1-d0b8-4cf4-a443-3e92f2157054": "1.00",
|
291
|
-
},
|
292
|
-
],
|
293
|
-
"inputs": [
|
294
|
-
{
|
295
|
-
"id": "e5688083-30b9-449e-adaf-bf8ff69eb2ac",
|
296
|
-
"name": "Currency",
|
297
|
-
"field": "currency",
|
298
|
-
},
|
299
|
-
{
|
300
|
-
"id": "42c29309-9aa4-4441-bd1a-b1b57d1b628e",
|
301
|
-
"name": "Completed Count",
|
302
|
-
"field": "completed_count",
|
303
|
-
},
|
304
|
-
{
|
305
|
-
"id": "71b9d121-5b37-4b0b-b4c2-d29a868fed35",
|
306
|
-
"name": "Country",
|
307
|
-
"field": "country",
|
308
|
-
},
|
309
|
-
],
|
310
|
-
"outputs": [
|
311
|
-
{
|
312
|
-
"id": "662e29e1-d0b8-4cf4-a443-3e92f2157054",
|
313
|
-
"field": "completed_price_per_transaction_usd",
|
314
|
-
"name": "Completed Price Per Transaction (USD)",
|
315
|
-
}
|
316
|
-
],
|
317
|
-
"passThrough": True,
|
318
|
-
"passThorough": None,
|
319
|
-
"inputField": "rows",
|
320
|
-
"outputPath": "line_items",
|
321
|
-
"executionMode": "loop",
|
322
|
-
},
|
323
|
-
"position": {"x": 350, "y": 95},
|
324
|
-
},
|
325
|
-
{
|
326
|
-
"id": "a9a82683-5dbb-4eed-8326-83dea36c1d53",
|
327
|
-
"type": "outputNode",
|
328
|
-
"name": "Output",
|
329
|
-
"content": {
|
330
|
-
"schema": '{"$defs": {"TransactionPricingLine": {"properties": {"period": {"title": "Period", "type": "string"}, "country": {"title": "Country", "type": "string"}, "currency": {"title": "Currency", "type": "string"}, "completed_count": {"title": "Completed Count", "type": "integer"}, "rejected_count": {"title": "Rejected Count", "type": "integer"}, "completed_price_per_transaction_usd": {"title": "Completed Price Per Transaction Usd", "type": "number"}, "rejected_price_per_transaction_usd": {"title": "Rejected Price Per Transaction Usd", "type": "number"}}, "required": ["period", "country", "currency", "completed_count", "rejected_count", "completed_price_per_transaction_usd", "rejected_price_per_transaction_usd"], "title": "TransactionPricingLine", "type": "object"}}, "properties": {"line_items": {"items": {"$ref": "#/$defs/TransactionPricingLine"}, "title": "Line Items", "type": "array"}}, "required": ["line_items"], "title": "PricingRuleOutput", "type": "object"}'
|
331
|
-
},
|
332
|
-
"position": {"x": 1195, "y": 60},
|
333
|
-
},
|
334
|
-
{
|
335
|
-
"id": "b384c91d-dbc3-4043-a0f0-a3adef9ac340",
|
336
|
-
"type": "expressionNode",
|
337
|
-
"name": "expression1",
|
338
|
-
"content": {
|
339
|
-
"expressions": [
|
340
|
-
{
|
341
|
-
"id": "b0e3f514-c109-43e4-91ad-3007110d0a35",
|
342
|
-
"key": "rejected_price_per_transaction_usd",
|
343
|
-
"value": "200",
|
344
|
-
}
|
345
|
-
],
|
346
|
-
"passThrough": True,
|
347
|
-
"inputField": "line_items",
|
348
|
-
"outputPath": "line_items",
|
349
|
-
"executionMode": "loop",
|
350
|
-
},
|
351
|
-
"position": {"x": 670, "y": 100},
|
352
|
-
},
|
353
|
-
{
|
354
|
-
"id": "b89b13b8-526f-4db2-a524-faeeca0e78d7",
|
355
|
-
"type": "expressionNode",
|
356
|
-
"name": "expression2",
|
357
|
-
"content": {
|
358
|
-
"expressions": [
|
359
|
-
{
|
360
|
-
"id": "b6a9570b-7ea1-4ebb-b5eb-b693fe14ca47",
|
361
|
-
"key": "line_items",
|
362
|
-
"value": "line_items",
|
363
|
-
}
|
364
|
-
],
|
365
|
-
"passThrough": False,
|
366
|
-
"inputField": None,
|
367
|
-
"outputPath": None,
|
368
|
-
"executionMode": "single",
|
369
|
-
},
|
370
|
-
"position": {"x": 950, "y": 100},
|
371
|
-
},
|
372
|
-
],
|
373
|
-
"edges": [
|
374
|
-
{
|
375
|
-
"id": "a9c02fbb-3ad6-4f65-a718-16c0e02d7551",
|
376
|
-
"type": "edge",
|
377
|
-
"sourceId": "6cc036d3-3350-449e-9b2c-1569b8f86ffc",
|
378
|
-
"targetId": "3921e9d3-02e3-4a72-b74d-037c80f97eaa",
|
379
|
-
},
|
380
|
-
{
|
381
|
-
"id": "c2959035-5f0d-4317-8ccf-2f885450b669",
|
382
|
-
"type": "edge",
|
383
|
-
"sourceId": "3921e9d3-02e3-4a72-b74d-037c80f97eaa",
|
384
|
-
"targetId": "b384c91d-dbc3-4043-a0f0-a3adef9ac340",
|
385
|
-
},
|
386
|
-
{
|
387
|
-
"id": "6513b9bf-7016-4776-bf84-81418caf7b74",
|
388
|
-
"type": "edge",
|
389
|
-
"sourceId": "b384c91d-dbc3-4043-a0f0-a3adef9ac340",
|
390
|
-
"targetId": "b89b13b8-526f-4db2-a524-faeeca0e78d7",
|
391
|
-
},
|
392
|
-
{
|
393
|
-
"id": "b75e295e-8fb4-45b6-9040-06fdd8d6723e",
|
394
|
-
"type": "edge",
|
395
|
-
"sourceId": "b89b13b8-526f-4db2-a524-faeeca0e78d7",
|
396
|
-
"targetId": "a9a82683-5dbb-4eed-8326-83dea36c1d53",
|
397
|
-
},
|
398
|
-
],
|
399
|
-
}
|
400
|
-
|
401
|
-
|
402
|
-
async def test_save_rule_endpoints_with_jdm(client: PlanarTestClient, app: PlanarApp):
|
403
|
-
response = await client.get("/planar/v1/rules/pricing_rule")
|
404
|
-
|
405
|
-
assert response.status_code == 200
|
406
|
-
|
407
|
-
data = response.json()
|
408
|
-
|
409
|
-
assert len(data["configs"]) == 1
|
410
|
-
|
411
|
-
# save the rule
|
412
|
-
response = await client.post("/planar/v1/rules/pricing_rule", json=PRICING_RULE_JDM)
|
413
|
-
|
414
|
-
assert response.status_code == 200
|
415
|
-
|
416
|
-
data = response.json()
|
417
|
-
|
418
|
-
assert len(data["configs"]) == 2
|
419
|
-
|
420
|
-
|
421
|
-
async def test_save_rule_endpoints_with_jdm_wrong_type(
|
422
|
-
client: PlanarTestClient, app: PlanarApp
|
423
|
-
):
|
424
|
-
response = await client.get("/planar/v1/rules/pricing_rule_with_wrong_type")
|
425
|
-
|
426
|
-
assert response.status_code == 200
|
427
|
-
|
428
|
-
data = response.json()
|
429
|
-
|
430
|
-
assert len(data["configs"]) == 1
|
431
|
-
|
432
|
-
# save the rule
|
433
|
-
response = await client.post(
|
434
|
-
"/planar/v1/rules/pricing_rule_with_wrong_type",
|
435
|
-
json=PRICING_RULE_JDM,
|
436
|
-
)
|
437
|
-
|
438
|
-
assert response.status_code == 400
|
439
|
-
response_json = response.json()
|
440
|
-
assert response_json["detail"]["error"] == "ValidationError"
|
441
|
-
assert response_json["detail"]["object_name"] == "pricing_rule_with_wrong_type"
|
442
|
-
assert response_json["detail"]["object_type"] == "rule"
|
443
|
-
assert response_json["detail"]["diagnostics"]["is_valid"] is False
|
444
|
-
assert (
|
445
|
-
response_json["detail"]["diagnostics"]["suggested_fix"]["jdm"]["nodes"][0][
|
446
|
-
"content"
|
447
|
-
]["schema"]
|
448
|
-
== PRICING_RULE_JDM["nodes"][0]["content"]["schema"]
|
449
|
-
)
|
450
|
-
# check contains some_other_field
|
451
|
-
assert (
|
452
|
-
"some_other_field"
|
453
|
-
in response_json["detail"]["diagnostics"]["suggested_fix"]["jdm"]["nodes"][2][
|
454
|
-
"content"
|
455
|
-
]["schema"]
|
456
|
-
)
|
457
|
-
|
458
|
-
assert response_json["detail"]["diagnostics"]["issues"] == [
|
459
|
-
{
|
460
|
-
"error_code": "MISSING_FIELD",
|
461
|
-
"field_path": "some_other_field",
|
462
|
-
"message": "Field 'some_other_field' is missing in current node",
|
463
|
-
"reference_value": {
|
464
|
-
"title": "Some Other Field",
|
465
|
-
"type": "string",
|
466
|
-
},
|
467
|
-
"current_value": None,
|
468
|
-
"for_object": "outputNode",
|
469
|
-
}
|
470
|
-
]
|