Hello,
I set up a testing suite with ApolloTestingModuleand it worked ok so far. Recently, I added a fragment to my query I got the next error and my test fails.
WARN: 'You're using fragments in your queries, but either don't have the addTypename:
true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.
Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client
can accurately match fragments.'
HeadlessChrome 67.0.3396 (Mac OS X 10.13.5): Executed 56 of 70 SUCCESS (0 secs / 1.117 secs)
WARN: 'Could not find __typename on Fragment ', 'RepairCase', Object{id: '1', categoryId: '10.10.10', createdAt: '2018-06-29T12:00:00Z', ...}
HeadlessChrome 67.0.3396 (Mac OS X 10.13.5): Executed 56 of 70 SUCCESS (0 secs / 1.117 secs)
WARN: 'DEPRECATION WARNING: using fragments without __typename is unsupported behavior and will be removed in future versions of Apollo client. You should fix this and set addTypename to true now.'
HeadlessChrome 67.0.3396 (Mac OS X 10.13.5): Executed 56 of 70 SUCCESS (0 secs / 1.117 secs)
ERROR: 'WARNING: heuristic fragment matching going on!'
It doesn't depend on which query I use or which fragment I added. The test doesn't do any fancy
imports: [
ApolloTestingModule
],
...
backend = TestBed.get(ApolloTestingController);
...
backend.expectOne('xxx').flush(TEST_RESPONSE);
I'm using [email protected]
I think it's connected with https://github.com/apollographql/react-apollo/issues/1747
any update on this?
Could you create a test for it here?
https://github.com/fetis/apollo-angular/commit/da7007342eb1728b2a57328dd9826b5c2bb19b45
here's the test which reproduces the problem.
to see the warnings you have to run the tests directly cd packages/apollo-angular && yarn test:testing
I have same problem when I use ApolloTestingModule.
The warn message as below:
console.warn node_modules/apollo-cache-inmemory/lib/bundle.umd.js:33
You're using fragments in your queries, but either don't have the addTypename:
true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.
Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client
can accurately match fragments.
...
console.warn node_modules/apollo-cache-inmemory/lib/bundle.umd.js:35
DEPRECATION WARNING: using fragments without __typename is unsupported behavior and will be removed in future versions of Apollo client. You should fix this and set addTypename to true now.
Then I check the code in apollo-angular/testing/module.js and found that "addTypename" was false.
function ApolloTestingModule(apollo, backend) {
var link = new ApolloLink(function (operation) { return backend.handle(operation); });
var cache = new InMemoryCache({
addTypename: false,
});
apollo.create({ link: link, cache: cache });
}
I can not solved this problem. Anyone can help me ?
I'm going to work on a change soon. It will allow to use a custom configuration. I need to check what workaround might look like so you can solve the issue for now.
@fetis @wszhi
Here's how you can solve the problem thanks to the PR:
https://github.com/apollographql/apollo-angular/blob/ff3db3a0e6e68a2b0b0adfea57b3a03984b2058e/packages/apollo-angular/testing/tests/integration.spec.ts#L182-L230
1.3.0 is out!
@kamilkisiela your change solved the problem with addTypename being set to false with no way of changing it as pointed out by @wszhi, but it does not solve the issue from op because when you set addTypename to true, tests that were passing start to fail.
For example, this is the error I get when I set addTypename to true on one of my tests:
Expected $[0].selectionSet.selections[0].selectionSet.selections.length = 2 to equal 1.
Expected $[0].selectionSet.selections[0].selectionSet.selections[1] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
Expected $[1].selectionSet.selections.length = 6 to equal 5.
Expected $[1].selectionSet.selections[1].selectionSet.selections.length = 3 to equal 2.
Expected $[1].selectionSet.selections[1].selectionSet.selections[2] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
Expected $[1].selectionSet.selections[5] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
@adgoncal could you provide an example?
@kamilkisiela
import { Injectable } from '@angular/core';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';
import { Observable, from } from 'rxjs';
import { pluck } from 'rxjs/operators';
export interface FileType {
id: string;
name: string;
type: string;
extension: string;
createDate: string;
blob: string;
}
export const FileFragment = `
fragment fileFields on File {
id
name
type
extension
createDate
blob
}
`;
export const FileQuery = gql`
query files($directoryId: ID!) {
files(directoryId: $directoryId) {
...fileFields
}
}
${FileFragment}
`;
@Injectable({
providedIn: 'root'
})
export class ApolloTestService {
constructor(private apollo: Apollo) {}
getFiles(directoryId: string): Observable<FileType[]> {
const query = FileQuery;
const variables = {
directoryId,
};
const files$ = this.apollo.query<any>({ query, variables });
return from(files$).pipe(pluck('data', 'files'));
}
}
import { TestBed } from '@angular/core/testing';
import {
ApolloTestingModule,
ApolloTestingController,
APOLLO_TESTING_CACHE,
} from 'apollo-angular/testing';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { Observable, of } from 'rxjs';
import {
ApolloTestService,
FileType,
FileQuery,
} from './apollo-test.service';
describe('ApolloTestService', () => {
let service: ApolloTestService;
let backend: ApolloTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloTestingModule],
});
backend = TestBed.get(ApolloTestingController);
service = TestBed.get(ApolloTestService);
});
afterEach(() => {
backend.verify();
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('getFiles', () => {
it('should return Observable<FileType[]>', (done: DoneFn) => {
const directoryId = 'directory id';
const files: FileType[] = [
{
id: 'file id',
name: 'file name',
type: 'file type',
extension: 'ext',
createDate: new Date().toISOString(),
blob: 'blob value',
}
];
const op = {
query: FileQuery,
variables: {
directoryId,
},
operationName: 'files',
};
const files$ = service.getFiles(directoryId);
files$.subscribe({
next: result => {
expect(result).toEqual(files);
done();
},
error: e => {
done.fail(e);
},
});
backend
.expectOne(operation => {
expect(operation.operationName).toBe(op.operationName);
expect(operation.variables).toEqual(op.variables);
expect(operation.query.definitions).toEqual(op.query.definitions);
return true;
})
.flush({ data: { files } });
});
});
});
describe('ApolloTestService with custom cache', () => {
let service: ApolloTestService;
let backend: ApolloTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloTestingModule],
providers: [
{
provide: APOLLO_TESTING_CACHE,
useValue: new InMemoryCache({addTypename: true}),
},
],
});
backend = TestBed.get(ApolloTestingController);
service = TestBed.get(ApolloTestService);
});
afterEach(() => {
backend.verify();
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('getFiles', () => {
it('should return Observable<FileType[]>', (done: DoneFn) => {
const directoryId = 'directory id';
const files: FileType[] = [
{
id: 'file id',
name: 'file name',
type: 'file type',
extension: 'ext',
createDate: new Date().toISOString(),
blob: 'blob value',
}
];
const op = {
query: FileQuery,
variables: {
directoryId,
},
operationName: 'files',
};
const files$ = service.getFiles(directoryId);
files$.subscribe({
next: result => {
expect(result).toEqual(files);
done();
},
error: e => {
done.fail(e);
},
});
backend
.expectOne(operation => {
expect(operation.operationName).toBe(op.operationName);
expect(operation.variables).toEqual(op.variables);
expect(operation.query.definitions).toEqual(op.query.definitions);
return true;
})
.flush({ data: { files } });
});
});
});
$ ng test --watch=false --no-progress
06 10 2018 15:40:36.161:INFO [karma]: Karma v3.0.0 server started at http://0.0.0.0:9876/
06 10 2018 15:40:36.738:INFO [launcher]: Launching browser Chrome with unlimited concurrency
06 10 2018 15:40:36.745:INFO [launcher]: Starting browser Chrome
06 10 2018 15:40:42.388:INFO [Chrome 69.0.3497 (Windows 10 0.0.0)]: Connected on socket Vhf0Dc6zagXZW8tcAAAA with id 77258880
WARN: 'You're using fragments in your queries, but either don't have the addTypename:
true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.
Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client
can accurately match fragments.'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'You're using fragments in your queries, but either don't have the addTypename:
true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.
Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client
WARN: 'Could not find __typename on Fragment ', 'File', Object{id: 'file id', name: 'file name', type: 'file type', extension: 'ext', createDate: '2018-10-06T20:40:42.897Z', blob: 'blob value'}
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'Could not find __typename on Fragment ', 'File', Object{id: 'file id', name: 'file name', type: 'file type', extension: 'ext', createDate: '2018-10-06T20:40:42.897Z', blob: 'blob valuWARN: 'DEPRECATION WARNING: using fragments without __typename is unsupported behavior and will be removed in future versions of Apollo client. You should fix this and set addTypename to true now.'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'DEPRECATION WARNING: using fragments without __typename is unsupported behavior and will be removed in future versions of Apollo client. You should fix this and set addTypename to truERROR: 'WARNING: heuristic fragment matching going on!'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
ERROR: 'WARNING: heuristic fragment matching going on!'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'Missing field __typename in {
"id": "file id",
"name": "file name",
"type": "file type",
"extension": "ext",
"createDa'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'Missing field __typename in {
"id": "file id",
"name": "file name",
"type": "file type",
"extension": "ext",
WARN: 'Missing field __typename in {
"id": "file id",
"name": "file name",
"type": "file type",
"extension": "ext",
"createDa'
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 0 of 4 SUCCESS (0 secs / 0 secs)
WARN: 'Missing field __typename in {
"id": "file id",
"name": "file name",
"type": "file type",
"extension": "ext",
Chrome 69.0.3497 (Windows 10 0.0.0) ApolloTestService with custom cache getFiles should return Observable<FileType[]> FAILED
Expected $[0].selectionSet.selections[0].selectionSet.selections.length = 2 to equal 1.
Expected $[0].selectionSet.selections[0].selectionSet.selections[1] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
Expected $[1].selectionSet.selections.length = 7 to equal 6.
Expected $[1].selectionSet.selections[6] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
at eval (./src/app/apollo-test.service.spec.ts?:123:53)
at eval (./node_modules/apollo-angular/fesm5/ng.apollo.testing.js?:160:64)
at Array.filter (<anonymous>)
at ApolloTestingBackend._match (./node_modules/apollo-angular/fesm5/ng.apollo.testing.js?:160:30)
Failed: Cannot read property 'files' of null
TypeError: Cannot read property 'files' of null
at MapSubscriber.mapper [as project] (./node_modules/rxjs/_esm5/internal/operators/pluck.js?:21:32)
at MapSubscriber._next (./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
at MapSubscriber.Subscriber.next (./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18)
at eval (./node_modules/apollo-angular/fesm5/ng.apollo.js?:37:28)
at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:387:26)
at ProxyZoneSpec.onInvoke (./node_modules/zone.js/dist/zone-testing.js?:287:39)
at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:386:32)
at Zone.run (./node_modules/zone.js/dist/zone.js?:137:43)
at eval (./node_modules/zone.js/dist/zone.js?:871:34)
at ZoneDelegate.invokeTask (./node_modules/zone.js/dist/zone.js?:420:31)
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 4 of 4 (1 FAILED) (0 secs / 0.138 secs)
Chrome 69.0.3497 (Windows 10 0.0.0) ApolloTestService with custom cache getFiles should return Observable<FileType[]> FAILED
Expected $[0].selectionSet.selections[0].selectionSet.selections.length = 2 to equal 1.
Expected $[0].selectionSet.selections[0].selectionSet.selections[1] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
Expected $[1].selectionSet.selections.length = 7 to equal 6.
Expected $[1].selectionSet.selections[6] = Object({ name: Object({ value: '__typename', kind: 'Name' }), kind: 'Field' }) to equal undefined.
at eval (./src/app/apollo-test.service.spec.ts?:123:53)
at eval (./node_modules/apollo-angular/fesm5/ng.apollo.testing.js?:160:64)
at Array.filter (<anonymous>)
at ApolloTestingBackend._match (./node_modules/apollo-angular/fesm5/ng.apollo.testing.js?:160:30)
Failed: Cannot read property 'files' of null
TypeError: Cannot read property 'files' of null
at MapSubscriber.mapper [as project] (./node_modules/rxjs/_esm5/internal/operators/pluck.js?:21:32)
at MapSubscriber._next (./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
at MapSubscriber.Subscriber.next (./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18)
at eval (./node_modules/apollo-angular/fesm5/ng.apollo.js?:37:28)
at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:387:26)
at ProxyZoneSpec.onInvoke (./node_modules/zone.js/dist/zone-testing.js?:287:39)
at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:386:32)
at Zone.run (./node_modules/zone.js/dist/zone.js?:137:43)
at eval (./node_modules/zone.js/dist/zone.js?:871:34)
Chrome 69.0.3497 (Windows 10 0.0.0): Executed 4 of 4 (1 FAILED) (0.213 secs / 0.138 secs)
TOTAL: 1 FAILED, 3 SUCCESS
TOTAL: 1 FAILED, 3 SUCCESS
$ ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ â–³ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 6.2.4
Node: 10.10.0
OS: linux x64
Angular: 6.1.9
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.8.4
@angular-devkit/build-angular 0.8.4
@angular-devkit/build-optimizer 0.8.4
@angular-devkit/build-webpack 0.8.4
@angular-devkit/core 0.8.4
@angular-devkit/schematics 0.8.4
@angular/cli 6.2.4
@ngtools/webpack 6.2.4
@schematics/angular 0.8.4
@schematics/update 0.8.4
rxjs 6.2.2
typescript 2.9.2
webpack 4.20.2
@adgoncal if you turned addTypename on why you don't define __typename fields in tests?
@kamilkisiela I thought the whole point was to not have to do that in tests.
Also, if I add __typename I will not be able to use type check on const files: FileType[] = [ ... ] because __typename is not a property in FileType
Most helpful comment
@kamilkisiela I thought the whole point was to not have to do that in tests.
Also, if I add
__typenameI will not be able to use type check onconst files: FileType[] = [ ... ]because__typenameis not a property inFileType