Skip to content

Commit

Permalink
Merge branch 'master' into add-mr-links-to-changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
andrebq authored Oct 4, 2023
2 parents 5dcf4b7 + b5f0b0c commit e0d1162
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 8 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Breaking changes

### New features & improvements
- Add handy `env()` and `team()` functions for adding corresponding Datadog `key:value` tags
- Add handy `env()` and `team()` functions for adding corresponding Datadog `key:value` tags ([#126](https://github.com/personio/datadog-synthetic-test-support/pull/126))
- Add minimum working implementation of a refactored browser test support ([#129](https://github.com/personio/datadog-synthetic-test-support/pull/129))
- Add `status()` function to set the SyntheticTestPauseStatus property ([#127](https://github.com/personio/datadog-synthetic-test-support/pull/127))

### Bug fixes

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Start using the library in a gradle project by following the steps below:
syntheticMultiStepApiTest("Test Login to the app") {
env("qa")
team("team-one")
status(SyntheticsTestPauseStatus.LIVE)
publicLocations(Location.FRANKFURT_AWS)
testFrequency(5.minutes)
retry(1, 600.milliseconds)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.personio.synthetics.builder

import com.datadog.api.client.v1.model.SyntheticsBrowserTest
import com.datadog.api.client.v1.model.SyntheticsBrowserTestConfig
import com.datadog.api.client.v1.model.SyntheticsBrowserTestType
import com.datadog.api.client.v1.model.SyntheticsBrowserVariable
import com.datadog.api.client.v1.model.SyntheticsBrowserVariableType
import com.datadog.api.client.v1.model.SyntheticsTestPauseStatus
import com.datadog.api.client.v1.model.SyntheticsTestRequest
import com.personio.synthetics.client.SyntheticsApiClient
import com.personio.synthetics.config.Defaults
import java.net.URL

/**
* A builder for creating SyntheticsBrowserTest instances
*/
class SyntheticBrowserTestBuilder(
override val name: String,
defaults: Defaults,
apiClient: SyntheticsApiClient
) : SyntheticTestBuilder(name, defaults, apiClient) {
private val config = SyntheticsBrowserTestConfig()

/**
* Builds a synthetic browser test
* @return SyntheticsBrowserTest object that contains a browser test
*/
fun build(): SyntheticsBrowserTest =
SyntheticsBrowserTest(
config,
parameters.locations,
parameters.message,
name,
options,
SyntheticsBrowserTestType.BROWSER
)
.tags(parameters.tags)
.status(SyntheticsTestPauseStatus.PAUSED)

/**
* Sets the base url for the synthetic browser test
* @param url The base url for the test
*/
fun baseUrl(url: URL) {
config.request(
SyntheticsTestRequest()
.method("GET")
.url(url.toString())
)
}

override fun addLocalVariable(name: String, pattern: String) {
config.addVariablesItem(
SyntheticsBrowserVariable()
.name(name.uppercase())
.type(SyntheticsBrowserVariableType.TEXT)
.pattern(pattern)
.example("")
)
}

override fun useGlobalVariable(name: String) {
val variableName = name.uppercase()
val variableId = getGlobalVariableId(variableName)
checkNotNull(variableId) { "The global variable $name to be used in the test doesn't exist in DataDog." }
config.addVariablesItem(
SyntheticsBrowserVariable()
.name(variableName)
.id(variableId)
.type(SyntheticsBrowserVariableType.GLOBAL)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.datadog.api.client.v1.model.SyntheticsAPITestType
import com.datadog.api.client.v1.model.SyntheticsConfigVariable
import com.datadog.api.client.v1.model.SyntheticsConfigVariableType
import com.datadog.api.client.v1.model.SyntheticsTestDetailsSubType
import com.datadog.api.client.v1.model.SyntheticsTestPauseStatus
import com.personio.synthetics.builder.api.StepsBuilder
import com.personio.synthetics.client.SyntheticsApiClient
import com.personio.synthetics.config.Defaults
Expand Down Expand Up @@ -36,7 +35,7 @@ class SyntheticMultiStepApiTestBuilder(
SyntheticsAPITestType.API
)
.tags(parameters.tags)
.status(SyntheticsTestPauseStatus.PAUSED)
.status(status)
.subtype(SyntheticsTestDetailsSubType.MULTI)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.datadog.api.client.v1.model.SyntheticsTestOptionsMonitorOptions
import com.datadog.api.client.v1.model.SyntheticsTestOptionsRetry
import com.datadog.api.client.v1.model.SyntheticsTestOptionsScheduling
import com.datadog.api.client.v1.model.SyntheticsTestOptionsSchedulingTimeframe
import com.datadog.api.client.v1.model.SyntheticsTestPauseStatus
import com.personio.synthetics.client.SyntheticsApiClient
import com.personio.synthetics.config.Defaults
import com.personio.synthetics.domain.SyntheticTestParameters
Expand Down Expand Up @@ -33,7 +34,7 @@ abstract class SyntheticTestBuilder(
) {
protected var parameters: SyntheticTestParameters
protected var options: SyntheticsTestOptions
protected var locations: List<String> = defaults.runLocations
protected var status: SyntheticsTestPauseStatus = SyntheticsTestPauseStatus.PAUSED

init {
parameters = SyntheticTestParameters(
Expand Down Expand Up @@ -171,8 +172,8 @@ abstract class SyntheticTestBuilder(
* Allowed minimum location failed is between 1 and the number of locations where the test is configured to run
*/
fun minLocationFailed(minLocationFailed: Long) {
require(minLocationFailed in 1..locations.count()) {
"Minimum location failed should be between 1 and the number of locations where the test is configured to run: ${locations.count()}."
require(minLocationFailed in 1..parameters.locations.count()) {
"Minimum location failed should be between 1 and the number of locations where the test is configured to run: ${parameters.locations.count()}."
}
options.minLocationFailed = minLocationFailed
}
Expand All @@ -190,8 +191,8 @@ abstract class SyntheticTestBuilder(
* @param monitorPriority The monitor priority of the test
* Allowed monitor priority is one of [1, 2, 3, 4, 5]
*/
fun monitorPriority(monitorPriorities: MonitorPriority) {
options.monitorPriority = monitorPriorities.priorityValue
fun monitorPriority(monitorPriority: MonitorPriority) {
options.monitorPriority = monitorPriority.priorityValue
}

/**
Expand Down Expand Up @@ -295,6 +296,10 @@ abstract class SyntheticTestBuilder(
tags("team:$teamName")
}

fun status(status: SyntheticsTestPauseStatus) {
this.status = status
}

private fun getScaledDate(value: Duration): Pair<Long, String>? =
value.getScaledValue(
sequenceOf(DurationUnit.MILLISECONDS, DurationUnit.SECONDS, DurationUnit.MINUTES, DurationUnit.HOURS, DurationUnit.DAYS),
Expand Down Expand Up @@ -332,5 +337,6 @@ abstract class SyntheticTestBuilder(
?.id

protected abstract fun addLocalVariable(name: String, pattern: String)

abstract fun useGlobalVariable(name: String)
}
22 changes: 22 additions & 0 deletions src/main/kotlin/com/personio/synthetics/dsl/SyntheticTestDsl.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.personio.synthetics.dsl

import com.datadog.api.client.v1.model.SyntheticsAPITest
import com.datadog.api.client.v1.model.SyntheticsBrowserTest
import com.personio.synthetics.builder.SyntheticBrowserTestBuilder
import com.personio.synthetics.builder.SyntheticMultiStepApiTestBuilder
import com.personio.synthetics.client.AwsSecretsManagerCredentialsProvider
import com.personio.synthetics.client.ConfigCredentialsProvider
Expand Down Expand Up @@ -39,6 +41,26 @@ fun syntheticMultiStepApiTest(name: String, init: SyntheticMultiStepApiTestBuild
}
}

fun syntheticBrowserTest(name: String, init: SyntheticBrowserTestBuilder.() -> Unit): SyntheticsBrowserTest {
check(name.isNotBlank()) {
"The test's name must not be empty."
}

val (client, defaults) = getSyntheticsApiClientAndDefaults()

val test = SyntheticBrowserTestBuilder(name, defaults, client)
.apply(init)
.build()

val testId = getTestId(client, name)

return if (testId != null) {
client.updateBrowserTest(testId, test)
} else {
client.createSyntheticsBrowserTest(test)
}
}

private fun getTestId(syntheticsApiClient: SyntheticsApiClient, name: String) =
syntheticsApiClient.listTests()
.tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.personio.synthetics.builder
import com.datadog.api.client.v1.model.SyntheticsAPIStep
import com.datadog.api.client.v1.model.SyntheticsConfigVariable
import com.datadog.api.client.v1.model.SyntheticsConfigVariableType
import com.datadog.api.client.v1.model.SyntheticsTestPauseStatus
import com.personio.synthetics.builder.api.StepsBuilder
import com.personio.synthetics.client.SyntheticsApiClient
import com.personio.synthetics.config.getConfigFromFile
Expand Down Expand Up @@ -300,4 +301,18 @@ class SyntheticMultiStepApiTestBuilderTest {
assertTrue(result.tags.contains("team:team-one"))
assertTrue(result.tags.contains("team:team-two"))
}

@Test
fun `status is set to PAUSED by default`() {
val result = sut.build()
assertEquals(SyntheticsTestPauseStatus.PAUSED, result.status)
}

@Test
fun `status sets status of a test`() {
sut.status(SyntheticsTestPauseStatus.LIVE)
val result = sut.build()

assertEquals(SyntheticsTestPauseStatus.LIVE, result.status)
}
}
65 changes: 65 additions & 0 deletions src/test/kotlin/com/personio/synthetics/e2e/E2EBrowserTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.personio.synthetics.e2e

import com.personio.synthetics.dsl.syntheticBrowserTest
import com.personio.synthetics.model.config.Location
import com.personio.synthetics.model.config.MonitorPriority
import com.personio.synthetics.model.config.RenotifyInterval
import com.personio.synthetics.model.config.Timeframe
import org.junit.jupiter.api.Test
import java.net.URL
import java.time.DayOfWeek
import java.time.LocalTime
import java.time.ZoneId
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds

class E2EBrowserTest {
@Test
fun `create synthetic browser test`() {
syntheticBrowserTest("[Browser] Synthetic-Test-As-Code") {
alertMessage("Test Failed", "@slack-test_slack_channel")
recoveryMessage("Test recovered")
env("qa")
tags("synthetics-api")
baseUrl(URL("https://synthetic-test.personio.de"))
publicLocations(Location.IRELAND_AWS, Location.N_CALIFORNIA_AWS, Location.MUMBAI_AWS)
testFrequency(6.minutes)
advancedScheduling(
Timeframe(
from = LocalTime.of(0, 1),
to = LocalTime.of(23, 59),
DayOfWeek.MONDAY,
DayOfWeek.TUESDAY,
DayOfWeek.FRIDAY
),
timezone = ZoneId.of("Europe/Dublin")
)
retry(2, 600.milliseconds)
minFailureDuration(120.minutes)
minLocationFailed(2)
monitorName("Monitor for [Browser] Synthetic-Test-As-Code")
renotifyInterval(RenotifyInterval.HOURS_2)
monitorPriority(MonitorPriority.P3_MEDIUM)
useGlobalVariable("TEST_PASSWORD")
textVariable("TEXT_VARIABLE", "test")
numericPatternVariable(
name = "NUMERIC_PATTERN",
characterLength = 4,
prefix = "test"
)
alphabeticPatternVariable("ALPHABETIC_PATTERN", 5)
alphanumericPatternVariable("ALPHANUMERIC_PATTERN", 6)
datePatternVariable(
name = "DATE_PATTERN",
duration = (-1).days,
format = "MM-DD-YYYY"
)
timestampPatternVariable(
name = "TIMESTAMP_PATTERN",
duration = 10.seconds
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.personio.synthetics.e2e

import com.datadog.api.client.v1.model.SyntheticsTestPauseStatus
import com.datadog.api.client.v1.model.SyntheticsTestRequestBodyType
import com.personio.synthetics.builder.RequestMethod
import com.personio.synthetics.dsl.syntheticMultiStepApiTest
Expand All @@ -23,6 +24,7 @@ class E2EMultiStepApiTest {
alertMessage("Test failed", "@slack-test_slack_channel")
recoveryMessage("Test recovered")
env("qa")
status(SyntheticsTestPauseStatus.PAUSED)
publicLocations(Location.IRELAND_AWS, Location.N_CALIFORNIA_AWS, Location.MUMBAI_AWS)
testFrequency(1.minutes)
advancedScheduling(
Expand Down

0 comments on commit e0d1162

Please sign in to comment.