@@ -3,18 +3,23 @@ package test
33import app.cash.turbine.test
44import app.cash.turbine.withTurbineTimeout
55import com.apollographql.apollo.ApolloClient
6+ import com.apollographql.apollo.api.ApolloRequest
7+ import com.apollographql.apollo.api.ApolloResponse
68import com.apollographql.apollo.api.Error
9+ import com.apollographql.apollo.api.Operation
710import com.apollographql.apollo.exception.ApolloGraphQLException
811import com.apollographql.apollo.exception.CacheMissException
9- import com.apollographql.cache.normalized.FetchPolicy.CacheFirst
12+ import com.apollographql.apollo.interceptor.ApolloInterceptor
13+ import com.apollographql.apollo.interceptor.ApolloInterceptorChain
1014import com.apollographql.cache.normalized.api.CacheHeaders
1115import com.apollographql.cache.normalized.api.NormalizedCache
1216import com.apollographql.cache.normalized.api.NormalizedCacheFactory
1317import com.apollographql.cache.normalized.api.Record
1418import com.apollographql.cache.normalized.api.RecordMerger
19+ import com.apollographql.cache.normalized.fetchFromCache
1520import com.apollographql.cache.normalized.isFromCache
1621import com.apollographql.cache.normalized.memory.MemoryCacheFactory
17- import com.apollographql.cache.normalized.refetchPolicy
22+ import com.apollographql.cache.normalized.refetchPolicyInterceptor
1823import com.apollographql.cache.normalized.testing.assertErrorsEquals
1924import com.apollographql.cache.normalized.testing.runTest
2025import com.apollographql.cache.normalized.watch
@@ -23,6 +28,10 @@ import com.apollographql.mockserver.MockResponse
2328import com.apollographql.mockserver.MockServer
2429import com.apollographql.mockserver.MockServerHandler
2530import kotlinx.coroutines.delay
31+ import kotlinx.coroutines.flow.Flow
32+ import kotlinx.coroutines.flow.emitAll
33+ import kotlinx.coroutines.flow.flow
34+ import kotlinx.coroutines.flow.single
2635import okio.use
2736import test.cache.Cache.cache
2837import kotlin.random.Random
@@ -74,7 +83,7 @@ class FetchPolicyTest {
7483 .build()
7584 .use { apolloClient ->
7685 apolloClient.query(MeQuery ())
77- .refetchPolicy( CacheFirst )
86+ .refetchPolicyInterceptor( PartialCacheFirstInterceptor )
7887 .watch()
7988 .test {
8089 // 1. response from the cache (cache miss)
@@ -128,3 +137,27 @@ private fun AsyncCacheFactory(): NormalizedCacheFactory = object : NormalizedCac
128137 }
129138 }
130139}
140+
141+ /* *
142+ * An interceptor that emits the response from the cache first, and if there was a cache miss on the response, emits the response(s) from
143+ * the network.
144+ * If there are no exception on the cache response or there is an exception which is not a cache miss (server error), no network request is
145+ * made.
146+ */
147+ val PartialCacheFirstInterceptor = object : ApolloInterceptor {
148+ override fun <D : Operation .Data > intercept (request : ApolloRequest <D >, chain : ApolloInterceptorChain ): Flow <ApolloResponse <D >> {
149+ return flow {
150+ val cacheResponse = chain.proceed(
151+ request = request
152+ .newBuilder()
153+ .fetchFromCache(true )
154+ .build(),
155+ ).single()
156+ val isCacheMiss = cacheResponse.exception == CacheMissException
157+ emit(cacheResponse.newBuilder().isLast(! isCacheMiss).build())
158+ if (isCacheMiss) {
159+ emitAll(chain.proceed(request = request))
160+ }
161+ }
162+ }
163+ }
0 commit comments