diff --git a/packages/glimmer-apollo/src/-private/query.ts b/packages/glimmer-apollo/src/-private/query.ts index 3bf0884..11b86ac 100644 --- a/packages/glimmer-apollo/src/-private/query.ts +++ b/packages/glimmer-apollo/src/-private/query.ts @@ -31,16 +31,16 @@ export interface QueryOptions export type QueryPositionalArgs< TData, TVariables extends OperationVariables = OperationVariables -> = [DocumentNode, QueryOptions?]; + > = [DocumentNode, QueryOptions?]; export class QueryResource< TData, TVariables extends OperationVariables = OperationVariables -> extends ObservableResource< + > extends ObservableResource< TData, TVariables, TemplateArgs> -> { + > { @tracked loading = true; @tracked error?: ApolloError; @tracked data: TData | undefined; @@ -50,6 +50,8 @@ export class QueryResource< #subscription?: ObservableSubscription; #previousPositionalArgs: typeof this.args.positional | undefined; + #firstPromiseReject: Function | undefined; + /** @internal */ async setup(): Promise { this.#previousPositionalArgs = this.args.positional; @@ -64,6 +66,7 @@ export class QueryResource< } let [promise, firstResolve, firstReject] = createPromise(); // eslint-disable-line prefer-const + this.#firstPromiseReject = firstReject; this.promise = promise; const observable = client.watchQuery({ query, @@ -82,9 +85,9 @@ export class QueryResource< }, (error) => { this.#onError(error); - if (firstReject) { - firstReject(); - firstReject = undefined; + if (this.#firstPromiseReject) { + this.#firstPromiseReject(); + this.#firstPromiseReject = undefined; } } ); @@ -112,6 +115,10 @@ export class QueryResource< if (this.#subscription) { this.#subscription.unsubscribe(); } + if (this.#firstPromiseReject) { + this.#firstPromiseReject(); + this.#firstPromiseReject = undefined; + } } settled(): Promise { diff --git a/packages/test-app/app/components/playground/experiment.hbs b/packages/test-app/app/components/playground/experiment.hbs index 3d49802..522ea79 100644 --- a/packages/test-app/app/components/playground/experiment.hbs +++ b/packages/test-app/app/components/playground/experiment.hbs @@ -1,4 +1,4 @@ -

+

User Info

diff --git a/packages/test-app/app/components/playground/experiment.ts b/packages/test-app/app/components/playground/experiment.ts index 6d70b5c..9017996 100644 --- a/packages/test-app/app/components/playground/experiment.ts +++ b/packages/test-app/app/components/playground/experiment.ts @@ -23,6 +23,7 @@ export default class PlaygroundExperiment extends Component { userInfo = useQuery(this, () => [ USER_INFO, { + variables: { id: '1-with-delay' }, errorPolicy: 'all', notifyOnNetworkStatusChange: true } diff --git a/packages/test-app/app/components/playground/index.hbs b/packages/test-app/app/components/playground/index.hbs index 20e11de..ddadb62 100644 --- a/packages/test-app/app/components/playground/index.hbs +++ b/packages/test-app/app/components/playground/index.hbs @@ -1,4 +1,4 @@ - diff --git a/packages/test-app/app/components/playground/index.ts b/packages/test-app/app/components/playground/index.ts index 87c9129..6dbee70 100644 --- a/packages/test-app/app/components/playground/index.ts +++ b/packages/test-app/app/components/playground/index.ts @@ -2,7 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; export default class Playground extends Component { - @tracked isExperimenting = true; + @tracked isExperimenting = false; toggle = (): void => { this.isExperimenting = !this.isExperimenting; diff --git a/packages/test-app/app/mocks/handlers.ts b/packages/test-app/app/mocks/handlers.ts index f62be70..167a64b 100644 --- a/packages/test-app/app/mocks/handlers.ts +++ b/packages/test-app/app/mocks/handlers.ts @@ -84,6 +84,16 @@ export const handlers = [ } }) ); + } else if (user && req.variables.id.includes('with-delay')) { + return res( + ctx.delay(300), + ctx.data({ + user: { + __typename: 'User', + ...user + } + }) + ); } else if (user) { return res( ctx.data({ diff --git a/packages/test-app/tests/integration/components/playground-test.ts b/packages/test-app/tests/integration/components/playground-test.ts new file mode 100644 index 0000000..b5c3d83 --- /dev/null +++ b/packages/test-app/tests/integration/components/playground-test.ts @@ -0,0 +1,18 @@ +import { hbs } from 'ember-cli-htmlbars'; +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { click, render, waitFor } from '@ember/test-helpers'; + +module('Integration | Components | Playground', function(hooks) { + setupRenderingTest(hooks); + + test('no waiters should be left behind when resource is teardown before resolving', async function(this, assert) { + await render(hbs``); + + click('[dates-test-id="toggle"]'); + await waitFor('[data-test-id="experiment"]', { timeout: 100 }); + + await click('[dates-test-id="toggle"]'); + assert.ok(true); + }); +});