Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,40 @@ jobs:

- name: Generated API reference is up to date
run: git diff --exit-code packages/docs/api

test-vue-rc:
runs-on: ubuntu-latest
name: Test against Vue release candidate

steps:
- name: Set alternate npm integrity keys
run: |
echo COREPACK_INTEGRITY_KEYS="$(curl https://registry.npmjs.org/-/npm/v1/keys | jq -c '{npm: .keys}')" >> $GITHUB_ENV
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm

- name: Resolve the Vue release candidate
run: |
VUE_RC="$(npm view vue dist-tags.rc)"
echo "Testing against Vue $VUE_RC"
# Pinned to the resolved version rather than the `rc` tag so every package in the
# tree lands on one Vue — two copies mean two reactive graphs and bogus failures.
npm pkg set \
"pnpm.overrides.vue=$VUE_RC" \
"pnpm.overrides.@vue/reactivity=$VUE_RC" \
"pnpm.overrides.@vue/runtime-core=$VUE_RC" \
"pnpm.overrides.@vue/runtime-dom=$VUE_RC" \
"pnpm.overrides.@vue/server-renderer=$VUE_RC" \
"pnpm.overrides.@vue/shared=$VUE_RC"

- run: pnpm install --no-frozen-lockfile

- name: Build
run: pnpm run build

- name: Tests
run: pnpm run test
39 changes: 39 additions & 0 deletions packages/vue-apollo-composable/src/useQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,45 @@ describe('useQuery', () => {

wrapper.unmount()
})

it('should start with the resolved variables when enabled and variables land in the same tick', async () => {
const spy = vi.spyOn(apolloClient, 'watchQuery')

const TestComponent = defineComponent({
setup() {
const open = ref(false)
const { current, variables } = useQuery(ECHO_QUERY, () =>
!open.value
? { enabled: false }
: { variables: { message: 'hello' }, fetchPolicy: 'no-cache' as const })

return { current, variables, open }
},
render() {
return h('div', this.current.resultState === 'complete' ? this.current.result.echo : 'no result')
},
})

const wrapper = mount(TestComponent, {
global: { provide: { [DefaultApolloClient]: apolloClient } },
})

expect(spy).not.toHaveBeenCalled()

// One write turns the query on and gives it its variables.
wrapper.vm.open = true

expect(spy.mock.calls[0]?.[0].variables).toEqual({ message: 'hello' })
expect(wrapper.vm.variables).toEqual({ message: 'hello' })
expect(wrapper.vm.current.loading).toBe(true)

await until(() => wrapper.vm.current.resultState).toBe('complete', { timeout: 200 })
expect(wrapper.find('div').text()).toBe('hello')
expect(wrapper.vm.current.loading).toBe(false)

spy.mockRestore()
wrapper.unmount()
})
// #endregion

// #region Lifecycle
Expand Down
17 changes: 13 additions & 4 deletions packages/vue-apollo-composable/src/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1064,8 +1064,15 @@ export function useQueryImpl<
return result as TVariables
})

/** One write, so a re-entrant sync watcher cannot catch half a commit (Vue 3.6). */
const commitState = shallowRef({ variables: variables.value, committing: false })

/** The actual variables sent to Apollo (may be delayed by debounce/throttle) */
const currentVariables = shallowRef(variables.value)
const currentVariables = computed<TVariables>({
get: () => commitState.value.variables,
// Writable for compat's `load(document, variables)`, which pushes variables in by hand.
set: variables => commitState.value = { ...commitState.value, variables },
})

/**
* `true` while `variables` have moved ahead of what has actually been handed to Apollo,
Expand All @@ -1083,7 +1090,10 @@ export function useQueryImpl<
* Bridges the gap between `pending` clearing (on write) and `loading` being set on the
* next flush, when the watcher below reobserves.
*/
const isCommitting = ref(false)
const isCommitting = computed<boolean>({
get: () => commitState.value.committing,
set: committing => commitState.value = { ...commitState.value, committing },
})

function commitVariables(newVariables: TVariables) {
if (equal(newVariables, currentVariables.value)) {
Expand All @@ -1092,8 +1102,7 @@ export function useQueryImpl<
return
}

isCommitting.value = true
currentVariables.value = newVariables
commitState.value = { variables: newVariables, committing: true }
}

const setDebouncedVariables = useDebounceFn(
Expand Down
Loading