3.4.* introduces a regression on the `merge` policy
See original GitHub issueIntended outcome:
The 3.4.* versions introduce a regression on the merge
policy
Actual outcome: The merge custom policy should receive correct parameters
How to reproduce the issue:
Here a unit test:
import { gql, InMemoryCache, useQuery } from '@apollo/client'
import { MockedProvider } from '@apollo/client/testing'
import { render, screen, waitFor } from '@testing-library/react'
import faker from 'faker'
const cache = new InMemoryCache({
typePolicies: {
Country: {
fields: {
cities: {
keyArgs: ['size'],
merge(existing, incoming, { args }) {
console.log(existing, incoming, { args })
if (!args) return incoming
const items = existing ? existing.slice(0) : []
const offset = args.offset ?? 0
for (let i = 0; i < incoming.length; ++i) {
items[offset + i] = incoming[i]
}
return items
},
},
},
},
CityInfo: {
merge: true,
},
},
})
const GET_COUNTRIES = gql`
query GetCountries {
countries {
id
...WithSmallCities
...WithAirQuality
}
}
fragment WithSmallCities on Country {
biggestCity {
id
}
smallCities: cities(size: SMALL) {
id
}
}
fragment WithAirQuality on Country {
biggestCity {
id
info {
airQuality
}
}
}
`
function Test() {
const { data } = useQuery(GET_COUNTRIES)
return <div data-testid="countryNumber">{data?.countries.length}</div>
}
it('should render without error', async () => {
const countries = [
{
__typename: 'Country',
id: faker.datatype.uuid(),
biggestCity: {
__typename: 'City',
id: faker.datatype.uuid(),
info: {
__typename: 'CityInfo',
airQuality: faker.datatype.number(),
},
},
smallCities: [
{
__typename: 'City',
id: faker.datatype.uuid(),
},
],
},
]
const mock = { request: { query: GET_COUNTRIES }, result: { data: { countries } } }
render(
<MockedProvider cache={cache} mocks={[mock]} resolvers={{}}>
<Test />
</MockedProvider>,
)
await waitFor(() => {
const element = screen.getByTestId('countryNumber')
expect(element).toHaveTextContent(countries.length.toString())
})
})
If you try to run this test, you will have this error Uncaught [TypeError: existing.slice is not a function]
, since we receive these arguments into the merge function:
{ __ref: 'City:a44cfd2e-c50f-4fcf-924d-d8e275c8df07' }
as existing
{ id: 'a44cfd2e-c50f-4fcf-924d-d8e275c8df07', __typename: 'City', info: { __typename: 'CityInfo', airQuality: 20807 } }
as incoming
We should have:
undefined
as existing
{ __ref: 'City:a44cfd2e-c50f-4fcf-924d-d8e275c8df07' }
as incoming
FYI If we delete CityInfo: { merge: true }
from the cache configuration, it works.
Versions It works with 3.3.21 but not with the new 3.4.* versions
Issue Analytics
- State:
- Created 2 years ago
- Reactions:3
- Comments:5 (4 by maintainers)
Top GitHub Comments
@Grmiade (and @anark) Thanks for the reproduction! This should be fixed in
@apollo/client@3.4.7
(just published).It also works on our side. Thanks a lot for the reactivity 💪