Skip to content

Commit 30e27be

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add subtest for synthetics multistep tests (#3347)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 47b0464 commit 30e27be

File tree

9 files changed

+846
-4
lines changed

9 files changed

+846
-4
lines changed

.generator/schemas/v1/openapi.yaml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14766,6 +14766,61 @@ components:
1476614766
oneOf:
1476714767
- $ref: '#/components/schemas/SyntheticsAPITestStep'
1476814768
- $ref: '#/components/schemas/SyntheticsAPIWaitStep'
14769+
- $ref: '#/components/schemas/SyntheticsAPISubtestStep'
14770+
SyntheticsAPISubtestStep:
14771+
description: The subtest step used in a Synthetics multi-step API test.
14772+
properties:
14773+
allowFailure:
14774+
description: Determines whether or not to continue with test if this step
14775+
fails.
14776+
type: boolean
14777+
alwaysExecute:
14778+
description: A boolean set to always execute this step even if the previous
14779+
step failed or was skipped.
14780+
type: boolean
14781+
exitIfSucceed:
14782+
description: Determines whether or not to exit the test if the step succeeds.
14783+
type: boolean
14784+
extractedValuesFromScript:
14785+
description: Generate variables using JavaScript.
14786+
type: string
14787+
id:
14788+
description: ID of the step.
14789+
example: abc-def-123
14790+
readOnly: true
14791+
type: string
14792+
isCritical:
14793+
description: 'Determines whether or not to consider the entire test as failed
14794+
if this step fails.
14795+
14796+
Can be used only if `allowFailure` is `true`.'
14797+
type: boolean
14798+
name:
14799+
description: The name of the step.
14800+
example: Example step name
14801+
type: string
14802+
retry:
14803+
$ref: '#/components/schemas/SyntheticsTestOptionsRetry'
14804+
subtestPublicId:
14805+
description: Public ID of the test to be played as part of a `playSubTest`
14806+
step type.
14807+
example: ''
14808+
type: string
14809+
subtype:
14810+
$ref: '#/components/schemas/SyntheticsAPISubtestStepSubtype'
14811+
required:
14812+
- name
14813+
- subtype
14814+
- subtestPublicId
14815+
type: object
14816+
SyntheticsAPISubtestStepSubtype:
14817+
description: The subtype of the Synthetic multi-step API subtest step.
14818+
enum:
14819+
- playSubTest
14820+
example: playSubTest
14821+
type: string
14822+
x-enum-varnames:
14823+
- PLAY_SUB_TEST
1476914824
SyntheticsAPITest:
1477014825
description: Object containing details about a Synthetic API test.
1477114826
properties:
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Create a multistep test with subtest returns "OK" response
2+
3+
import com.datadog.api.client.ApiClient;
4+
import com.datadog.api.client.ApiException;
5+
import com.datadog.api.client.v1.api.SyntheticsApi;
6+
import com.datadog.api.client.v1.model.SyntheticsAPIStep;
7+
import com.datadog.api.client.v1.model.SyntheticsAPISubtestStep;
8+
import com.datadog.api.client.v1.model.SyntheticsAPISubtestStepSubtype;
9+
import com.datadog.api.client.v1.model.SyntheticsAPITest;
10+
import com.datadog.api.client.v1.model.SyntheticsAPITestConfig;
11+
import com.datadog.api.client.v1.model.SyntheticsAPITestStep;
12+
import com.datadog.api.client.v1.model.SyntheticsAPITestStepSubtype;
13+
import com.datadog.api.client.v1.model.SyntheticsAPITestType;
14+
import com.datadog.api.client.v1.model.SyntheticsAssertion;
15+
import com.datadog.api.client.v1.model.SyntheticsAssertionOperator;
16+
import com.datadog.api.client.v1.model.SyntheticsAssertionTarget;
17+
import com.datadog.api.client.v1.model.SyntheticsAssertionTargetValue;
18+
import com.datadog.api.client.v1.model.SyntheticsAssertionType;
19+
import com.datadog.api.client.v1.model.SyntheticsBasicAuth;
20+
import com.datadog.api.client.v1.model.SyntheticsBasicAuthWeb;
21+
import com.datadog.api.client.v1.model.SyntheticsTestDetailsSubType;
22+
import com.datadog.api.client.v1.model.SyntheticsTestOptions;
23+
import com.datadog.api.client.v1.model.SyntheticsTestRequest;
24+
import java.util.Arrays;
25+
import java.util.Collections;
26+
27+
public class Example {
28+
public static void main(String[] args) {
29+
ApiClient defaultClient = ApiClient.getDefaultApiClient();
30+
SyntheticsApi apiInstance = new SyntheticsApi(defaultClient);
31+
32+
// there is a valid "synthetics_api_test" in the system
33+
String SYNTHETICS_API_TEST_PUBLIC_ID = System.getenv("SYNTHETICS_API_TEST_PUBLIC_ID");
34+
35+
SyntheticsAPITest body =
36+
new SyntheticsAPITest()
37+
.config(
38+
new SyntheticsAPITestConfig()
39+
.steps(
40+
Arrays.asList(
41+
new SyntheticsAPIStep(
42+
new SyntheticsAPITestStep()
43+
.assertions(
44+
Collections.singletonList(
45+
new SyntheticsAssertion(
46+
new SyntheticsAssertionTarget()
47+
.operator(SyntheticsAssertionOperator.IS)
48+
.type(SyntheticsAssertionType.STATUS_CODE)
49+
.target(
50+
new SyntheticsAssertionTargetValue(
51+
200.0)))))
52+
.name("request is sent")
53+
.request(
54+
new SyntheticsTestRequest()
55+
.url("https://httpbin.org/status/200")
56+
.method("GET")
57+
.basicAuth(
58+
new SyntheticsBasicAuth(
59+
new SyntheticsBasicAuthWeb()
60+
.password("password")
61+
.username("username"))))
62+
.subtype(SyntheticsAPITestStepSubtype.HTTP)),
63+
new SyntheticsAPIStep(
64+
new SyntheticsAPISubtestStep()
65+
.subtype(SyntheticsAPISubtestStepSubtype.PLAY_SUB_TEST)
66+
.subtestPublicId(SYNTHETICS_API_TEST_PUBLIC_ID)
67+
.name("subtest step")))))
68+
.locations(Collections.singletonList("aws:us-east-2"))
69+
.message("BDD test payload: synthetics_api_test_multi_step_with_subtest.json")
70+
.name("Example-Synthetic")
71+
.options(new SyntheticsTestOptions().tickEvery(60L))
72+
.subtype(SyntheticsTestDetailsSubType.MULTI)
73+
.type(SyntheticsAPITestType.API);
74+
75+
try {
76+
SyntheticsAPITest result = apiInstance.createSyntheticsAPITest(body);
77+
System.out.println(result);
78+
} catch (ApiException e) {
79+
System.err.println("Exception when calling SyntheticsApi#createSyntheticsAPITest");
80+
System.err.println("Status code: " + e.getCode());
81+
System.err.println("Reason: " + e.getResponseBody());
82+
System.err.println("Response headers: " + e.getResponseHeaders());
83+
e.printStackTrace();
84+
}
85+
}
86+
}

src/main/java/com/datadog/api/client/v1/model/SyntheticsAPIStep.java

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,51 @@ public SyntheticsAPIStep deserialize(JsonParser jp, DeserializationContext ctxt)
167167
log.log(Level.FINER, "Input data does not match schema 'SyntheticsAPIWaitStep'", e);
168168
}
169169

170+
// deserialize SyntheticsAPISubtestStep
171+
try {
172+
boolean attemptParsing = true;
173+
// ensure that we respect type coercion as set on the client ObjectMapper
174+
if (SyntheticsAPISubtestStep.class.equals(Integer.class)
175+
|| SyntheticsAPISubtestStep.class.equals(Long.class)
176+
|| SyntheticsAPISubtestStep.class.equals(Float.class)
177+
|| SyntheticsAPISubtestStep.class.equals(Double.class)
178+
|| SyntheticsAPISubtestStep.class.equals(Boolean.class)
179+
|| SyntheticsAPISubtestStep.class.equals(String.class)) {
180+
attemptParsing = typeCoercion;
181+
if (!attemptParsing) {
182+
attemptParsing |=
183+
((SyntheticsAPISubtestStep.class.equals(Integer.class)
184+
|| SyntheticsAPISubtestStep.class.equals(Long.class))
185+
&& token == JsonToken.VALUE_NUMBER_INT);
186+
attemptParsing |=
187+
((SyntheticsAPISubtestStep.class.equals(Float.class)
188+
|| SyntheticsAPISubtestStep.class.equals(Double.class))
189+
&& (token == JsonToken.VALUE_NUMBER_FLOAT
190+
|| token == JsonToken.VALUE_NUMBER_INT));
191+
attemptParsing |=
192+
(SyntheticsAPISubtestStep.class.equals(Boolean.class)
193+
&& (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE));
194+
attemptParsing |=
195+
(SyntheticsAPISubtestStep.class.equals(String.class)
196+
&& token == JsonToken.VALUE_STRING);
197+
}
198+
}
199+
if (attemptParsing) {
200+
tmp = tree.traverse(jp.getCodec()).readValueAs(SyntheticsAPISubtestStep.class);
201+
// TODO: there is no validation against JSON schema constraints
202+
// (min, max, enum, pattern...), this does not perform a strict JSON
203+
// validation, which means the 'match' count may be higher than it should be.
204+
if (!((SyntheticsAPISubtestStep) tmp).unparsed) {
205+
deserialized = tmp;
206+
match++;
207+
}
208+
log.log(Level.FINER, "Input data matches schema 'SyntheticsAPISubtestStep'");
209+
}
210+
} catch (Exception e) {
211+
// deserialization failed, continue
212+
log.log(Level.FINER, "Input data does not match schema 'SyntheticsAPISubtestStep'", e);
213+
}
214+
170215
SyntheticsAPIStep ret = new SyntheticsAPIStep();
171216
if (match == 1) {
172217
ret.setActualInstance(deserialized);
@@ -205,9 +250,15 @@ public SyntheticsAPIStep(SyntheticsAPIWaitStep o) {
205250
setActualInstance(o);
206251
}
207252

253+
public SyntheticsAPIStep(SyntheticsAPISubtestStep o) {
254+
super("oneOf", Boolean.FALSE);
255+
setActualInstance(o);
256+
}
257+
208258
static {
209259
schemas.put("SyntheticsAPITestStep", new GenericType<SyntheticsAPITestStep>() {});
210260
schemas.put("SyntheticsAPIWaitStep", new GenericType<SyntheticsAPIWaitStep>() {});
261+
schemas.put("SyntheticsAPISubtestStep", new GenericType<SyntheticsAPISubtestStep>() {});
211262
JSON.registerDescendants(SyntheticsAPIStep.class, Collections.unmodifiableMap(schemas));
212263
}
213264

@@ -218,7 +269,8 @@ public Map<String, GenericType> getSchemas() {
218269

219270
/**
220271
* Set the instance that matches the oneOf child schema, check the instance parameter is valid
221-
* against the oneOf child schemas: SyntheticsAPITestStep, SyntheticsAPIWaitStep
272+
* against the oneOf child schemas: SyntheticsAPITestStep, SyntheticsAPIWaitStep,
273+
* SyntheticsAPISubtestStep
222274
*
223275
* <p>It could be an instance of the 'oneOf' schemas. The oneOf child schemas may themselves be a
224276
* composed schema (allOf, anyOf, oneOf).
@@ -233,20 +285,26 @@ public void setActualInstance(Object instance) {
233285
super.setActualInstance(instance);
234286
return;
235287
}
288+
if (JSON.isInstanceOf(SyntheticsAPISubtestStep.class, instance, new HashSet<Class<?>>())) {
289+
super.setActualInstance(instance);
290+
return;
291+
}
236292

237293
if (JSON.isInstanceOf(UnparsedObject.class, instance, new HashSet<Class<?>>())) {
238294
super.setActualInstance(instance);
239295
return;
240296
}
241297
throw new RuntimeException(
242-
"Invalid instance type. Must be SyntheticsAPITestStep, SyntheticsAPIWaitStep");
298+
"Invalid instance type. Must be SyntheticsAPITestStep, SyntheticsAPIWaitStep,"
299+
+ " SyntheticsAPISubtestStep");
243300
}
244301

245302
/**
246303
* Get the actual instance, which can be the following: SyntheticsAPITestStep,
247-
* SyntheticsAPIWaitStep
304+
* SyntheticsAPIWaitStep, SyntheticsAPISubtestStep
248305
*
249-
* @return The actual instance (SyntheticsAPITestStep, SyntheticsAPIWaitStep)
306+
* @return The actual instance (SyntheticsAPITestStep, SyntheticsAPIWaitStep,
307+
* SyntheticsAPISubtestStep)
250308
*/
251309
@Override
252310
public Object getActualInstance() {
@@ -274,4 +332,15 @@ public SyntheticsAPITestStep getSyntheticsAPITestStep() throws ClassCastExceptio
274332
public SyntheticsAPIWaitStep getSyntheticsAPIWaitStep() throws ClassCastException {
275333
return (SyntheticsAPIWaitStep) super.getActualInstance();
276334
}
335+
336+
/**
337+
* Get the actual instance of `SyntheticsAPISubtestStep`. If the actual instance is not
338+
* `SyntheticsAPISubtestStep`, the ClassCastException will be thrown.
339+
*
340+
* @return The actual instance of `SyntheticsAPISubtestStep`
341+
* @throws ClassCastException if the instance is not `SyntheticsAPISubtestStep`
342+
*/
343+
public SyntheticsAPISubtestStep getSyntheticsAPISubtestStep() throws ClassCastException {
344+
return (SyntheticsAPISubtestStep) super.getActualInstance();
345+
}
277346
}

0 commit comments

Comments
 (0)