All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.apollographql.apollo.testing.TestNetworkTransport.kt Maven / Gradle / Ivy

package com.apollographql.apollo.testing

import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.annotations.ApolloExperimental
import com.apollographql.apollo.api.ApolloRequest
import com.apollographql.apollo.api.ApolloResponse
import com.apollographql.apollo.api.Error
import com.apollographql.apollo.api.Operation
import com.apollographql.apollo.exception.ApolloNetworkException
import com.apollographql.apollo.network.NetworkTransport
import com.benasher44.uuid.uuid4
import kotlinx.atomicfu.locks.reentrantLock
import kotlinx.atomicfu.locks.withLock
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.yield

private sealed interface TestResponse {
  object NetworkError : TestResponse
  class Response(val response: ApolloResponse) : TestResponse
}

@ApolloExperimental
class QueueTestNetworkTransport : NetworkTransport {
  private val lock = reentrantLock()
  private val queue = ArrayDeque()

  override fun  execute(request: ApolloRequest): Flow> {
    return flow {
      // "Emulate" a network call
      yield()

      val response = lock.withLock { queue.removeFirstOrNull() } ?: error("No more responses in queue")

      val apolloResponse = when (response) {
        is TestResponse.NetworkError -> {
          ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid)
              .exception(exception = ApolloNetworkException("Network error queued in QueueTestNetworkTransport"))
              .build()
        }

        is TestResponse.Response -> {
          @Suppress("UNCHECKED_CAST")
          response.response as ApolloResponse
        }
      }

      emit(apolloResponse.newBuilder().isLast(true).build())
    }
  }

  fun  enqueue(response: ApolloResponse) {
    lock.withLock {
      queue.add(TestResponse.Response(response))
    }
  }

  fun enqueueNetworkError() {
    lock.withLock {
      queue.add(TestResponse.NetworkError)
    }
  }

  override fun dispose() {}
}

@ApolloExperimental
class MapTestNetworkTransport : NetworkTransport {
  private val lock = reentrantLock()
  private val operationsToResponses = mutableMapOf, TestResponse>()

  override fun  execute(request: ApolloRequest): Flow> {
    return flow {
      // "Emulate" a network call
      yield()

      val response = lock.withLock { operationsToResponses[request.operation] }
          ?: error("No response registered for operation ${request.operation}")

      val apolloResponse = when (response) {
        is TestResponse.NetworkError -> {
          ApolloResponse.Builder(operation = request.operation, requestUuid = request.requestUuid)
              .exception(exception = ApolloNetworkException("Network error registered in MapTestNetworkTransport"))
              .build()
        }

        is TestResponse.Response -> {
          @Suppress("UNCHECKED_CAST")
          response.response as ApolloResponse
        }
      }

      emit(apolloResponse.newBuilder().isLast(true).build())
    }
  }

  fun  register(operation: Operation, response: ApolloResponse) {
    lock.withLock {
      operationsToResponses[operation] = TestResponse.Response(response)
    }
  }

  fun  registerNetworkError(operation: Operation) {
    lock.withLock {
      operationsToResponses[operation] = TestResponse.NetworkError
    }
  }

  override fun dispose() {}
}

@ApolloExperimental
fun  ApolloClient.enqueueTestResponse(response: ApolloResponse) =
    (networkTransport as? QueueTestNetworkTransport)?.enqueue(response)
        ?: error("Apollo: ApolloClient.enqueueTestResponse() can be used only with QueueTestNetworkTransport")

@ApolloExperimental
fun  ApolloClient.enqueueTestResponse(
    operation: Operation,
    data: D? = null,
    errors: List? = null,
) = enqueueTestResponse(
    ApolloResponse.Builder(
        operation = operation,
        requestUuid = uuid4(),
    )
        .data(data)
        .errors(errors)
        .build()
)

@ApolloExperimental
fun ApolloClient.enqueueTestNetworkError() =
    (networkTransport as? QueueTestNetworkTransport)?.enqueueNetworkError()
        ?: error("Apollo: ApolloClient.enqueueTestNetworkError() can be used only with QueueTestNetworkTransport")


@ApolloExperimental
fun  ApolloClient.registerTestResponse(
    operation: Operation,
    response: ApolloResponse,
) = (networkTransport as? MapTestNetworkTransport)?.register(operation, response)
    ?: error("Apollo: ApolloClient.registerTestResponse() can be used only with MapTestNetworkTransport")

@ApolloExperimental
fun  ApolloClient.registerTestResponse(
    operation: Operation,
    data: D? = null,
    errors: List? = null,
) = registerTestResponse(
    operation,
    ApolloResponse.Builder(
        operation = operation,
        requestUuid = uuid4(),
    )
        .data(data)
        .errors(errors)
        .build()
)

@ApolloExperimental
fun  ApolloClient.registerTestNetworkError(operation: Operation) =
    (networkTransport as? MapTestNetworkTransport)?.registerNetworkError(operation)
        ?: error("Apollo: ApolloClient.registerTestNetworkError() can be used only with MapTestNetworkTransport")




© 2015 - 2025 Weber Informatics LLC | Privacy Policy