Skip to content

Commit ef92176

Browse files
authored
Revert changing test to fetch from the network to be any exception (#352)
* Revert changing test to fetch from the network to be any exception * Revert test changes
1 parent 9b42afd commit ef92176

4 files changed

Lines changed: 48 additions & 12 deletions

File tree

normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/FetchPolicy.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import com.apollographql.apollo.ApolloCall
44

55
enum class FetchPolicy {
66
/**
7-
* Emit the response from the cache first, and if there was a cache miss, emit the response(s) from the network.
7+
* Emit the response from the cache first, and if there was an exception on the response (e.g. a cache miss or a cached server error),
8+
* emits the response(s) from the network.
89
*
9-
* This is the default behaviour.
10+
* This is the default behavior.
1011
*/
1112
CacheFirst,
1213

normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/FetchPolicyInterceptors.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import kotlinx.coroutines.flow.onEach
2222
import kotlinx.coroutines.flow.single
2323

2424
/**
25-
* An interceptor that emits the response from the cache first, and if there was a cache miss, emits the response(s) from the network.
25+
* An interceptor that emits the response from the cache first, and if there was an exception on the response (e.g. a cache miss or a cached
26+
* server error), emits the response(s) from the network.
2627
*
2728
* This is the default cache policy interceptor.
2829
*
@@ -43,11 +44,8 @@ val DefaultFetchPolicyInterceptor = object : ApolloInterceptor {
4344
.fetchFromCache(true)
4445
.build(),
4546
).single()
46-
emit(
47-
cacheResponse.newBuilder().isLast(request.onlyIfCached || cacheResponse.exception == null)
48-
.build(),
49-
)
50-
if (cacheResponse.exception !is CacheMissException) {
47+
emit(cacheResponse.newBuilder().isLast(request.onlyIfCached || cacheResponse.exception == null).build())
48+
if (cacheResponse.exception == null) {
5149
return@flow
5250
}
5351
}

tests/defer/src/commonTest/kotlin/test/DeferNormalizedCacheTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.apollographql.apollo.api.Error
77
import com.apollographql.apollo.api.Operation
88
import com.apollographql.apollo.exception.ApolloException
99
import com.apollographql.apollo.exception.ApolloGraphQLException
10+
import com.apollographql.apollo.exception.ApolloHttpException
1011
import com.apollographql.apollo.exception.ApolloNetworkException
1112
import com.apollographql.apollo.exception.CacheMissException
1213
import com.apollographql.apollo.network.NetworkTransport
@@ -453,10 +454,13 @@ class DeferNormalizedCacheTest {
453454
)
454455
assertResponseListEquals(networkExpected, networkActual)
455456

456-
// The error was stored in the cache and is surfaced as an exception
457+
mockServer.enqueueError(statusCode = 500)
458+
// Because of the error we fallback to the network (which also fails)
457459
val exception = apolloClient.query(WithFragmentSpreadsQuery()).execute().exception
458460
check(exception is ApolloGraphQLException)
461+
assertIs<ApolloHttpException>(exception.suppressedExceptions.first())
459462
assertEquals("GraphQL error: 'Cannot resolve isColor'", exception.message)
463+
mockServer.awaitRequest()
460464
}
461465

462466
@Test

tests/fetch-policy/src/commonTest/kotlin/test/FetchPolicyTest.kt

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@ package test
33
import app.cash.turbine.test
44
import app.cash.turbine.withTurbineTimeout
55
import com.apollographql.apollo.ApolloClient
6+
import com.apollographql.apollo.api.ApolloRequest
7+
import com.apollographql.apollo.api.ApolloResponse
68
import com.apollographql.apollo.api.Error
9+
import com.apollographql.apollo.api.Operation
710
import com.apollographql.apollo.exception.ApolloGraphQLException
811
import 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
1014
import com.apollographql.cache.normalized.api.CacheHeaders
1115
import com.apollographql.cache.normalized.api.NormalizedCache
1216
import com.apollographql.cache.normalized.api.NormalizedCacheFactory
1317
import com.apollographql.cache.normalized.api.Record
1418
import com.apollographql.cache.normalized.api.RecordMerger
19+
import com.apollographql.cache.normalized.fetchFromCache
1520
import com.apollographql.cache.normalized.isFromCache
1621
import com.apollographql.cache.normalized.memory.MemoryCacheFactory
17-
import com.apollographql.cache.normalized.refetchPolicy
22+
import com.apollographql.cache.normalized.refetchPolicyInterceptor
1823
import com.apollographql.cache.normalized.testing.assertErrorsEquals
1924
import com.apollographql.cache.normalized.testing.runTest
2025
import com.apollographql.cache.normalized.watch
@@ -23,6 +28,10 @@ import com.apollographql.mockserver.MockResponse
2328
import com.apollographql.mockserver.MockServer
2429
import com.apollographql.mockserver.MockServerHandler
2530
import 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
2635
import okio.use
2736
import test.cache.Cache.cache
2837
import 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

Comments
 (0)