diff --git a/.apigentools-info b/.apigentools-info index ae68541e5..7699c240d 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.6.6", - "regenerated": "2024-04-04 19:22:22.135102", - "spec_repo_commit": "fd06108d" + "regenerated": "2024-04-05 17:05:09.050525", + "spec_repo_commit": "9b7c8967" }, "v2": { "apigentools_version": "1.6.6", - "regenerated": "2024-04-04 19:22:22.154344", - "spec_repo_commit": "fd06108d" + "regenerated": "2024-04-05 17:05:09.094275", + "spec_repo_commit": "9b7c8967" } } } \ No newline at end of file diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index 228f29336..e08c005f4 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -15871,6 +15871,11 @@ components: maximum: 65535 minimum: 1 type: integer + files: + description: Files to be used as part of the request in the test. + items: + $ref: '#/components/schemas/SyntheticsTestRequestBodyFile' + type: array follow_redirects: description: Specifies whether or not the request follows redirects. type: boolean @@ -15937,6 +15942,32 @@ components: example: https://example.com type: string type: object + SyntheticsTestRequestBodyFile: + description: Object describing a file to be used as part of the request in the + test. + properties: + bucketKey: + description: Bucket key of the file. + type: string + content: + description: Content of the file. + maxLength: 3145728 + type: string + name: + description: Name of the file. + maxLength: 1500 + type: string + size: + description: Size of the file. + format: int64 + maximum: 3145728 + minimum: 1 + type: integer + type: + description: Type of the file. + maxLength: 1500 + type: string + type: object SyntheticsTestRequestBodyType: description: Type of the request body. enum: @@ -15946,6 +15977,8 @@ components: - text/html - application/x-www-form-urlencoded - graphql + - application/octet-stream + - multipart/form-data example: text/plain type: string x-enum-varnames: @@ -15955,6 +15988,8 @@ components: - TEXT_HTML - APPLICATION_X_WWW_FORM_URLENCODED - GRAPHQL + - APPLICATION_OCTET_STREAM + - MULTIPART_FORM_DATA SyntheticsTestRequestCertificate: description: Client certificate to use when performing the test request. properties: diff --git a/examples/v1_synthetics_create_synthetics_api_test_1241981394.rs b/examples/v1_synthetics_create_synthetics_api_test_1241981394.rs new file mode 100644 index 000000000..d7c77554a --- /dev/null +++ b/examples/v1_synthetics_create_synthetics_api_test_1241981394.rs @@ -0,0 +1,169 @@ +// Create an API test with a file payload returns "OK - Returns the created test +// details." response +use datadog_api_client::datadog::configuration::Configuration; +use datadog_api_client::datadogV1::api::api_synthetics::SyntheticsAPI; +use datadog_api_client::datadogV1::model::SyntheticsAPITest; +use datadog_api_client::datadogV1::model::SyntheticsAPITestConfig; +use datadog_api_client::datadogV1::model::SyntheticsAPITestType; +use datadog_api_client::datadogV1::model::SyntheticsAssertion; +use datadog_api_client::datadogV1::model::SyntheticsAssertionJSONPathOperator; +use datadog_api_client::datadogV1::model::SyntheticsAssertionJSONPathTarget; +use datadog_api_client::datadogV1::model::SyntheticsAssertionJSONPathTargetTarget; +use datadog_api_client::datadogV1::model::SyntheticsAssertionOperator; +use datadog_api_client::datadogV1::model::SyntheticsAssertionTarget; +use datadog_api_client::datadogV1::model::SyntheticsAssertionTimingsScope; +use datadog_api_client::datadogV1::model::SyntheticsAssertionType; +use datadog_api_client::datadogV1::model::SyntheticsAssertionXPathOperator; +use datadog_api_client::datadogV1::model::SyntheticsAssertionXPathTarget; +use datadog_api_client::datadogV1::model::SyntheticsAssertionXPathTargetTarget; +use datadog_api_client::datadogV1::model::SyntheticsBasicAuth; +use datadog_api_client::datadogV1::model::SyntheticsBasicAuthOauthClient; +use datadog_api_client::datadogV1::model::SyntheticsBasicAuthOauthClientType; +use datadog_api_client::datadogV1::model::SyntheticsBasicAuthOauthTokenApiAuthentication; +use datadog_api_client::datadogV1::model::SyntheticsConfigVariable; +use datadog_api_client::datadogV1::model::SyntheticsConfigVariableType; +use datadog_api_client::datadogV1::model::SyntheticsTestDetailsSubType; +use datadog_api_client::datadogV1::model::SyntheticsTestOptions; +use datadog_api_client::datadogV1::model::SyntheticsTestOptionsHTTPVersion; +use datadog_api_client::datadogV1::model::SyntheticsTestOptionsRetry; +use datadog_api_client::datadogV1::model::SyntheticsTestRequest; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestBodyFile; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestBodyType; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestCertificate; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestCertificateItem; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestProxy; +use serde_json::Value; +use std::collections::BTreeMap; + +#[tokio::main] +async fn main() { + let body = SyntheticsAPITest::new( + SyntheticsAPITestConfig::new() + .assertions(vec![ + SyntheticsAssertion::SyntheticsAssertionTarget(Box::new( + SyntheticsAssertionTarget::new( + SyntheticsAssertionOperator::IS, + Value::from("text/html"), + SyntheticsAssertionType::HEADER, + ) + .property("{{ PROPERTY }}".to_string()), + )), + SyntheticsAssertion::SyntheticsAssertionTarget(Box::new( + SyntheticsAssertionTarget::new( + SyntheticsAssertionOperator::LESS_THAN, + Value::from(2000), + SyntheticsAssertionType::RESPONSE_TIME, + ) + .timings_scope(SyntheticsAssertionTimingsScope::WITHOUT_DNS), + )), + SyntheticsAssertion::SyntheticsAssertionJSONPathTarget(Box::new( + SyntheticsAssertionJSONPathTarget::new( + SyntheticsAssertionJSONPathOperator::VALIDATES_JSON_PATH, + SyntheticsAssertionType::BODY, + ) + .target( + SyntheticsAssertionJSONPathTargetTarget::new() + .json_path("topKey".to_string()) + .operator("isNot".to_string()) + .target_value(Value::from("0")), + ), + )), + SyntheticsAssertion::SyntheticsAssertionXPathTarget(Box::new( + SyntheticsAssertionXPathTarget::new( + SyntheticsAssertionXPathOperator::VALIDATES_X_PATH, + SyntheticsAssertionType::BODY, + ) + .target( + SyntheticsAssertionXPathTargetTarget::new() + .operator("contains".to_string()) + .target_value(Value::from("0")) + .x_path("target-xpath".to_string()), + ), + )), + ]) + .config_variables(vec![SyntheticsConfigVariable::new( + "PROPERTY".to_string(), + SyntheticsConfigVariableType::TEXT, + ) + .example("content-type".to_string()) + .pattern("content-type".to_string())]) + .request( + SyntheticsTestRequest::new() + .basic_auth(SyntheticsBasicAuth::SyntheticsBasicAuthOauthClient( + Box::new( + SyntheticsBasicAuthOauthClient::new( + "https://datadog-token.com".to_string(), + "client-id".to_string(), + "client-secret".to_string(), + SyntheticsBasicAuthOauthTokenApiAuthentication::HEADER, + ) + .audience("audience".to_string()) + .resource("resource".to_string()) + .scope("yoyo".to_string()) + .type_(SyntheticsBasicAuthOauthClientType::OAUTH_CLIENT), + ), + )) + .body_type(SyntheticsTestRequestBodyType::APPLICATION_OCTET_STREAM) + .certificate( + SyntheticsTestRequestCertificate::new() + .cert( + SyntheticsTestRequestCertificateItem::new() + .content("cert-content".to_string()) + .filename("cert-filename".to_string()) + .updated_at("2020-10-16T09:23:24.857Z".to_string()), + ) + .key( + SyntheticsTestRequestCertificateItem::new() + .content("key-content".to_string()) + .filename("key-filename".to_string()) + .updated_at("2020-10-16T09:23:24.857Z".to_string()), + ), + ) + .files(vec![SyntheticsTestRequestBodyFile::new() + .content("file content".to_string()) + .name("file name".to_string()) + .type_("file type".to_string())]) + .headers(BTreeMap::from([( + "unique".to_string(), + "examplesynthetic".to_string(), + )])) + .method("GET".to_string()) + .persist_cookies(true) + .proxy( + SyntheticsTestRequestProxy::new("https://datadoghq.com".to_string()) + .headers(BTreeMap::from([])), + ) + .timeout(10.0 as f64) + .url("https://datadoghq.com".to_string()), + ), + vec!["aws:us-east-2".to_string()], + "BDD test payload: synthetics_api_http_test_payload.json".to_string(), + "Example-Synthetic".to_string(), + SyntheticsTestOptions::new() + .accept_self_signed(false) + .allow_insecure(true) + .follow_redirects(true) + .http_version(SyntheticsTestOptionsHTTPVersion::HTTP2) + .min_failure_duration(10) + .min_location_failed(1) + .monitor_name("Example-Synthetic".to_string()) + .monitor_priority(5) + .retry( + SyntheticsTestOptionsRetry::new() + .count(3) + .interval(10.0 as f64), + ) + .tick_every(60), + SyntheticsAPITestType::API, + ) + .subtype(SyntheticsTestDetailsSubType::HTTP) + .tags(vec!["testing:api".to_string()]); + let configuration = Configuration::new(); + let api = SyntheticsAPI::with_config(configuration); + let resp = api.create_synthetics_api_test(body).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v1_synthetics_update_browser_test.rs b/examples/v1_synthetics_update_browser_test.rs index 733b9f95d..294787344 100644 --- a/examples/v1_synthetics_update_browser_test.rs +++ b/examples/v1_synthetics_update_browser_test.rs @@ -26,6 +26,7 @@ use datadog_api_client::datadogV1::model::SyntheticsTestOptionsScheduling; use datadog_api_client::datadogV1::model::SyntheticsTestOptionsSchedulingTimeframe; use datadog_api_client::datadogV1::model::SyntheticsTestPauseStatus; use datadog_api_client::datadogV1::model::SyntheticsTestRequest; +use datadog_api_client::datadogV1::model::SyntheticsTestRequestBodyFile; use datadog_api_client::datadogV1::model::SyntheticsTestRequestBodyType; use datadog_api_client::datadogV1::model::SyntheticsTestRequestCertificate; use datadog_api_client::datadogV1::model::SyntheticsTestRequestCertificateItem; @@ -49,6 +50,7 @@ async fn main() { .key(SyntheticsTestRequestCertificateItem::new()), ) .certificate_domains(vec![]) + .files(vec![SyntheticsTestRequestBodyFile::new()]) .http_version(SyntheticsTestOptionsHTTPVersion::HTTP1) .proxy(SyntheticsTestRequestProxy::new( "https://example.com".to_string(), diff --git a/src/datadogV1/model/mod.rs b/src/datadogV1/model/mod.rs index a0e7fe2bf..bb8b3acaa 100644 --- a/src/datadogV1/model/mod.rs +++ b/src/datadogV1/model/mod.rs @@ -1322,6 +1322,8 @@ pub mod model_synthetics_test_request_certificate; pub use self::model_synthetics_test_request_certificate::SyntheticsTestRequestCertificate; pub mod model_synthetics_test_request_certificate_item; pub use self::model_synthetics_test_request_certificate_item::SyntheticsTestRequestCertificateItem; +pub mod model_synthetics_test_request_body_file; +pub use self::model_synthetics_test_request_body_file::SyntheticsTestRequestBodyFile; pub mod model_synthetics_test_options_http_version; pub use self::model_synthetics_test_options_http_version::SyntheticsTestOptionsHTTPVersion; pub mod model_synthetics_test_request_proxy; diff --git a/src/datadogV1/model/model_synthetics_test_request.rs b/src/datadogV1/model/model_synthetics_test_request.rs index 3c1dcb8b5..90121f4ff 100644 --- a/src/datadogV1/model/model_synthetics_test_request.rs +++ b/src/datadogV1/model/model_synthetics_test_request.rs @@ -44,6 +44,9 @@ pub struct SyntheticsTestRequest { /// DNS server port to use for DNS tests. #[serde(rename = "dnsServerPort")] pub dns_server_port: Option, + /// Files to be used as part of the request in the test. + #[serde(rename = "files")] + pub files: Option>, /// Specifies whether or not the request follows redirects. #[serde(rename = "follow_redirects")] pub follow_redirects: Option, @@ -119,6 +122,7 @@ impl SyntheticsTestRequest { compressed_proto_file: None, dns_server: None, dns_server_port: None, + files: None, follow_redirects: None, headers: None, host: None, @@ -202,6 +206,14 @@ impl SyntheticsTestRequest { self } + pub fn files( + mut self, + value: Vec, + ) -> Self { + self.files = Some(value); + self + } + pub fn follow_redirects(mut self, value: bool) -> Self { self.follow_redirects = Some(value); self @@ -333,6 +345,8 @@ impl<'de> Deserialize<'de> for SyntheticsTestRequest { let mut compressed_proto_file: Option = None; let mut dns_server: Option = None; let mut dns_server_port: Option = None; + let mut files: Option> = + None; let mut follow_redirects: Option = None; let mut headers: Option> = None; let mut host: Option = None; @@ -453,6 +467,12 @@ impl<'de> Deserialize<'de> for SyntheticsTestRequest { dns_server_port = Some(serde_json::from_value(v).map_err(M::Error::custom)?); } + "files" => { + if v.is_null() { + continue; + } + files = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } "follow_redirects" => { if v.is_null() { continue; @@ -591,6 +611,7 @@ impl<'de> Deserialize<'de> for SyntheticsTestRequest { compressed_proto_file, dns_server, dns_server_port, + files, follow_redirects, headers, host, diff --git a/src/datadogV1/model/model_synthetics_test_request_body_file.rs b/src/datadogV1/model/model_synthetics_test_request_body_file.rs new file mode 100644 index 000000000..0bd23c304 --- /dev/null +++ b/src/datadogV1/model/model_synthetics_test_request_body_file.rs @@ -0,0 +1,153 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Object describing a file to be used as part of the request in the test. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SyntheticsTestRequestBodyFile { + /// Bucket key of the file. + #[serde(rename = "bucketKey")] + pub bucket_key: Option, + /// Content of the file. + #[serde(rename = "content")] + pub content: Option, + /// Name of the file. + #[serde(rename = "name")] + pub name: Option, + /// Size of the file. + #[serde(rename = "size")] + pub size: Option, + /// Type of the file. + #[serde(rename = "type")] + pub type_: Option, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SyntheticsTestRequestBodyFile { + pub fn new() -> SyntheticsTestRequestBodyFile { + SyntheticsTestRequestBodyFile { + bucket_key: None, + content: None, + name: None, + size: None, + type_: None, + _unparsed: false, + } + } + + pub fn bucket_key(mut self, value: String) -> Self { + self.bucket_key = Some(value); + self + } + + pub fn content(mut self, value: String) -> Self { + self.content = Some(value); + self + } + + pub fn name(mut self, value: String) -> Self { + self.name = Some(value); + self + } + + pub fn size(mut self, value: i64) -> Self { + self.size = Some(value); + self + } + + pub fn type_(mut self, value: String) -> Self { + self.type_ = Some(value); + self + } +} + +impl Default for SyntheticsTestRequestBodyFile { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SyntheticsTestRequestBodyFile { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SyntheticsTestRequestBodyFileVisitor; + impl<'a> Visitor<'a> for SyntheticsTestRequestBodyFileVisitor { + type Value = SyntheticsTestRequestBodyFile; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut bucket_key: Option = None; + let mut content: Option = None; + let mut name: Option = None; + let mut size: Option = None; + let mut type_: Option = None; + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "bucketKey" => { + if v.is_null() { + continue; + } + bucket_key = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "content" => { + if v.is_null() { + continue; + } + content = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "name" => { + if v.is_null() { + continue; + } + name = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "size" => { + if v.is_null() { + continue; + } + size = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + if v.is_null() { + continue; + } + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => {} + } + } + + let content = SyntheticsTestRequestBodyFile { + bucket_key, + content, + name, + size, + type_, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SyntheticsTestRequestBodyFileVisitor) + } +} diff --git a/src/datadogV1/model/model_synthetics_test_request_body_type.rs b/src/datadogV1/model/model_synthetics_test_request_body_type.rs index 9a080e464..df55ee652 100644 --- a/src/datadogV1/model/model_synthetics_test_request_body_type.rs +++ b/src/datadogV1/model/model_synthetics_test_request_body_type.rs @@ -13,6 +13,8 @@ pub enum SyntheticsTestRequestBodyType { TEXT_HTML, APPLICATION_X_WWW_FORM_URLENCODED, GRAPHQL, + APPLICATION_OCTET_STREAM, + MULTIPART_FORM_DATA, UnparsedObject(crate::datadog::UnparsedObject), } @@ -27,6 +29,8 @@ impl ToString for SyntheticsTestRequestBodyType { String::from("application/x-www-form-urlencoded") } Self::GRAPHQL => String::from("graphql"), + Self::APPLICATION_OCTET_STREAM => String::from("application/octet-stream"), + Self::MULTIPART_FORM_DATA => String::from("multipart/form-data"), Self::UnparsedObject(v) => v.value.to_string(), } } @@ -57,6 +61,8 @@ impl<'de> Deserialize<'de> for SyntheticsTestRequestBodyType { "text/html" => Self::TEXT_HTML, "application/x-www-form-urlencoded" => Self::APPLICATION_X_WWW_FORM_URLENCODED, "graphql" => Self::GRAPHQL, + "application/octet-stream" => Self::APPLICATION_OCTET_STREAM, + "multipart/form-data" => Self::MULTIPART_FORM_DATA, _ => Self::UnparsedObject(crate::datadog::UnparsedObject { value: serde_json::Value::String(s.into()), }), diff --git a/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.frozen b/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.frozen new file mode 100644 index 000000000..42decaa94 --- /dev/null +++ b/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.frozen @@ -0,0 +1 @@ +2024-04-02T15:35:39.188Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.json b/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.json new file mode 100644 index 000000000..11643166d --- /dev/null +++ b/tests/scenarios/cassettes/v1/synthetics/Create-an-API-test-with-a-file-payload-returns-OK-Returns-the-created-test-details-response.json @@ -0,0 +1,73 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"config\":{\"assertions\":[{\"operator\":\"is\",\"property\":\"{{ PROPERTY }}\",\"target\":\"text/html\",\"type\":\"header\"},{\"operator\":\"lessThan\",\"target\":2000,\"timingsScope\":\"withoutDNS\",\"type\":\"responseTime\"},{\"operator\":\"validatesJSONPath\",\"target\":{\"jsonPath\":\"topKey\",\"operator\":\"isNot\",\"targetValue\":\"0\"},\"type\":\"body\"},{\"operator\":\"validatesXPath\",\"target\":{\"operator\":\"contains\",\"targetValue\":\"0\",\"xPath\":\"target-xpath\"},\"type\":\"body\"}],\"configVariables\":[{\"example\":\"content-type\",\"name\":\"PROPERTY\",\"pattern\":\"content-type\",\"type\":\"text\"}],\"request\":{\"basicAuth\":{\"accessTokenUrl\":\"https://datadog-token.com\",\"audience\":\"audience\",\"clientId\":\"client-id\",\"clientSecret\":\"client-secret\",\"resource\":\"resource\",\"scope\":\"yoyo\",\"tokenApiAuthentication\":\"header\",\"type\":\"oauth-client\"},\"bodyType\":\"application/octet-stream\",\"certificate\":{\"cert\":{\"content\":\"cert-content\",\"filename\":\"cert-filename\",\"updatedAt\":\"2020-10-16T09:23:24.857Z\"},\"key\":{\"content\":\"key-content\",\"filename\":\"key-filename\",\"updatedAt\":\"2020-10-16T09:23:24.857Z\"}},\"files\":[{\"content\":\"file content\",\"name\":\"file name\",\"type\":\"file type\"}],\"headers\":{\"unique\":\"testcreateanapitestwithafilepayloadreturnsokreturnsthecreatedtestdetailsresponse1712072139\"},\"method\":\"GET\",\"persistCookies\":true,\"proxy\":{\"headers\":{},\"url\":\"https://datadoghq.com\"},\"timeout\":10,\"url\":\"https://datadoghq.com\"}},\"locations\":[\"aws:us-east-2\"],\"message\":\"BDD test payload: synthetics_api_http_test_payload.json\",\"name\":\"Test-Create_an_API_test_with_a_file_payload_returns_OK_Returns_the_created_test_details_response-1712072139\",\"options\":{\"accept_self_signed\":false,\"allow_insecure\":true,\"follow_redirects\":true,\"httpVersion\":\"http2\",\"min_failure_duration\":10,\"min_location_failed\":1,\"monitor_name\":\"Test-Create_an_API_test_with_a_file_payload_returns_OK_Returns_the_created_test_details_response-1712072139\",\"monitor_priority\":5,\"retry\":{\"count\":3,\"interval\":10},\"tick_every\":60},\"subtype\":\"http\",\"tags\":[\"testing:api\"],\"type\":\"api\"}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v1/synthetics/tests/api" + }, + "response": { + "body": { + "string": "{\"public_id\":\"sxp-kz5-mk7\",\"name\":\"Test-Create_an_API_test_with_a_file_payload_returns_OK_Returns_the_created_test_details_response-1712072139\",\"status\":\"live\",\"type\":\"api\",\"tags\":[\"testing:api\"],\"created_at\":\"2024-04-02T15:35:40.509801+00:00\",\"modified_at\":\"2024-04-02T15:35:40.509801+00:00\",\"config\":{\"assertions\":[{\"operator\":\"is\",\"property\":\"{{ PROPERTY }}\",\"target\":\"text/html\",\"type\":\"header\"},{\"operator\":\"lessThan\",\"target\":2000,\"timingsScope\":\"withoutDNS\",\"type\":\"responseTime\"},{\"operator\":\"validatesJSONPath\",\"target\":{\"jsonPath\":\"topKey\",\"operator\":\"isNot\",\"targetValue\":\"0\"},\"type\":\"body\"},{\"operator\":\"validatesXPath\",\"target\":{\"operator\":\"contains\",\"targetValue\":\"0\",\"xPath\":\"target-xpath\"},\"type\":\"body\"}],\"configVariables\":[{\"example\":\"content-type\",\"name\":\"PROPERTY\",\"pattern\":\"content-type\",\"type\":\"text\"}],\"request\":{\"basicAuth\":{\"accessTokenUrl\":\"https://datadog-token.com\",\"audience\":\"audience\",\"clientId\":\"client-id\",\"clientSecret\":\"client-secret\",\"resource\":\"resource\",\"scope\":\"yoyo\",\"tokenApiAuthentication\":\"header\",\"type\":\"oauth-client\"},\"bodyType\":\"application/octet-stream\",\"certificate\":{\"cert\":{\"filename\":\"cert-filename\",\"updatedAt\":\"2020-10-16T09:23:24.857Z\"},\"key\":{\"filename\":\"key-filename\",\"updatedAt\":\"2020-10-16T09:23:24.857Z\"}},\"files\":[{\"name\":\"file name\",\"type\":\"file type\",\"bucketKey\":\"api-upload-file/sxp-kz5-mk7/2024-04-02T15:35:40.363501_da19b48f-1756-453d-a03d-90526e629d7e.json\"}],\"headers\":{\"unique\":\"testcreateanapitestwithafilepayloadreturnsokreturnsthecreatedtestdetailsresponse1712072139\"},\"method\":\"GET\",\"persistCookies\":true,\"proxy\":{\"headers\":{},\"url\":\"https://datadoghq.com\"},\"timeout\":10,\"url\":\"https://datadoghq.com\"}},\"message\":\"BDD test payload: synthetics_api_http_test_payload.json\",\"options\":{\"accept_self_signed\":false,\"allow_insecure\":true,\"follow_redirects\":true,\"httpVersion\":\"http2\",\"min_failure_duration\":10,\"min_location_failed\":1,\"monitor_name\":\"Test-Create_an_API_test_with_a_file_payload_returns_OK_Returns_the_created_test_details_response-1712072139\",\"monitor_priority\":5,\"retry\":{\"count\":3,\"interval\":10},\"tick_every\":60},\"locations\":[\"aws:us-east-2\"],\"subtype\":\"http\",\"created_by\":{\"name\":null,\"handle\":\"frog@datadoghq.com\",\"email\":\"frog@datadoghq.com\"},\"deleted_at\":null,\"monitor_id\":142439982,\"org_id\":321813,\"modified_by\":{\"name\":null,\"handle\":\"frog@datadoghq.com\",\"email\":\"frog@datadoghq.com\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Tue, 02 Apr 2024 15:35:39 GMT" + }, + { + "request": { + "body": { + "string": "{\"public_ids\":[\"sxp-kz5-mk7\"]}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v1/synthetics/tests/delete" + }, + "response": { + "body": { + "string": "{\"deleted_tests\":[{\"public_id\":\"sxp-kz5-mk7\",\"deleted_at\":\"2024-04-02T15:35:41.326918+00:00\"}]}\n", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Tue, 02 Apr 2024 15:35:39 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/features/v1/synthetics.feature b/tests/scenarios/features/v1/synthetics.feature index 4942cb45e..64ccdb946 100644 --- a/tests/scenarios/features/v1/synthetics.feature +++ b/tests/scenarios/features/v1/synthetics.feature @@ -34,7 +34,7 @@ Feature: Synthetics @generated @skip @team:DataDog/synthetics-app Scenario: Create a browser test returns "- JSON format is wrong" response Given new "CreateSyntheticsBrowserTest" request - And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} + And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "files": [{}], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} When the request is sent Then the response status is 400 - JSON format is wrong @@ -61,7 +61,7 @@ Feature: Synthetics @generated @skip @team:DataDog/synthetics-app Scenario: Create a browser test returns "Test quota is reached" response Given new "CreateSyntheticsBrowserTest" request - And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} + And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "files": [{}], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} When the request is sent Then the response status is 402 Test quota is reached @@ -193,6 +193,17 @@ Feature: Synthetics Then the response status is 200 OK - Returns the created test details. And the response "name" is equal to "{{ unique }}" + @team:DataDog/synthetics-app + Scenario: Create an API test with a file payload returns "OK - Returns the created test details." response + Given new "CreateSyntheticsAPITest" request + And body from file "synthetics_api_http_test_with_file_payload.json" + When the request is sent + Then the response status is 200 OK - Returns the created test details. + And the response "name" is equal to "{{ unique }}" + And the response "config.request.files[0].name" is equal to "file name" + And the response "config.request.files[0].type" is equal to "file type" + And the response "config.request.files[0]" has field "bucketKey" + @team:DataDog/synthetics-app Scenario: Create an API test with multi subtype returns "OK - Returns the created test details." response Given new "CreateSyntheticsAPITest" request @@ -205,6 +216,7 @@ Feature: Synthetics And the response "config.steps[0].request.httpVersion" is equal to "http2" And the response "config.steps[0].extractedValues[0].secure" is equal to true And the response "config.steps[1].request.host" is equal to "grpcbin.test.k6.io" + And the response "config.steps[1].request.host" is equal to "grpcbin.test.k6.io" @generated @skip @team:DataDog/synthetics-app Scenario: Delete a global variable returns "JSON format is wrong" response @@ -268,7 +280,7 @@ Feature: Synthetics Scenario: Edit a browser test returns "- JSON format is wrong" response Given new "UpdateBrowserTest" request And request contains "public_id" parameter from "REPLACE.ME" - And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} + And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "files": [{}], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} When the request is sent Then the response status is 400 - JSON format is wrong @@ -276,7 +288,7 @@ Feature: Synthetics Scenario: Edit a browser test returns "- Synthetic Monitoring is not activated for the user" response Given new "UpdateBrowserTest" request And request contains "public_id" parameter from "REPLACE.ME" - And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} + And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "files": [{}], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} When the request is sent Then the response status is 404 - Synthetic Monitoring is not activated for the user @@ -284,7 +296,7 @@ Feature: Synthetics Scenario: Edit a browser test returns "OK" response Given new "UpdateBrowserTest" request And request contains "public_id" parameter from "REPLACE.ME" - And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} + And body with value {"config": {"assertions": [], "configVariables": [{"name": "VARIABLE_NAME", "secure": false, "type": "text"}], "request": {"basicAuth": {"password": "PaSSw0RD!", "type": "web", "username": "my_username"}, "bodyType": "text/plain", "callType": "unary", "certificate": {"cert": {}, "key": {}}, "certificateDomains": [], "files": [{}], "httpVersion": "http1", "proxy": {"url": "https://example.com"}, "service": "Greeter", "url": "https://example.com"}, "variables": [{"name": "VARIABLE_NAME", "type": "text"}]}, "locations": ["aws:eu-west-3"], "message": "", "name": "Example test name", "options": {"ci": {"executionRule": "blocking"}, "device_ids": ["chrome.laptop_large"], "httpVersion": "http1", "monitor_options": {}, "restricted_roles": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "retry": {}, "rumSettings": {"applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "clientTokenId": 12345, "isEnabled": true}, "scheduling": {"timeframes": [{"day": 1, "from": "07:00", "to": "16:00"}, {"day": 3, "from": "07:00", "to": "16:00"}], "timezone": "America/New_York"}}, "status": "live", "steps": [{"type": "assertElementContent"}], "tags": ["env:prod"], "type": "browser"} When the request is sent Then the response status is 200 OK diff --git a/tests/scenarios/features/v1/synthetics_api_http_test_with_file_payload.json b/tests/scenarios/features/v1/synthetics_api_http_test_with_file_payload.json new file mode 100644 index 000000000..bf4f0e4ad --- /dev/null +++ b/tests/scenarios/features/v1/synthetics_api_http_test_with_file_payload.json @@ -0,0 +1,96 @@ +{ + "config": { + "assertions": [ + { + "operator": "is", + "property": "{{ '{{ PROPERTY }}' }}", + "target": "text/html", + "type": "header" + }, + { "operator": "lessThan", "target": 2000, "type": "responseTime", "timingsScope": "withoutDNS" }, + { + "operator": "validatesJSONPath", + "target": { + "jsonPath": "topKey", + "operator": "isNot", + "targetValue": "0" + }, + "type": "body" + }, + { + "operator": "validatesXPath", + "target": { + "xPath": "target-xpath", + "targetValue": "0", + "operator": "contains" + }, + "type": "body" + } + ], + "configVariables": [ + { + "example": "content-type", + "name": "PROPERTY", + "pattern": "content-type", + "type": "text" + } + ], + "request": { + "certificate": { + "cert": { + "content": "cert-content", + "filename": "cert-filename", + "updatedAt": "2020-10-16T09:23:24.857Z" + }, + "key": { + "content": "key-content", + "filename": "key-filename", + "updatedAt": "2020-10-16T09:23:24.857Z" + } + }, + "headers": { "unique": "{{ unique_lower_alnum }}" }, + "method": "GET", + "timeout": 10, + "url": "https://datadoghq.com", + "proxy": { + "url": "https://datadoghq.com", + "headers": {} + }, + "bodyType": "application/octet-stream", + "files": [{ + "name": "file name", + "content": "file content", + "type": "file type" + }], + "basicAuth": { + "accessTokenUrl": "https://datadog-token.com", + "audience": "audience", + "clientId": "client-id", + "clientSecret": "client-secret", + "resource": "resource", + "scope": "yoyo", + "tokenApiAuthentication": "header", + "type": "oauth-client" + }, + "persistCookies": true + } + }, + "locations": ["aws:us-east-2"], + "message": "BDD test payload: synthetics_api_http_test_payload.json", + "name": "{{ unique }}", + "options": { + "accept_self_signed": false, + "allow_insecure": true, + "follow_redirects": true, + "min_failure_duration": 10, + "min_location_failed": 1, + "monitor_name": "{{ unique }}", + "monitor_priority": 5, + "retry": { "count": 3, "interval": 10 }, + "tick_every": 60, + "httpVersion": "http2" + }, + "subtype": "http", + "tags": ["testing:api"], + "type": "api" + }