Skip to content

Commit

Permalink
Get configuration dynamically (#37)
Browse files Browse the repository at this point in the history
Co-authored-by: HARSHIT SINHA <[email protected]>
  • Loading branch information
Tan108 and hsinha610 authored Aug 5, 2024
1 parent d13cbeb commit 9c961d1
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 70 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Conditions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ object Conditions {
attributeValue is AttributeValue.StringValue && conditionValue is ConditionValue.ArrayValue -> {
when (operator) {
IN_ARRAY -> attributeValue.value in conditionValue.values
NOT_IN_ARRAY -> (attributeValue.value in conditionValue.values).not()
NOT_IN_ARRAY -> (attributeValue.value !in conditionValue.values)
else -> false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun benchmarkFeature(option: BenchMarkOptions) {

val datafileBuildStart = System.nanoTime().toDouble()

val datafileContent = buildDataFileForStaging(option.projectRootPath)
val datafileContent = buildDataFileAsPerEnvironment(option.projectRootPath,"staging")

val datafileBuildEnd = System.nanoTime().toDouble()

Expand Down
12 changes: 12 additions & 0 deletions src/main/kotlin/com/featurevisor/testRunner/CommandExecuter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,15 @@ private fun String.runCommand(workingDir: File): String? =
printMessageInRedColor("Exception while executing command -> ${e.message}")
null
}

fun createCommandForConfiguration()=
"npx featurevisor config --print --pretty"

fun getConfigurationJson(projectRootPath: String) =
try {
createCommandForConfiguration().runCommand(getFileForSpecificPath(projectRootPath))
}catch (e:Exception){
printMessageInRedColor("Exception in createCommandForConfiguration Commandline execution --> ${e.message}")
null
}

4 changes: 4 additions & 0 deletions src/main/kotlin/com/featurevisor/testRunner/Parser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,7 @@ private fun parseConditionValue(value: Any?): ConditionValue {
}
}

fun parseConfiguration(projectRootPath: String) =
json.decodeFromString(Configuration.serializer(),getConfigurationJson(projectRootPath)!!)


82 changes: 47 additions & 35 deletions src/main/kotlin/com/featurevisor/testRunner/TestExecuter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,60 @@ data class TestProjectOption(
val showDatafile: Boolean = false,
val onlyFailures: Boolean = false,
val fast: Boolean = false,
val testDirPath: String = "tests",
val projectRootPath: String = getRootProjectDir()
val projectRootPath: String? = null
)

fun startTest(option: TestProjectOption) {
fun startTest(option: TestProjectOption) = option.projectRootPath?.let { it ->
val projectConfig = parseConfiguration(it)
var hasError = false
val folder = File("${option.projectRootPath}/${option.testDirPath}")
val folder = File(projectConfig.testsDirectoryPath)
val listOfFiles = folder.listFiles()?.sortedBy { it }
var executionResult: ExecutionResult? = null
var executionResult: ExecutionResult?
val startTime = System.currentTimeMillis()
var passedTestsCount = 0
var failedTestsCount = 0
var passedAssertionsCount = 0
var failedAssertionsCount = 0
val datafileContentByEnvironment: MutableMap<String, DatafileContent> = mutableMapOf()

if (!listOfFiles.isNullOrEmpty()) {
val datafile =
if (option.fast) buildDataFileForBothEnvironments(projectRootPath = option.projectRootPath) else DataFile(
null,
null
if (option.fast) {
for (environment in projectConfig.environments) {
val datafileContent = buildDataFileAsPerEnvironment(
projectRootPath = it,
environment = environment
)
if (option.fast && (datafile.stagingDataFiles == null || datafile.productionDataFiles == null)) {
return
datafileContentByEnvironment[environment] = datafileContent
}
}

if (!listOfFiles.isNullOrEmpty()) {
for (file in listOfFiles) {
if (file.isFile) {
if (file.extension.equals("yml", true)) {
val filePath = file.absoluteFile.path
try {
executionResult = executeTest(filePath, dataFile = datafile, option)
} catch (e: Exception) {
printMessageInRedColor("Exception while execution test --> ${e.message}")
}

if (executionResult == null) {
continue
}

if (executionResult.passed) {
passedTestsCount++
if (listOfFiles.isNotEmpty()) {
executionResult = try {
executeTest(filePath, datafileContentByEnvironment, option, projectConfig)
} catch (e: Exception) {
printMessageInRedColor("Exception while executing assertion -> ${e.message}")
null
}
if (executionResult == null) {
continue
}

if (executionResult.passed) {
passedTestsCount++
} else {
hasError = true
failedTestsCount++
}

passedAssertionsCount += executionResult.assertionsCount.passed
failedAssertionsCount += executionResult.assertionsCount.failed
} else {
hasError = true
failedTestsCount++
printMessageInRedColor("The file is not valid yml file")
}

passedAssertionsCount += executionResult.assertionsCount.passed
failedAssertionsCount += executionResult.assertionsCount.failed
} else {
printMessageInRedColor("The file is not valid yml file")
}
}
}
Expand All @@ -81,17 +86,23 @@ fun startTest(option: TestProjectOption) {
} else {
printMessageInRedColor("Directory is Empty or not exists")
}
}
} ?: printNormalMessage("Root Project Path Not Found")


private fun executeTest(filePath: String, dataFile: DataFile, option: TestProjectOption): ExecutionResult? {
private fun executeTest(
filePath: String,
datafileContentByEnvironment: MutableMap<String, DatafileContent>,
option: TestProjectOption,
configuration: Configuration
): ExecutionResult? {
val test = parseTestFeatureAssertions(filePath)

val executionResult = ExecutionResult(
passed = true,
assertionsCount = AssertionsCount(0, 0)
)

if (test != null){
if (test != null) {
val key = when (test) {
is Test.Feature -> test.value.key
is Test.Segment -> test.value.key
Expand All @@ -105,14 +116,15 @@ private fun executeTest(filePath: String, dataFile: DataFile, option: TestProjec
is Test.Feature -> {
testFeature(
testFeature = test.value,
dataFile = dataFile,
datafileContentByEnvironment = datafileContentByEnvironment,
option = option
)
}

is Test.Segment -> {
testSegment(
testSegment = test.value,
configuration = configuration,
option = option
)
}
Expand Down
15 changes: 8 additions & 7 deletions src/main/kotlin/com/featurevisor/testRunner/TestFeature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement

fun testFeature(testFeature: TestFeature, dataFile: DataFile, option: TestProjectOption): TestResult {
fun testFeature(
testFeature: TestFeature,
datafileContentByEnvironment:MutableMap<String, DatafileContent>,
option: TestProjectOption
): TestResult {
val testStartTime = System.currentTimeMillis()
val featureKey = testFeature.key

Expand Down Expand Up @@ -40,15 +44,12 @@ fun testFeature(testFeature: TestFeature, dataFile: DataFile, option: TestProjec
return@forEach
}

val datafileContent = if (option.fast) {
if (it.environment.equals("staging", true)) dataFile.stagingDataFiles else dataFile.productionDataFiles
} else {
getDataFileContent(
val datafileContent = datafileContentByEnvironment[it.environment]
?: getDataFileContent(
featureName = testFeature.key,
environment = it.environment,
projectRootPath = option.projectRootPath
projectRootPath = option.projectRootPath.orEmpty()
)
}

if (option.showDatafile) {
printNormalMessage("")
Expand Down
9 changes: 3 additions & 6 deletions src/main/kotlin/com/featurevisor/testRunner/TestSegment.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.featurevisor.testRunner

import com.featurevisor.sdk.segmentIsMatched
import com.featurevisor.types.TestResult
import com.featurevisor.types.TestResultAssertion
import com.featurevisor.types.TestResultAssertionError
import com.featurevisor.types.TestSegment
import com.featurevisor.types.*

fun testSegment(testSegment: TestSegment, option: TestProjectOption): TestResult {
fun testSegment(testSegment: TestSegment,configuration: Configuration,option: TestProjectOption): TestResult {
val testStartTime = System.currentTimeMillis()
val segmentKey = testSegment.key

Expand Down Expand Up @@ -36,7 +33,7 @@ fun testSegment(testSegment: TestSegment, option: TestProjectOption): TestResult
return@forEach
}

val yamlSegment = parseYamlSegment("${option.projectRootPath}/segments/$segmentKey.yml")
val yamlSegment = parseYamlSegment("${configuration.segmentsDirectoryPath}/$segmentKey.yml")
val expected = it.expectedToMatch
val actual = segmentIsMatched(yamlSegment!!, it.context)
val passed = actual == expected
Expand Down
26 changes: 6 additions & 20 deletions src/main/kotlin/com/featurevisor/testRunner/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.featurevisor.testRunner

import com.featurevisor.sdk.FeaturevisorInstance
import com.featurevisor.sdk.InstanceOptions
import com.featurevisor.sdk.emptyDatafile
import com.featurevisor.types.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
Expand Down Expand Up @@ -237,29 +238,14 @@ fun checkJsonIsEquals(a: String, b: String): Boolean {
return map1 == map2
}

fun buildDataFileForBothEnvironments(projectRootPath: String): DataFile =
DataFile(
stagingDataFiles = buildDataFileForStaging(projectRootPath),
productionDataFiles = buildDataFileForProduction(projectRootPath)
)

fun buildDataFileForStaging(projectRootPath: String) = try {
getJsonForDataFile(environment = "staging", projectRootPath = projectRootPath)?.run {
convertToDataClass<DatafileContent>()
}
} catch (e: Exception) {
printMessageInRedColor("Unable to parse staging data file")
null
}

fun buildDataFileForProduction(projectRootPath: String) = try {
getJsonForDataFile(environment = "production", projectRootPath = projectRootPath)?.run {
fun buildDataFileAsPerEnvironment(projectRootPath: String,environment: String) = try {
getJsonForDataFile(environment = environment, projectRootPath = projectRootPath)?.run {
convertToDataClass<DatafileContent>()
}

} ?: emptyDatafile
} catch (e: Exception) {
printMessageInRedColor("Unable to parse production data file")
null
printMessageInRedColor("Unable to parse data file")
emptyDatafile
}

fun getDataFileContent(featureName: String, environment: String, projectRootPath: String) =
Expand Down
18 changes: 18 additions & 0 deletions src/main/kotlin/com/featurevisor/types/Types.kt
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,21 @@ data class DataFile(
val stagingDataFiles: DatafileContent? = null,
val productionDataFiles: DatafileContent? = null
)

@Serializable
data class Configuration(
val environments:List<String>,
val tags: List<String>,
val defaultBucketBy:String,
val prettyState:Boolean,
val prettyDatafile:Boolean,
val stringify:Boolean,
val featuresDirectoryPath:String,
val segmentsDirectoryPath:String,
val attributesDirectoryPath:String,
val groupsDirectoryPath:String,
val testsDirectoryPath:String,
val stateDirectoryPath:String,
val outputDirectoryPath:String,
val siteExportDirectoryPath:String
)

0 comments on commit 9c961d1

Please sign in to comment.