Skip to content

Commit

Permalink
Merge pull request #104 from speekha/develop
Browse files Browse the repository at this point in the history
Publish 1.3.0
  • Loading branch information
speekha committed Oct 21, 2020
2 parents 7ecc010 + 7278b0b commit 0a1b37c
Show file tree
Hide file tree
Showing 51 changed files with 406 additions and 322 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2.1
references:
container_config: &container_config
docker:
- image: circleci/android:api-29
- image: circleci/android:api-30

working_directory: ~/data

Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# HttpMocker

[![Kotlin](https://img.shields.io/badge/kotlin-1.3.61-blue.svg)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.4.10-blue.svg)](http://kotlinlang.org)
[![CircleCI](https://circleci.com/gh/speekha/httpmocker/tree/develop.svg?style=shield)](https://circleci.com/gh/speekha/httpmocker/tree/develop)
[![Download](https://api.bintray.com/packages/speekha/httpmocker/mocker/images/download.svg)](https://bintray.com/speekha/httpmocker/mocker/_latestVersion)

Expand All @@ -24,7 +24,7 @@ can be reused later.
## Current Version

```gradle
httpmocker_version = '1.2.0'
httpmocker_version = '1.3.0'
```

## Gradle
Expand Down Expand Up @@ -147,8 +147,12 @@ If your interceptor is disabled, it will not interfere with actual network calls
it will need to find scenarios to mock the HTTP calls. Dynamic mocks imply that you have to
provide the response for each request programmatically, which allows you to define stateful
responses (identical calls could lead to different answers based on what the user did in between
these calls). The response can be provided by implementing the `RequestCallback` interface or
you can simply provide a lambda function to do the computation.
these calls). The response can be provided as a `ResponseDescriptor` by implementing the
`RequestCallback` interface, or you can simply provide a lambda function to do the computation.

NB: If you use dynamic mocks, the `bodyFile` attribute of your `ResponseDescriptor` is not needed (it
will be ignored). Its only use is for static scenarios that could save the response body in a separate
file.

Another option is to use static mocks. Static mocks are scenarios stored as static files. Here is
an example for an Android app using static mocks, with a few more options:
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.2'
classpath 'com.android.tools.build:gradle:4.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
Expand Down Expand Up @@ -56,7 +56,7 @@ allprojects {

// Ktlint configuration for sub-projects
ktlint {
version = "0.34.2"
version = "0.39.0"
verbose = true
android = false
reporters {
Expand Down
2 changes: 1 addition & 1 deletion custom-adapter/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apply plugin: 'kotlin'

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

api project(':mocker')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package fr.speekha.httpmocker.custom.parser

import java.util.Locale
import java.util.*

internal class SimpleTypeParser(
private val handler: StringReader
Expand Down Expand Up @@ -47,6 +47,7 @@ internal class SimpleTypeParser(
private fun decodeString(value: String): String = value.drop(1)
.dropLast(1)
.replace("\\\"", "\"")
.replace("\\\\", "\\")

private fun parseBoolean(value: String): Boolean = when (value.toLowerCase(Locale.ROOT)) {
"true" -> true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal fun writeObjectFields(level: Int, vararg pairs: Pair<String, Any?>) =
postfix = closingBrace(level)
) { writePair(level + 1, it) }

internal fun String?.wrap() = this?.let { "\"${it.replace("\"", "\\\"")}\"" }
internal fun String?.wrap() = this?.let { "\"${it.replace("\\", "\\\\").replace("\"", "\\\"")}\"" }

internal fun Int?.wrap() = this?.toString()

Expand Down
10 changes: 5 additions & 5 deletions demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ apply plugin: 'kotlin-android-extensions'


android {
compileSdkVersion 29
compileSdkVersion 30
sourceSets {
main.kotlin.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "fr.speekha.httpmocker.demo"
minSdkVersion 21
targetSdkVersion 29
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -64,12 +64,12 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"

implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.core:core-ktx:1.2.0"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.core:core-ktx:1.3.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha05'
implementation 'com.google.android.material:material:1.2.0'

implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-jackson:$retrofit_version"
Expand Down
4 changes: 2 additions & 2 deletions demo/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

# For Jackson adapter
-keep class kotlin.Metadata { *; }
-keep class fr.speekha.httpmocker.jackson.* { *; }
-keep class fr.speekha.httpmocker.jackson.** { *; }

# For GSON adapter
-keep class fr.speekha.httpmocker.gson.* { *; }
-keep class fr.speekha.httpmocker.gson.** { *; }
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ class MainActivity : AppCompatActivity() {

private fun checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
checkSelfPermission(WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE), 1)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ class MainViewModelTest : ViewModelTest() {
viewModel.getData().observeForever(observer)

coEvery { mockService.listRepositoriesForOrganisation(org) } returns
listOf(Repo(id, repo, topContributor = contributor))
listOf(Repo(id, repo, topContributor = contributor))
coEvery { mockService.listContributorsForRepository(org, repo) } returns
listOf(User(login = contributor, contributions = contributions))
listOf(User(login = contributor, contributions = contributions))

viewModel.callService().join()
}
Expand Down Expand Up @@ -98,7 +98,7 @@ class MainViewModelTest : ViewModelTest() {
runBlocking {
viewModel.getData().observeForever(observer)
coEvery { mockService.listRepositoriesForOrganisation(org) } returns
listOf(Repo(id, repo, topContributor = contributor))
listOf(Repo(id, repo, topContributor = contributor))
coEvery {
mockService.listContributorsForRepository(
org,
Expand Down
2 changes: 1 addition & 1 deletion gradle/ktlint.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ apply plugin: "org.jlleitschuh.gradle.ktlint"

// Ktlint configuration for sub-projects
ktlint {
version = "0.34.2"
version = "0.39.0"
verbose = true
android = false
// reporters = [ReporterType.PLAIN, ReporterType.CHECKSTYLE]
Expand Down
28 changes: 14 additions & 14 deletions gradle/versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@
*/

ext {
httpmock_version = '1.2.0'
httpmock_version = '1.3.0'

kotlin_version = '1.3.71'
coroutines_version = '1.3.0'
jackson_version = '2.10.3'
kotlin_version = '1.4.10'
coroutines_version = '1.3.7'
jackson_version = '2.11.2'
gson_version = '2.8.6'
moshi_version = '1.9.2'
kotlinx_serialization_version = '0.20.0'
okhttp_version = '3.14.7'
retrofit_version = '2.6.0'
moshi_version = '1.11.0'
kotlinx_serialization_version = '1.0.0'
okhttp_version = '4.9.0'
retrofit_version = '2.9.0'
dokka_version = '0.9.18'
bintray_version = '1.8.4'
artifactory_version = '4.9.6'
slf4j_version = '1.7.26'
bintray_version = '1.8.5'
artifactory_version = '4.17.2'
slf4j_version = '1.7.28'
junit_version = '5.4.2'
mockito_version = '2.27.0'
mockito_kotlin_version = '2.1.0'
ktlint_version = '9.1.1'
mockito_version = '3.5.15'
mockito_kotlin_version = '2.2.0'
ktlint_version = '9.4.1'
}
6 changes: 3 additions & 3 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
# limitations under the License.
#

#Mon Aug 26 20:27:32 CEST 2019
#Wed Oct 07 21:11:42 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
zipStoreBase=GRADLE_USER_HOME
2 changes: 1 addition & 1 deletion gson-adapter/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apply plugin: 'kotlin'

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

api project(':mocker')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ class GsonMapper : Mapper {
private fun Gson.parse(json: String) =
fromJson<List<JsonMatcher>>(json, dataType) ?: emptyList()

override fun serialize(matchers: List<Matcher>): String = gson.toJson(matchers.map {
it.fromModel()
})
override fun serialize(matchers: List<Matcher>): String = gson.toJson(
matchers.map {
it.fromModel()
}
)

private class MatcherType : TypeToken<List<JsonMatcher>>()
}
2 changes: 1 addition & 1 deletion jackson-adapter/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apply plugin: 'kotlin'

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

api project(':mocker')

Expand Down
4 changes: 2 additions & 2 deletions kotlinx-adapter/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ repositories {
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlinx_serialization_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinx_serialization_version"

api project(':mocker')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ package fr.speekha.httpmocker.kotlinx
import fr.speekha.httpmocker.model.Matcher
import fr.speekha.httpmocker.serialization.JSON_FORMAT
import fr.speekha.httpmocker.serialization.Mapper
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.builtins.list
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.modules.EmptyModule
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.modules.EmptySerializersModule
import fr.speekha.httpmocker.kotlinx.model.Matcher as JsonMatcher

@UnstableDefault
/**
* A mapper using Kotlinx serialization to serialize/deserialize scenarios.
* The common JSON format available with other mappers is not compatible with Kotlinx Serialization,
Expand All @@ -36,6 +36,7 @@ import fr.speekha.httpmocker.kotlinx.model.Matcher as JsonMatcher
* @param formatInput transformation function to apply when reading JSON
* @param formatOutput transformation function to apply when writing JSON
*/
@ExperimentalSerializationApi
class KotlinxMapper(
private val formatInput: (String) -> String = { it },
private val formatOutput: (String) -> String = { it }
Expand All @@ -48,21 +49,21 @@ class KotlinxMapper(
prettyPrint = true
ignoreUnknownKeys = false
isLenient = false
unquotedPrint = false
indent = " "
prettyPrint = true
prettyPrintIndent = " "
useArrayPolymorphism = false
classDiscriminator = "type"
serialModule = EmptyModule
serializersModule = EmptySerializersModule
}

override fun deserialize(payload: String): List<Matcher> =
parseMatcherList(adapter.parseJson(formatInput(payload)))
parseMatcherList(adapter.parseToJsonElement(formatInput(payload)))

private fun parseMatcherList(json: JsonElement): List<Matcher> = json.jsonArray.map {
it.toMatcher()
}

override fun serialize(matchers: List<Matcher>): String = formatOutput(
adapter.stringify(JsonMatcher.serializer().list, matchers.map { JsonMatcher(it) })
adapter.encodeToString(ListSerializer(JsonMatcher.serializer()), matchers.map { JsonMatcher(it) })
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ import fr.speekha.httpmocker.serialization.REQUEST
import fr.speekha.httpmocker.serialization.RESPONSE
import fr.speekha.httpmocker.serialization.VALUE
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonLiteral
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import fr.speekha.httpmocker.model.Header as ModelHeader

internal fun JsonElement.toMatcher(): Matcher = Matcher(
Expand All @@ -51,20 +58,20 @@ internal fun JsonElement.toMatcher(): Matcher = Matcher(
)

private fun JsonElement.toRequest(): RequestDescriptor = RequestDescriptor(
jsonObject[EXACT_MATCH]?.primitive?.boolean ?: false,
jsonObject[EXACT_MATCH]?.jsonPrimitive?.boolean ?: false,
jsonObject[PROTOCOL]?.asNullableLiteral(),
jsonObject[METHOD]?.asNullableLiteral(),
jsonObject[HOST]?.asNullableLiteral(),
jsonObject[PORT]?.primitive?.int,
jsonObject[PORT]?.jsonPrimitive?.int,
jsonObject[PATH]?.asNullableLiteral(),
jsonObject[HEADERS].toHeaders(),
jsonObject[PARAMS].toParams(),
jsonObject[BODY]?.asNullableLiteral()
)

private fun JsonElement.toResponse(): ResponseDescriptor = ResponseDescriptor()
.update(this, DELAY) { copy(delay = it.primitive.long) }
.update(this, CODE) { copy(code = it.primitive.int) }
.update(this, DELAY) { copy(delay = it.jsonPrimitive.long) }
.update(this, CODE) { copy(code = it.jsonPrimitive.int) }
.update(this, MEDIA_TYPE) { copy(mediaType = it.asLiteral()) }
.update(this, HEADERS) { copy(headers = it.toHeaders()) }
.update(this, BODY) { copy(body = it.asLiteral()) }
Expand Down Expand Up @@ -92,6 +99,6 @@ private fun JsonElement?.toHeaders(): List<ModelHeader> = this?.jsonArray?.map {
)
} ?: listOf()

private fun JsonElement?.asLiteral(): String = (this as? JsonLiteral)?.body?.toString() ?: ""
private fun JsonElement?.asLiteral(): String = (this as? JsonPrimitive)?.contentOrNull ?: ""

private fun JsonElement?.asNullableLiteral(): String? = (this as? JsonLiteral)?.body?.toString()
private fun JsonElement?.asNullableLiteral(): String? = (this as? JsonPrimitive)?.contentOrNull
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal data class Header(
@SerialName(NAME)
val name: String?,
@SerialName(VALUE)
var value: String?
val value: String?
) {
constructor(model: Model) : this(model.name, model.value)
}
2 changes: 1 addition & 1 deletion mocker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
apply plugin: 'kotlin'

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
api "org.slf4j:slf4j-api:$slf4j_version"
}
Expand Down
Loading

0 comments on commit 0a1b37c

Please sign in to comment.