Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tracking to the returned result object when assigning data #399

Merged
merged 2 commits into from
Jun 16, 2021
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
20 changes: 18 additions & 2 deletions addon/services/apollo.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Ember from 'ember';
import { get, set, setProperties } from '@ember/object';
import { get, set, setProperties, defineProperty } from '@ember/object';
import { sendEvent } from '@ember/object/events';
import RSVP from 'rsvp';
import Service from '@ember/service';
Expand All @@ -16,6 +16,7 @@ import { isNone, isPresent } from '@ember/utils';
import { run } from '@ember/runloop';
import { QueryManager } from '../index';
import { waitForPromise } from '@ember/test-waiters';
import { tracked } from '@glimmer/tracking';

const apolloObservableWeakMap = new WeakMap();
const apolloUnsubscribeWeakMap = new WeakMap();
Expand Down Expand Up @@ -46,6 +47,20 @@ class EmberApolloSubscription {
}
}

class TrackedObject {
constructor() {
defineProperty(this, 'setUnknownProperty', {
configurable: false,
enumerable: false,
value: function (key, value) {
defineProperty(this, key, tracked());
this[key] = value;
},
writable: false,
});
}
}

function extractNewData(resultKey, { data, loading }) {
if (loading && isNone(data)) {
// This happens when the cache has no data and the data is still loading
Expand Down Expand Up @@ -75,7 +90,8 @@ function newDataFunc(observable, resultKey, resolve, unsubscribeFn = null) {
if (isArray(dataToSend)) {
obj = A([...dataToSend]);
} else {
obj = { ...dataToSend };
obj = new TrackedObject();
setProperties(obj, dataToSend);
}

if (!apolloObservableWeakMap.has(obj)) {
Expand Down
25 changes: 24 additions & 1 deletion tests/acceptance/watch-query-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ module('Acceptance | watch query', function (hooks) {
posterPath: '/dM2w364MScsjFf8pfMbaWUcWrR.jpg',
overview: 'lorem',
releaseDate: '1994-10-14',
reviews: {
edges: [],
__typename: 'ReviewsConnection',
},
__typename: 'Movie',
};

const mockReviews = {
edges: [
{
node: {
stars: 5,
__typename: 'Review',
},
__typename: 'ReviewEdge',
},
],
__typename: 'ReviewsConnection',
};

test('data should be updated when executing a mutation', async function (assert) {
Expand Down Expand Up @@ -64,7 +82,10 @@ module('Acceptance | watch query', function (hooks) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(
Object.assign({}, mockMovie, { title: 'The Godfather' })
Object.assign({}, mockMovie, {
title: 'The Godfather',
reviews: mockReviews,
})
);
}, 200);
});
Expand All @@ -81,11 +102,13 @@ module('Acceptance | watch query', function (hooks) {
assert.equal(currentURL(), '/movie/680');

assert.dom('.movie-title').hasText('Pulp Fiction');
assert.dom('.movie-reviews').hasText('No reviews');

isRefetch = true;
await click('.refetch-data-using-observable');

assert.dom('.movie-title').hasText('The Godfather');
assert.dom('.movie-reviews').hasText('5 stars');
});

test('refetch using reoute refresh should update template', async function (assert) {
Expand Down
9 changes: 9 additions & 0 deletions tests/dummy/app/controllers/movie.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Controller from '@ember/controller';

export default class MovieController extends Controller {
get reviews() {
return this.model.movie.reviews.edges.map((edge) => {
return edge.node;
});
}
}
7 changes: 7 additions & 0 deletions tests/dummy/app/gql/queries/movie.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,12 @@ query GetMovie($id: ID!) {
voteAverage
posterPath
releaseDate
reviews {
edges {
node {
stars
}
}
}
}
}
4 changes: 4 additions & 0 deletions tests/dummy/app/instance-initializers/mock-graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ function startPretender() {
Date() {
return '2019-09-28';
},

Int() {
return 5;
},
};

let schema = makeExecutableSchema({ typeDefs: schemaString, resolvers });
Expand Down
9 changes: 9 additions & 0 deletions tests/dummy/app/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Movie {
voteAverage: Float
posterPath: String
releaseDate: Date
reviews: ReviewsConnection!
}

# Represents a review for a movie
Expand All @@ -35,6 +36,14 @@ type Review {
commentary: String
}

type ReviewEdge {
node: Review!
}

type ReviewsConnection {
edges: [ReviewEdge]!
}

# The input object sent when someone is creating a new review
input ReviewInput {
# 0-5 stars
Expand Down
8 changes: 8 additions & 0 deletions tests/dummy/app/templates/movie.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@
</div>

<MovieDetail @movie={{this.model.movie}} />

<div class="movie-reviews">
{{#each this.reviews as |review|}}
<p>{{review.stars}} stars</p>
{{else}}
<p>No reviews</p>
{{/each}}
</div>