@voxgig/sdkgen 0.44.0 → 1.0.1
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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/cmp/ReadmeEntity.js +9 -153
- package/dist/cmp/ReadmeEntity.js.map +1 -1
- package/dist/cmp/ReadmeIntro.js +9 -14
- package/dist/cmp/ReadmeIntro.js.map +1 -1
- package/dist/cmp/ReadmeModel.js +6 -4
- package/dist/cmp/ReadmeModel.js.map +1 -1
- package/dist/cmp/ReadmeOptions.js +9 -61
- package/dist/cmp/ReadmeOptions.js.map +1 -1
- package/dist/cmp/ReadmeRef.js +10 -1328
- package/dist/cmp/ReadmeRef.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -2
- package/dist/sdkgen.js +2 -1
- package/dist/sdkgen.js.map +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +9 -0
- package/dist/utility.js.map +1 -1
- package/package.json +3 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +9 -4
- package/project/.sdk/src/cmp/go/Entity_go.ts +2 -2
- package/project/.sdk/src/cmp/go/Main_go.ts +8 -4
- package/project/.sdk/src/cmp/go/Package_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +138 -0
- package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +8 -5
- package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +2 -2
- package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +18 -0
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +8 -5
- package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +58 -0
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +13 -9
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +354 -0
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +8 -6
- package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +2 -2
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +222 -41
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +142 -60
- package/project/.sdk/src/cmp/go/Test_go.ts +2 -2
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +21 -4
- package/project/.sdk/src/cmp/js/Config_js.ts +18 -0
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +138 -0
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +11 -6
- package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +18 -0
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +6 -3
- package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +58 -0
- package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +384 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +23 -12
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +107 -74
- package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +1 -5
- package/project/.sdk/src/cmp/lua/Config_lua.ts +9 -4
- package/project/.sdk/src/cmp/lua/Package_lua.ts +9 -2
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +138 -0
- package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +18 -0
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +58 -0
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +360 -0
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +172 -29
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +120 -52
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +20 -4
- package/project/.sdk/src/cmp/php/Config_php.ts +10 -8
- package/project/.sdk/src/cmp/php/Package_php.ts +7 -1
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +138 -0
- package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +18 -0
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +58 -0
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +358 -0
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +171 -28
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +126 -55
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +17 -3
- package/project/.sdk/src/cmp/py/Config_py.ts +9 -4
- package/project/.sdk/src/cmp/py/Package_py.ts +8 -1
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +138 -0
- package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +18 -0
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +58 -0
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +356 -0
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +164 -27
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +125 -51
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -4
- package/project/.sdk/src/cmp/rb/Config_rb.ts +9 -4
- package/project/.sdk/src/cmp/rb/Package_rb.ts +9 -2
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +138 -0
- package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +18 -0
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +58 -0
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +361 -0
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +172 -29
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +120 -52
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +19 -3
- package/project/.sdk/src/cmp/ts/Config_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/Package_ts.ts +1 -1
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +138 -0
- package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +11 -6
- package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +9 -5
- package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +58 -0
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +384 -0
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +213 -42
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +168 -75
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +1 -5
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +8 -1
- package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +8 -2
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +21 -1
- package/project/.sdk/tm/go/feature/test_feature.go +51 -3
- package/project/.sdk/tm/go/test/runner_test.go +106 -6
- package/project/.sdk/tm/go/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/go/utility/fetcher.go +10 -0
- package/project/.sdk/tm/go/utility/make_url.go +12 -0
- package/project/.sdk/tm/go/utility/prepare_auth.go +15 -1
- package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +7 -1
- package/project/.sdk/tm/lua/feature/test_feature.lua +41 -3
- package/project/.sdk/tm/lua/test/runner.lua +74 -0
- package/project/.sdk/tm/lua/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/lua/utility/fetcher.lua +13 -0
- package/project/.sdk/tm/lua/utility/make_url.lua +16 -0
- package/project/.sdk/tm/lua/utility/prepare_auth.lua +9 -1
- package/project/.sdk/tm/php/feature/TestFeature.php +185 -43
- package/project/.sdk/tm/php/test/Runner.php +62 -0
- package/project/.sdk/tm/php/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/php/utility/Fetcher.php +132 -9
- package/project/.sdk/tm/php/utility/MakeUrl.php +16 -0
- package/project/.sdk/tm/php/utility/PrepareAuth.php +11 -1
- package/project/.sdk/tm/py/feature/test_feature.py +35 -3
- package/project/.sdk/tm/py/test/runner.py +60 -0
- package/project/.sdk/tm/py/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/py/utility/fetcher.py +13 -0
- package/project/.sdk/tm/py/utility/make_url.py +13 -0
- package/project/.sdk/tm/py/utility/prepare_auth.py +10 -1
- package/project/.sdk/tm/rb/feature/test_feature.rb +36 -3
- package/project/.sdk/tm/rb/test/runner.rb +46 -0
- package/project/.sdk/tm/rb/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/rb/utility/fetcher.rb +49 -28
- package/project/.sdk/tm/rb/utility/make_url.rb +16 -0
- package/project/.sdk/tm/rb/utility/prepare_auth.rb +8 -1
- package/project/.sdk/tm/ts/src/utility/MakeUrlUtility.ts +7 -8
- package/project/.sdk/tm/ts/src/utility/PrepareAuthUtility.ts +7 -1
- package/project/.sdk/tm/ts/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/ts/test/utility.ts +120 -2
- package/src/cmp/ReadmeEntity.ts +11 -178
- package/src/cmp/ReadmeIntro.ts +11 -25
- package/src/cmp/ReadmeModel.ts +7 -5
- package/src/cmp/ReadmeOptions.ts +12 -74
- package/src/cmp/ReadmeRef.ts +11 -1372
- package/src/sdkgen.ts +2 -1
- package/src/utility.ts +12 -0
- /package/project/.sdk/tm/go/utility/{make_target.go → make_point.go} +0 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
import {
|
|
3
|
+
Model,
|
|
4
|
+
ModelEntity,
|
|
5
|
+
nom,
|
|
3
6
|
depluralize,
|
|
4
7
|
} from '@voxgig/apidef'
|
|
5
8
|
|
|
@@ -8,6 +11,7 @@ import {
|
|
|
8
11
|
File,
|
|
9
12
|
cmp,
|
|
10
13
|
snakify,
|
|
14
|
+
isAuthActive,
|
|
11
15
|
} from '@voxgig/sdkgen'
|
|
12
16
|
|
|
13
17
|
|
|
@@ -51,12 +55,20 @@ function normalizePathParams(
|
|
|
51
55
|
|
|
52
56
|
const TestDirect = cmp(function TestDirect(props: any) {
|
|
53
57
|
const ctx$ = props.ctx$
|
|
54
|
-
const model = ctx$.model
|
|
58
|
+
const model: Model = ctx$.model
|
|
55
59
|
|
|
56
60
|
const target = props.target
|
|
57
|
-
const entity = props.entity
|
|
61
|
+
const entity: ModelEntity = props.entity
|
|
58
62
|
|
|
59
|
-
const PROJECTNAME = model
|
|
63
|
+
const PROJECTNAME = nom(model, 'Name').toUpperCase().replace(/[^A-Z_]/g, '_')
|
|
64
|
+
|
|
65
|
+
const authActive = isAuthActive(model)
|
|
66
|
+
const apikeyEnvEntry = authActive
|
|
67
|
+
? `\n "${PROJECTNAME}_APIKEY": "NONE",`
|
|
68
|
+
: ''
|
|
69
|
+
const apikeyLiveField = authActive
|
|
70
|
+
? `\n "apikey": env.get("${PROJECTNAME}_APIKEY"),`
|
|
71
|
+
: ''
|
|
60
72
|
|
|
61
73
|
const opnames = Object.keys(entity.op)
|
|
62
74
|
const hasLoad = opnames.includes('load')
|
|
@@ -71,13 +83,52 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
71
83
|
|
|
72
84
|
const loadPoint = loadOp?.points?.[0]
|
|
73
85
|
const loadPath = loadPoint ? normalizePathParams(loadPoint.parts || [], loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
74
|
-
const
|
|
86
|
+
const allLoadParams = loadPoint?.args?.params || []
|
|
87
|
+
// Some upstream OpenAPI specs declare a parameter as `in: path` even when
|
|
88
|
+
// that path has no `{name}` placeholder for it. Only path params that
|
|
89
|
+
// actually appear in the URL template should drive direct-test path-param
|
|
90
|
+
// setup and URL-substitution asserts; otherwise the SDK silently drops
|
|
91
|
+
// them and the URL-includes assert fails.
|
|
92
|
+
const _pathPlaceholders = new Set<string>()
|
|
93
|
+
for (const part of (loadPoint?.parts || [])) {
|
|
94
|
+
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
95
|
+
_pathPlaceholders.add(part.slice(1, -1))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const _renameMap = (loadPoint?.rename?.param || {}) as Record<string, string>
|
|
99
|
+
const _renamedPlaceholders = new Set<string>()
|
|
100
|
+
for (const ph of _pathPlaceholders) {
|
|
101
|
+
_renamedPlaceholders.add(ph)
|
|
102
|
+
for (const [orig, renamed] of Object.entries(_renameMap)) {
|
|
103
|
+
if (renamed === ph) _renamedPlaceholders.add(orig)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const loadParams = allLoadParams.filter((p: any) =>
|
|
107
|
+
_renamedPlaceholders.has(p.name) || _renamedPlaceholders.has(p.orig))
|
|
75
108
|
|
|
76
109
|
const listPoint = listOp?.points?.[0]
|
|
77
110
|
const listPath = listPoint ? normalizePathParams(listPoint.parts || [], listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
78
111
|
const listParams = listPoint?.args?.params || []
|
|
79
112
|
|
|
80
|
-
|
|
113
|
+
// Required query params with spec-provided examples — needed in live mode
|
|
114
|
+
// to satisfy API contracts (e.g. /v2018/history requires city/start/end).
|
|
115
|
+
const loadQuery = loadPoint?.args?.query || []
|
|
116
|
+
const loadLiveQueryEntries = loadQuery
|
|
117
|
+
.filter((q: any) => q.reqd && undefined !== q.example && null !== q.example)
|
|
118
|
+
const loadLiveQueryLines = loadLiveQueryEntries
|
|
119
|
+
.map((q: any) => ` query["${q.name}"] = ${JSON.stringify(q.example)}`)
|
|
120
|
+
.join('\n')
|
|
121
|
+
|
|
122
|
+
// Path params with spec-provided examples — when ALL load params have
|
|
123
|
+
// spec examples, prefer them over list-bootstrap.
|
|
124
|
+
const loadAllHaveExamples =
|
|
125
|
+
loadParams.length > 0 &&
|
|
126
|
+
loadParams.every((p: any) => undefined !== p.example && null !== p.example)
|
|
127
|
+
const loadExampleLines = loadAllHaveExamples
|
|
128
|
+
? loadParams.map((p: any) => ` params["${p.name}"] = ${JSON.stringify(p.example)}`).join('\n')
|
|
129
|
+
: ''
|
|
130
|
+
|
|
131
|
+
const entidEnvVar = `${PROJECTNAME}_TEST_${nom(entity, 'NAME').replace(/[^A-Z_]/g, '_')}_ENTID`
|
|
81
132
|
|
|
82
133
|
File({ name: 'test_' + entity.name + '_direct.' + target.ext }, () => {
|
|
83
134
|
|
|
@@ -97,12 +148,33 @@ class Test${entity.Name}Direct:
|
|
|
97
148
|
`)
|
|
98
149
|
|
|
99
150
|
if (hasList && listPoint) {
|
|
151
|
+
// Track idmap keys this list test consumes in live mode.
|
|
152
|
+
const listLiveIdKeys: string[] = listParams.map((lp: any) => {
|
|
153
|
+
return lp.name === 'id'
|
|
154
|
+
? entity.name + '01'
|
|
155
|
+
: lp.name.replace(/_id$/, '') + '01'
|
|
156
|
+
})
|
|
157
|
+
const listSkipBlock = listLiveIdKeys.length > 0
|
|
158
|
+
? ` if setup["live"]:
|
|
159
|
+
for _live_key in [${listLiveIdKeys.map(k => `"${k}"`).join(', ')}]:
|
|
160
|
+
if setup["idmap"].get(_live_key) is None:
|
|
161
|
+
# pytest already imported at module scope
|
|
162
|
+
pytest.skip(f"live test needs {_live_key} via *_ENTID env var (synthetic IDs only)")
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
`
|
|
166
|
+
: ''
|
|
100
167
|
Content(` def test_should_direct_list_${entity.name}(self):
|
|
101
168
|
setup = _${entity.name}_direct_setup([
|
|
102
169
|
{"id": "direct01"},
|
|
103
170
|
{"id": "direct02"},
|
|
104
171
|
])
|
|
105
|
-
|
|
172
|
+
_skip, _reason = runner.is_control_skipped("direct", "direct-list-${entity.name}", "live" if setup["live"] else "unit")
|
|
173
|
+
if _skip:
|
|
174
|
+
# pytest already imported at module scope
|
|
175
|
+
pytest.skip(_reason or "skipped via sdk-test-control.json")
|
|
176
|
+
return
|
|
177
|
+
${listSkipBlock} client = setup["client"]
|
|
106
178
|
|
|
107
179
|
`)
|
|
108
180
|
|
|
@@ -136,11 +208,24 @@ class Test${entity.Name}Direct:
|
|
|
136
208
|
`)
|
|
137
209
|
}
|
|
138
210
|
|
|
139
|
-
Content(`
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
211
|
+
Content(` if setup["live"]:
|
|
212
|
+
# Live mode is lenient: synthetic IDs frequently 4xx and the
|
|
213
|
+
# list-response shape varies wildly across public APIs. Skip
|
|
214
|
+
# rather than fail when the call doesn't return a usable list.
|
|
215
|
+
if err is not None:
|
|
216
|
+
pytest.skip(f"list call failed (likely synthetic IDs against live API): {err}")
|
|
217
|
+
return
|
|
218
|
+
if not result.get("ok"):
|
|
219
|
+
pytest.skip("list call not ok (likely synthetic IDs against live API)")
|
|
220
|
+
return
|
|
221
|
+
status = helpers.to_int(result["status"])
|
|
222
|
+
if status < 200 or status >= 300:
|
|
223
|
+
pytest.skip(f"expected 2xx status, got {status}")
|
|
224
|
+
return
|
|
225
|
+
else:
|
|
226
|
+
assert err is None
|
|
227
|
+
assert result["ok"] is True
|
|
228
|
+
assert helpers.to_int(result["status"]) == 200
|
|
144
229
|
assert isinstance(result["data"], list)
|
|
145
230
|
assert len(result["data"]) == 2
|
|
146
231
|
assert len(setup["calls"]) == 1
|
|
@@ -149,18 +234,58 @@ class Test${entity.Name}Direct:
|
|
|
149
234
|
}
|
|
150
235
|
|
|
151
236
|
if (hasLoad && loadPoint) {
|
|
237
|
+
// Python's direct-load test has no list-bootstrap, so when load path
|
|
238
|
+
// params can't be filled (no spec examples + no override), skip cleanly.
|
|
239
|
+
const loadSkipBlock = (loadParams.length > 0 && !loadAllHaveExamples)
|
|
240
|
+
? ` if setup["live"]:
|
|
241
|
+
# pytest already imported at module scope
|
|
242
|
+
pytest.skip("live direct-load needs real ID — set *_ENTID env var with real IDs to run")
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
`
|
|
246
|
+
: ''
|
|
152
247
|
Content(` def test_should_direct_load_${entity.name}(self):
|
|
153
248
|
setup = _${entity.name}_direct_setup({"id": "direct01"})
|
|
154
|
-
|
|
249
|
+
_skip, _reason = runner.is_control_skipped("direct", "direct-load-${entity.name}", "live" if setup["live"] else "unit")
|
|
250
|
+
if _skip:
|
|
251
|
+
# pytest already imported at module scope
|
|
252
|
+
pytest.skip(_reason or "skipped via sdk-test-control.json")
|
|
253
|
+
return
|
|
254
|
+
${loadSkipBlock} client = setup["client"]
|
|
155
255
|
|
|
156
256
|
`)
|
|
157
257
|
|
|
158
|
-
|
|
258
|
+
const needsQuery = loadParams.length > 0 || loadLiveQueryLines !== ''
|
|
259
|
+
if (needsQuery) {
|
|
159
260
|
Content(` params = {}
|
|
160
|
-
|
|
261
|
+
query = {}
|
|
262
|
+
`)
|
|
263
|
+
if (loadAllHaveExamples) {
|
|
264
|
+
// Use spec-provided path-param examples in live mode.
|
|
265
|
+
Content(` if setup["live"]:
|
|
266
|
+
${loadLiveQueryLines ? loadLiveQueryLines + '\n' : ''}${loadExampleLines}
|
|
267
|
+
else:
|
|
161
268
|
`)
|
|
162
|
-
|
|
163
|
-
|
|
269
|
+
for (let i = 0; i < loadParams.length; i++) {
|
|
270
|
+
Content(` params["${loadParams[i].name}"] = "direct0${i + 1}"
|
|
271
|
+
`)
|
|
272
|
+
}
|
|
273
|
+
} else if (loadParams.length > 0) {
|
|
274
|
+
if (loadLiveQueryLines) {
|
|
275
|
+
Content(` if setup["live"]:
|
|
276
|
+
${loadLiveQueryLines}
|
|
277
|
+
`)
|
|
278
|
+
}
|
|
279
|
+
Content(` if not setup["live"]:
|
|
280
|
+
`)
|
|
281
|
+
for (let i = 0; i < loadParams.length; i++) {
|
|
282
|
+
Content(` params["${loadParams[i].name}"] = "direct0${i + 1}"
|
|
283
|
+
`)
|
|
284
|
+
}
|
|
285
|
+
} else if (loadLiveQueryLines) {
|
|
286
|
+
// Required-query only, no path params.
|
|
287
|
+
Content(` if setup["live"]:
|
|
288
|
+
${loadLiveQueryLines}
|
|
164
289
|
`)
|
|
165
290
|
}
|
|
166
291
|
}
|
|
@@ -170,20 +295,34 @@ class Test${entity.Name}Direct:
|
|
|
170
295
|
"path": "${loadPath}",
|
|
171
296
|
"method": "GET",
|
|
172
297
|
`)
|
|
173
|
-
if (
|
|
298
|
+
if (needsQuery) {
|
|
174
299
|
Content(` "params": params,
|
|
300
|
+
"query": query,
|
|
175
301
|
`)
|
|
176
302
|
} else {
|
|
177
303
|
Content(` "params": {},
|
|
178
304
|
`)
|
|
179
305
|
}
|
|
180
306
|
Content(` })
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
307
|
+
if setup["live"]:
|
|
308
|
+
# Live mode is lenient: synthetic IDs frequently 4xx. Skip
|
|
309
|
+
# rather than fail when the load endpoint isn't reachable
|
|
310
|
+
# with the IDs we can construct from setup.idmap.
|
|
311
|
+
if err is not None:
|
|
312
|
+
pytest.skip(f"load call failed (likely synthetic IDs against live API): {err}")
|
|
313
|
+
return
|
|
314
|
+
if not result.get("ok"):
|
|
315
|
+
pytest.skip("load call not ok (likely synthetic IDs against live API)")
|
|
316
|
+
return
|
|
317
|
+
status = helpers.to_int(result["status"])
|
|
318
|
+
if status < 200 or status >= 300:
|
|
319
|
+
pytest.skip(f"expected 2xx status, got {status}")
|
|
320
|
+
return
|
|
321
|
+
else:
|
|
322
|
+
assert err is None
|
|
323
|
+
assert result["ok"] is True
|
|
324
|
+
assert helpers.to_int(result["status"]) == 200
|
|
325
|
+
assert result["data"] is not None
|
|
187
326
|
if isinstance(result["data"], dict):
|
|
188
327
|
assert result["data"]["id"] == "direct01"
|
|
189
328
|
assert len(setup["calls"]) == 1
|
|
@@ -200,15 +339,13 @@ def _${entity.name}_direct_setup(mockres):
|
|
|
200
339
|
|
|
201
340
|
env = runner.env_override({
|
|
202
341
|
"${entidEnvVar}": {},
|
|
203
|
-
"${PROJECTNAME}_TEST_LIVE": "FALSE"
|
|
204
|
-
"${PROJECTNAME}_APIKEY": "NONE",
|
|
342
|
+
"${PROJECTNAME}_TEST_LIVE": "FALSE",${apikeyEnvEntry}
|
|
205
343
|
})
|
|
206
344
|
|
|
207
345
|
live = env.get("${PROJECTNAME}_TEST_LIVE") == "TRUE"
|
|
208
346
|
|
|
209
347
|
if live:
|
|
210
|
-
merged_opts = {
|
|
211
|
-
"apikey": env.get("${PROJECTNAME}_APIKEY"),
|
|
348
|
+
merged_opts = {${apikeyLiveField}
|
|
212
349
|
}
|
|
213
350
|
client = ${model.const.Name}SDK(merged_opts)
|
|
214
351
|
return {
|
|
@@ -7,7 +7,12 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
KIT,
|
|
10
|
+
Model,
|
|
11
|
+
ModelEntity,
|
|
12
|
+
ModelEntityFlow,
|
|
13
|
+
ModelEntityFlowStep,
|
|
10
14
|
getModelPath,
|
|
15
|
+
nom,
|
|
11
16
|
} from '@voxgig/apidef'
|
|
12
17
|
|
|
13
18
|
|
|
@@ -18,34 +23,47 @@ import {
|
|
|
18
23
|
each,
|
|
19
24
|
buildIdNames,
|
|
20
25
|
getMatchEntries,
|
|
26
|
+
isAuthActive,
|
|
21
27
|
} from '@voxgig/sdkgen'
|
|
22
28
|
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
// See TestEntity_ts.ts for the GenCtx/OpGen contract.
|
|
26
31
|
type GenCtx = {
|
|
27
|
-
model:
|
|
28
|
-
entity:
|
|
29
|
-
flow:
|
|
32
|
+
model: Model
|
|
33
|
+
entity: ModelEntity
|
|
34
|
+
flow: ModelEntityFlow
|
|
30
35
|
PROJUPPER: string
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
type OpGen = (ctx: GenCtx, step: ModelEntityFlowStep, index: number) => void
|
|
39
|
+
|
|
33
40
|
|
|
34
41
|
const TestEntity = cmp(function TestEntity(props: any) {
|
|
35
42
|
const ctx$ = props.ctx$
|
|
36
|
-
const model = ctx$.model
|
|
43
|
+
const model: Model = ctx$.model
|
|
37
44
|
|
|
38
45
|
const target = props.target
|
|
39
|
-
const entity = props.entity
|
|
46
|
+
const entity: ModelEntity = props.entity
|
|
40
47
|
|
|
41
|
-
const basicflow
|
|
42
|
-
|
|
48
|
+
const basicflow: ModelEntityFlow | undefined =
|
|
49
|
+
getModelPath(model, `main.${KIT}.flow.Basic${nom(entity, 'Name')}Flow`)
|
|
43
50
|
|
|
44
|
-
|
|
51
|
+
// No flow or flow inactive — nothing to generate. The narrowed-form
|
|
52
|
+
// check (rather than `if (!dobasic)`) is what lets TS know `basicflow`
|
|
53
|
+
// is non-null in the rest of the cmp body.
|
|
54
|
+
if (null == basicflow || true !== basicflow.active) {
|
|
45
55
|
return
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
const PROJUPPER = model.const
|
|
58
|
+
const PROJUPPER = nom(model.const, 'Name').toUpperCase().replace(/[^A-Z_]/g, '_')
|
|
59
|
+
|
|
60
|
+
const authActive = isAuthActive(model)
|
|
61
|
+
const apikeyEnvEntry = authActive
|
|
62
|
+
? `\n "${PROJUPPER}_APIKEY": "NONE",`
|
|
63
|
+
: ''
|
|
64
|
+
const apikeyLiveField = authActive
|
|
65
|
+
? `\n "apikey": env.get("${PROJUPPER}_APIKEY"),`
|
|
66
|
+
: ''
|
|
49
67
|
|
|
50
68
|
const idnames = buildIdNames(entity, basicflow)
|
|
51
69
|
const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
|
|
@@ -86,6 +104,20 @@ class Test${entity.Name}Entity:
|
|
|
86
104
|
|
|
87
105
|
def test_should_run_basic_flow(self):
|
|
88
106
|
setup = _${entity.name}_basic_setup(None)
|
|
107
|
+
# Per-op sdk-test-control.json skip — basic test exercises a flow with
|
|
108
|
+
# multiple ops; skipping any one skips the whole flow (steps depend
|
|
109
|
+
# on each other).
|
|
110
|
+
_live = setup.get("live", False)
|
|
111
|
+
for _op in [${(Array.from(new Set((basicflow.step as any[]).map((s: any) => s.op).filter(Boolean)))).map(o => `"${o}"`).join(', ')}]:
|
|
112
|
+
_skip, _reason = runner.is_control_skipped("entityOp", "${entity.name}." + _op, "live" if _live else "unit")
|
|
113
|
+
if _skip:
|
|
114
|
+
pytest.skip(_reason or "skipped via sdk-test-control.json")
|
|
115
|
+
return
|
|
116
|
+
# The basic flow consumes synthetic IDs from the fixture. In live mode
|
|
117
|
+
# without an *_ENTID env override, those IDs hit the live API and 4xx.
|
|
118
|
+
if setup.get("synthetic_only"):
|
|
119
|
+
pytest.skip("live entity test uses synthetic IDs from fixture — "
|
|
120
|
+
"set ${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID JSON to run live")
|
|
89
121
|
client = setup["client"]
|
|
90
122
|
|
|
91
123
|
`)
|
|
@@ -144,11 +176,17 @@ def _${entity.name}_basic_setup(extra):
|
|
|
144
176
|
|
|
145
177
|
`)
|
|
146
178
|
|
|
147
|
-
Content(` env
|
|
179
|
+
Content(` # Detect ENTID env override before envOverride consumes it. When live
|
|
180
|
+
# mode is on without a real override, the basic test runs against synthetic
|
|
181
|
+
# IDs from the fixture and 4xx's. We surface this so the test can skip.
|
|
182
|
+
_entid_env_raw = os.environ.get(
|
|
183
|
+
"${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID")
|
|
184
|
+
_idmap_overridden = _entid_env_raw is not None and _entid_env_raw.strip().startswith("{")
|
|
185
|
+
|
|
186
|
+
env = runner.env_override({
|
|
148
187
|
"${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID": idmap,
|
|
149
188
|
"${PROJUPPER}_TEST_LIVE": "FALSE",
|
|
150
|
-
"${PROJUPPER}_TEST_EXPLAIN": "FALSE"
|
|
151
|
-
"${PROJUPPER}_APIKEY": "NONE",
|
|
189
|
+
"${PROJUPPER}_TEST_EXPLAIN": "FALSE",${apikeyEnvEntry}
|
|
152
190
|
})
|
|
153
191
|
|
|
154
192
|
idmap_resolved = helpers.to_map(
|
|
@@ -167,19 +205,21 @@ def _${entity.name}_basic_setup(extra):
|
|
|
167
205
|
Content(`
|
|
168
206
|
if env.get("${PROJUPPER}_TEST_LIVE") == "TRUE":
|
|
169
207
|
merged_opts = vs.merge([
|
|
170
|
-
{
|
|
171
|
-
"apikey": env.get("${PROJUPPER}_APIKEY"),
|
|
208
|
+
{${apikeyLiveField}
|
|
172
209
|
},
|
|
173
210
|
extra or {},
|
|
174
211
|
])
|
|
175
212
|
client = ${model.const.Name}SDK(helpers.to_map(merged_opts))
|
|
176
213
|
|
|
214
|
+
_live = env.get("${PROJUPPER}_TEST_LIVE") == "TRUE"
|
|
177
215
|
return {
|
|
178
216
|
"client": client,
|
|
179
217
|
"data": entity_data,
|
|
180
218
|
"idmap": idmap_resolved,
|
|
181
219
|
"env": env,
|
|
182
220
|
"explain": env.get("${PROJUPPER}_TEST_EXPLAIN") == "TRUE",
|
|
221
|
+
"live": _live,
|
|
222
|
+
"synthetic_only": _live and not _idmap_overridden,
|
|
183
223
|
"now": int(time.time() * 1000),
|
|
184
224
|
}
|
|
185
225
|
`)
|
|
@@ -189,9 +229,9 @@ def _${entity.name}_basic_setup(extra):
|
|
|
189
229
|
|
|
190
230
|
const generateCreate: OpGen = (ctx, step, index) => {
|
|
191
231
|
const { entity, flow } = ctx
|
|
192
|
-
const ref = step.input
|
|
193
|
-
const entvar = step.input
|
|
194
|
-
const datavar = step.input
|
|
232
|
+
const ref = step.input.ref ?? entity.name + '_ref01'
|
|
233
|
+
const entvar = step.input.entvar ?? ref + '_ent'
|
|
234
|
+
const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
195
235
|
|
|
196
236
|
const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
|
|
197
237
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
@@ -199,8 +239,8 @@ const generateCreate: OpGen = (ctx, step, index) => {
|
|
|
199
239
|
|
|
200
240
|
const hasDatvar = priorSteps.some((s: any) => {
|
|
201
241
|
if ('create' === s.op) {
|
|
202
|
-
const priorRef = s.input
|
|
203
|
-
const priorDatvar = s.input
|
|
242
|
+
const priorRef = s.input.ref ?? entity.name + '_ref01'
|
|
243
|
+
const priorDatvar = s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? ''))
|
|
204
244
|
return priorDatvar === datavar
|
|
205
245
|
}
|
|
206
246
|
return false
|
|
@@ -229,22 +269,27 @@ const generateCreate: OpGen = (ctx, step, index) => {
|
|
|
229
269
|
`)
|
|
230
270
|
}
|
|
231
271
|
|
|
272
|
+
const hasEntIdC = null != ctx.entity.id
|
|
273
|
+
|
|
232
274
|
Content(`
|
|
233
275
|
${datavar}_result, err = ${entvar}.create(${datavar}, None)
|
|
234
276
|
assert err is None
|
|
235
277
|
${datavar} = helpers.to_map(${datavar}_result)
|
|
236
278
|
assert ${datavar} is not None
|
|
237
|
-
assert ${datavar}["id"] is not None
|
|
238
279
|
`)
|
|
280
|
+
if (hasEntIdC) {
|
|
281
|
+
Content(` assert ${datavar}["id"] is not None
|
|
282
|
+
`)
|
|
283
|
+
}
|
|
239
284
|
}
|
|
240
285
|
|
|
241
286
|
|
|
242
287
|
const generateList: OpGen = (ctx, step, index) => {
|
|
243
288
|
const { entity, flow } = ctx
|
|
244
|
-
const ref = step.input
|
|
245
|
-
const entvar = step.input
|
|
246
|
-
const matchvar = step.input
|
|
247
|
-
const listvar = step.input
|
|
289
|
+
const ref = step.input.ref ?? entity.name + '_ref01'
|
|
290
|
+
const entvar = step.input.entvar ?? ref + '_ent'
|
|
291
|
+
const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
|
|
292
|
+
const listvar = step.input.listvar ?? (ref + '_list' + (step.input.suffix ?? ''))
|
|
248
293
|
|
|
249
294
|
const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
|
|
250
295
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
@@ -284,7 +329,7 @@ const generateList: OpGen = (ctx, step, index) => {
|
|
|
284
329
|
for (const validator of step.valid) {
|
|
285
330
|
const validRef = validator.def?.ref
|
|
286
331
|
const hasRefData = validRef && allSteps.some((s: any) => 'create' === s.op &&
|
|
287
|
-
((s.input
|
|
332
|
+
((s.input.ref ?? entity.name + '_ref01') === validRef))
|
|
288
333
|
|
|
289
334
|
if ('ItemExists' === validator.apply && hasRefData) {
|
|
290
335
|
const refDataVar = validRef + '_data'
|
|
@@ -310,17 +355,19 @@ const generateList: OpGen = (ctx, step, index) => {
|
|
|
310
355
|
|
|
311
356
|
const generateUpdate: OpGen = (ctx, step, index) => {
|
|
312
357
|
const { entity, flow } = ctx
|
|
313
|
-
const ref = step.input
|
|
314
|
-
const entvar = step.input
|
|
315
|
-
const datavar = step.input
|
|
316
|
-
const resdatavar = step.input
|
|
317
|
-
const markdefvar = step.input
|
|
318
|
-
const srcdatavar = step.input
|
|
358
|
+
const ref = step.input.ref ?? entity.name + '_ref01'
|
|
359
|
+
const entvar = step.input.entvar ?? ref + '_ent'
|
|
360
|
+
const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
361
|
+
const resdatavar = step.input.resdatavar ?? (ref + '_resdata' + (step.input.suffix ?? ''))
|
|
362
|
+
const markdefvar = step.input.markdefvar ?? (ref + '_markdef' + (step.input.suffix ?? ''))
|
|
363
|
+
const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
319
364
|
|
|
320
365
|
const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
|
|
321
366
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
322
367
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
323
368
|
|
|
369
|
+
const hasEntIdU = null != entity.id
|
|
370
|
+
|
|
324
371
|
Content(` # UPDATE
|
|
325
372
|
`)
|
|
326
373
|
if (needsEnt) {
|
|
@@ -328,8 +375,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
|
|
|
328
375
|
`)
|
|
329
376
|
}
|
|
330
377
|
Content(` ${datavar}_up = {
|
|
331
|
-
"id": ${srcdatavar}["id"],
|
|
332
378
|
`)
|
|
379
|
+
if (hasEntIdU) {
|
|
380
|
+
Content(` "id": ${srcdatavar}["id"],
|
|
381
|
+
`)
|
|
382
|
+
}
|
|
333
383
|
|
|
334
384
|
if (step.data) {
|
|
335
385
|
const dataEntries = Object.entries(step.data).filter(([k]: any) => k !== 'id' && !k.endsWith('$'))
|
|
@@ -344,7 +394,7 @@ const generateUpdate: OpGen = (ctx, step, index) => {
|
|
|
344
394
|
|
|
345
395
|
if (step.spec) {
|
|
346
396
|
for (const spec of step.spec) {
|
|
347
|
-
if ('TextFieldMark' === spec.apply && null != step.input
|
|
397
|
+
if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
|
|
348
398
|
const fieldname = step.input.textfield
|
|
349
399
|
const fieldvalue = spec.def?.mark ?? `Mark01-${ref}`
|
|
350
400
|
Content(`
|
|
@@ -361,12 +411,15 @@ const generateUpdate: OpGen = (ctx, step, index) => {
|
|
|
361
411
|
assert err is None
|
|
362
412
|
${resdatavar} = helpers.to_map(${resdatavar}_result)
|
|
363
413
|
assert ${resdatavar} is not None
|
|
364
|
-
assert ${resdatavar}["id"] == ${datavar}_up["id"]
|
|
365
414
|
`)
|
|
415
|
+
if (hasEntIdU) {
|
|
416
|
+
Content(` assert ${resdatavar}["id"] == ${datavar}_up["id"]
|
|
417
|
+
`)
|
|
418
|
+
}
|
|
366
419
|
|
|
367
420
|
if (step.spec) {
|
|
368
421
|
for (const spec of step.spec) {
|
|
369
|
-
if ('TextFieldMark' === spec.apply && null != step.input
|
|
422
|
+
if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
|
|
370
423
|
Content(` assert ${resdatavar}[${markdefvar}_name] == ${markdefvar}_value
|
|
371
424
|
`)
|
|
372
425
|
}
|
|
@@ -377,11 +430,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
|
|
|
377
430
|
|
|
378
431
|
const generateLoad: OpGen = (ctx, step, index) => {
|
|
379
432
|
const { entity, flow } = ctx
|
|
380
|
-
const ref = step.input
|
|
381
|
-
const entvar = step.input
|
|
382
|
-
const matchvar = step.input
|
|
383
|
-
const datavar = step.input
|
|
384
|
-
const srcdatavar = step.input
|
|
433
|
+
const ref = step.input.ref ?? entity.name + '_ref01'
|
|
434
|
+
const entvar = step.input.entvar ?? ref + '_ent'
|
|
435
|
+
const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
|
|
436
|
+
const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
437
|
+
const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
385
438
|
|
|
386
439
|
const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
|
|
387
440
|
const hasEntVar = priorSteps.some((s: any) =>
|
|
@@ -392,20 +445,22 @@ const generateLoad: OpGen = (ctx, step, index) => {
|
|
|
392
445
|
const hasSrcData = (!flowHasCreate && srcdatavar === (preambleRef + '_data')) ||
|
|
393
446
|
priorSteps.some((s: any) => {
|
|
394
447
|
if ('create' === s.op) {
|
|
395
|
-
const priorRef = s.input
|
|
396
|
-
const priorDatvar = s.input
|
|
448
|
+
const priorRef = s.input.ref ?? entity.name + '_ref01'
|
|
449
|
+
const priorDatvar = s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? ''))
|
|
397
450
|
return priorDatvar === srcdatavar
|
|
398
451
|
}
|
|
399
452
|
return false
|
|
400
453
|
})
|
|
401
454
|
|
|
455
|
+
const hasEntId = null != entity.id
|
|
456
|
+
|
|
402
457
|
Content(` # LOAD
|
|
403
458
|
`)
|
|
404
459
|
if (!hasEntVar) {
|
|
405
460
|
Content(` ${entvar} = client.${entity.Name}(None)
|
|
406
461
|
`)
|
|
407
462
|
}
|
|
408
|
-
if (!hasSrcData) {
|
|
463
|
+
if (!hasSrcData && hasEntId) {
|
|
409
464
|
Content(` ${srcdatavar}_raw = vs.items(helpers.to_map(
|
|
410
465
|
vs.getpath(setup["data"], "existing.${entity.name}")))
|
|
411
466
|
${srcdatavar} = None
|
|
@@ -413,7 +468,8 @@ const generateLoad: OpGen = (ctx, step, index) => {
|
|
|
413
468
|
${srcdatavar} = helpers.to_map(${srcdatavar}_raw[0][1])
|
|
414
469
|
`)
|
|
415
470
|
}
|
|
416
|
-
|
|
471
|
+
if (hasEntId) {
|
|
472
|
+
Content(` ${matchvar} = {
|
|
417
473
|
"id": ${srcdatavar}["id"],
|
|
418
474
|
}
|
|
419
475
|
${datavar}_loaded, err = ${entvar}.load(${matchvar}, None)
|
|
@@ -422,32 +478,50 @@ const generateLoad: OpGen = (ctx, step, index) => {
|
|
|
422
478
|
assert ${datavar}_load_result is not None
|
|
423
479
|
assert ${datavar}_load_result["id"] == ${srcdatavar}["id"]
|
|
424
480
|
`)
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
Content(` ${matchvar} = {}
|
|
484
|
+
${datavar}_loaded, err = ${entvar}.load(${matchvar}, None)
|
|
485
|
+
assert err is None
|
|
486
|
+
assert ${datavar}_loaded is not None
|
|
487
|
+
`)
|
|
488
|
+
}
|
|
425
489
|
}
|
|
426
490
|
|
|
427
491
|
|
|
428
492
|
const generateRemove: OpGen = (ctx, step, index) => {
|
|
429
493
|
const { entity, flow } = ctx
|
|
430
|
-
const ref = step.input
|
|
431
|
-
const entvar = step.input
|
|
432
|
-
const matchvar = step.input
|
|
433
|
-
const srcdatavar = step.input
|
|
494
|
+
const ref = step.input.ref ?? entity.name + '_ref01'
|
|
495
|
+
const entvar = step.input.entvar ?? ref + '_ent'
|
|
496
|
+
const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
|
|
497
|
+
const srcdatavar = step.input.srcdatavar ?? (ref + '_data')
|
|
434
498
|
|
|
435
499
|
const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
|
|
436
500
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
437
501
|
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
438
502
|
|
|
503
|
+
const hasEntIdR = null != entity.id
|
|
504
|
+
|
|
439
505
|
Content(` # REMOVE
|
|
440
506
|
`)
|
|
441
507
|
if (needsEnt) {
|
|
442
508
|
Content(` ${entvar} = client.${entity.Name}(None)
|
|
443
509
|
`)
|
|
444
510
|
}
|
|
445
|
-
|
|
511
|
+
if (hasEntIdR) {
|
|
512
|
+
Content(` ${matchvar} = {
|
|
446
513
|
"id": ${srcdatavar}["id"],
|
|
447
514
|
}
|
|
448
515
|
_, err = ${entvar}.remove(${matchvar}, None)
|
|
449
516
|
assert err is None
|
|
450
517
|
`)
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
Content(` ${matchvar} = {}
|
|
521
|
+
_, err = ${entvar}.remove(${matchvar}, None)
|
|
522
|
+
assert err is None
|
|
523
|
+
`)
|
|
524
|
+
}
|
|
451
525
|
}
|
|
452
526
|
|
|
453
527
|
|