carbon-design-system / carbon-design-system/carbon-tutorial-angular

Step 3 - [SOLVED] Everything that goes wrong after adding Apollo

Open
#607 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
20
Forks
883
PR merge metrics
No merged PRs in 30d

Description

I created this ticket to help fellow coders/learners with the issues I faced with completing step 3.

Many of you may not face any such issue depending on the version of node, angular, and other packages, so first thing first, here's my package.json.
```
node --version
v14.14.0

npm -version
6.14.8
```

**package.json**
```
{
"name": "carbon-angular-starter",
"version": "0.1.0",
"license": "",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --aot",
"test": "ng test",
"test:once": "ng test --watch=false",
"lint": "ng lint",
"e2e": "ng e2e"
},
"engines": {
"node": ">= 10.9"
},
"private": true,
"dependencies": {
"@angular/animations": "^8.2.0",
"@angular/common": "^8.2.0",
"@angular/compiler": "^8.2.0",
"@angular/core": "^8.2.0",
"@angular/forms": "^8.2.0",
"@angular/platform-browser": "^8.2.0",
"@angular/platform-browser-dynamic": "^8.2.0",
"@angular/router": "^8.2.0",
"@carbon/icons-angular": "^10.4.0",
"apollo-angular": "^2.0.4",
"carbon-components": "^10.7.0",
"carbon-components-angular": "^3.21.2",
"core-js": "^2.5.2",
"rxjs": "^6.4.0",
"tslib": "^1.9.0",
"zone.js": "~0.9.1",
"@apollo/client": "^3.0.0",
"graphql": "^15.0.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.802.1",
"@angular/cli": "^8.2.1",
"@angular/compiler-cli": "^8.2.0",
"@types/graphql": "^14.5.0",
"@types/jasmine": "^2.8.2",
"@types/node": "~8.0.53",
"codelyzer": "^5.0.1",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^3.1.1",
"karma-chrome-launcher": "~2.2.0",
"karma-cli": "2.0.0",
"karma-coverage-istanbul-reporter": "^2.0.5",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"node-sass": "^4.12.0",
"postcss-loader": "3.0.0",
"protractor": "^5.4.2",
"ts-node": "~8.0.3",
"tslint": "^5.15.0",
"typescript": "3.5.3"
}
}

```
1. The first issue I faced was with the following few errors, in no particular order. The code won't build.

```
ERROR in ../node_modules/@apollo/client/core/ObservableQuery.d.ts:22:9 - error TS1086: An accessor cannot be declared in an ambient context.

22 get variables(): TVariables | undefined;
~~~~~~~~~
../node_modules/@apollo/client/utilities/observables/Observable.d.ts:1:8 - error TS1259: Module '"/Users/pooshonbanerjee/Documents/Pooshon/IBM Projects/2020/IBM Carbon Design - Angular/carbon-tutorial-angular/node_modules/@types/zen-observable/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

1 import Observable from 'zen-observable';
~~~~~~~~~~

../node_modules/@types/zen-observable/index.d.ts:69:1
69 export = Observable;
~~~~~~~~~~~~~~~~~~~~
This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
../node_modules/apollo-angular/apollo.d.ts:32:9 - error TS1086: An accessor cannot be declared in an ambient context.

32 get client(): ApolloClient;
~~~~~~
../node_modules/apollo-angular/apollo.d.ts:39:9 - error TS1086: An accessor cannot be declared in an ambient context.

39 set client(client: ApolloClient);
~~~~~~
../node_modules/graphql/subscription/subscribe.d.ts:41:12 - error TS2304: Cannot find name 'AsyncIterableIterator'.

41 ): Promise | ExecutionResult>;
~~~~~~~~~~~~~~~~~~~~~
../node_modules/graphql/subscription/subscribe.d.ts:52:12 - error TS2304: Cannot find name 'AsyncIterableIterator'.

52 ): Promise | ExecutionResult>;
~~~~~~~~~~~~~~~~~~~~~
../node_modules/graphql/subscription/subscribe.d.ts:80:12 - error TS2304: Cannot find name 'AsyncIterable'.

80 ): Promise | ExecutionResult>;
~~~~~~~~~~~~~

```
To solve this you have to modify the `typings.d.ts` file like it said on the tutorial for step 3, by commenting the module variable declaration.

But the next part about modifying `tsconfig.json` doesn't work since angular cli >= 7 ignores that file, so instead you have to make the following changes in the `tsconfig.app.json`.

`allowSyntheticDefaultImports, esModuleInterop, strictNullChecks, skipLibCheck, esnext.asynciterable`

```
{
"compilerOptions": {
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"strictNullChecks": false,
"skipLibCheck": true,
"lib": [
"es2016",
"dom",
"esnext.asynciterable"
],
"outDir": "../out-tsc/app",
"target": "es2015",
"module": "esnext",
"baseUrl": "",
"types": []
},
"include": [
"**/*"
],
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
```
This will get the code to build with no errors, but that won't be the end of it. When you run `ng serve`, you will see that the `/repo` route will come up blank and the dev console will show a long list of errors, beginning with `No provider for Apollo!`.

To solve this, do the following, and this is not mentioned in the training anywhere:

**graphql.modue.ts**

```
import { NgModule } from '@angular/core';
import { APOLLO_OPTIONS } from 'apollo-angular';
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
// import { InMemoryCache } from '@apollo/client/core';
import { Apollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { environment } from '../environments/environment';
import { HttpHeaders } from '@angular/common/http';

const uri = 'https://api.github.com/graphql'; // <-- add the URL of the GraphQL server here
// export function createApollo(httpLink: HttpLink): ApolloClientOptions {
export function createApollo(httpLink: HttpLink) {
return {
link: httpLink.create({uri,
headers: new HttpHeaders({
Authorization: `Bearer ${environment.githubPersonalAccessToken}`,
}),
}),
cache: new InMemoryCache(),
};
}
@NgModule({
providers: [ Apollo, HttpLink,
{
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink],
},
],
})
export class GraphQLModule {}
```
Add provider for both `Apollo` and `HttpLink` under `@NgModule`. Make sure your imports match my imports above.

In **`repo-table-component.ts`**, change the Apollo import statement to ...

`import { Apollo, gql } from 'apollo-angular';`

Since Apollo version 2.x, gql is a part of `apollo-angular`.

Now this solves the dev console errors too. If you have not yet gotten to the part where you add the `Skeleton` and `Pagination`, then you won't see any real data yet because there is a slight mistake there as well.

Consider this part.

![image](https://user-images.githubusercontent.com/40276600/96404305-36918480-11f8-11eb-9d15-bc29094cfc34.png)

The statement `this.prepareData(response.data.organization.repositories.nodes);` alone will not make any difference, and you'll still see the static rows you added to `ngOnInit()` since the data for the model is never populated with the response data after the query has been executed. So to make this work, you have to modify this line to the following:

`this.model.data = this.prepareData(response.data.organization.repositories.nodes);`

Now, you'll see the data Apollo queries from the Git API.

Remember, when you delete the static rows from `ngOnInit()` as instructed, keep the `model.header` and keep the `model` declaration, you'll need those at the pagination step. Only delete the static rows.

Once you add the skeleton part, this `/repo` page will again come up blank, so do not worry, carry on to the end and complete everything with the pagination part. This will add the missing pieces from the skeleton step and you will see everything nicely packed with a pagination component.

Now that the running part is over, you'd move to `ng lint --fix`.

This gave me a lot of `repo-table.component.ts:36:1 - tab indentation expected` errors pointing to the `gql` query section which it could not fix, so I had to manually go into the editor and replace the spaces with tabs. I hope you don't get the same, but if you do, follow my footsteps and re-indent with tabs.

The second nightmare started here, with `npm test`, it repeated all the previous build errors and then some. And since I have little idea on how this badge is awarded, I believe that every pull request must pass the tests on GitHub to get approved, and so I had to make sure my code passes `npm test` on my computer first in order to pass on GitHub.

So I did the following. I will show you the errors first, one by one, with the solution.

First it was this...

![image](https://user-images.githubusercontent.com/40276600/96405402-d6e8a880-11fa-11eb-9bb6-bd708f2711a4.png)

Which I solved by modifying `tsconfig.spec.json` to the following. Same changes as `tsconfig.app.json`.

```
{
"compilerOptions": {
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"strictNullChecks": false,
"skipLibCheck": true,
"resolveJsonModule": true,
"lib": [
"dom",
"es2016",
"esnext.asynciterable"
],
"outDir": "../out-tsc/spec",
"module": "esnext",
"target": "es2015",
"baseUrl": "",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts"
]
}
```

Then there was a long list of errors about `ibm-pagination` tag. Shown below, in part...

![image](https://user-images.githubusercontent.com/40276600/96405986-1c59a580-11fc-11eb-9484-a323b9c89659.png)

Which I solved by importing `PaginationModule` to both `repo-table.component.spec.ts` and `repo-page.component.spec.ts`.

Also, after importing this module, you need to add it to the `imports:` section of `TestBed.configureTestingModule`.

Don't worry, at the end I will show both the files completely, so you can compare and make changes.

Next there was `No provider for Apollo!` errors.

![image](https://user-images.githubusercontent.com/40276600/96406658-8d4d8d00-11fd-11eb-8412-e68facce7760.png)

Which I fixed by adding ...

```
import { Apollo } from 'apollo-angular';
```
to both `repo-table.component.spec.ts` and `repo-page.component.spec.ts`.

Also I had to add a `providers:` section and expose this module to `TestBed.configureTestingModule`.

`providers: [Apollo]`

Next there was `Error: Client has not been defined yet`

![image](https://user-images.githubusercontent.com/40276600/96407087-3b593700-11fe-11eb-847d-6de06c65c0e0.png)

Which I fixed by adding ...

```
import { GraphQLModule } from '../../graphql.module';
```
to both `repo-table.component.spec.ts` and `repo-page.component.spec.ts`. And added `GraphQLModule` to the `imports:` section of `TestBed.configureTestingModule`.

Next there was `NullInjectorError: No provider for HttpClient!`

![image](https://user-images.githubusercontent.com/40276600/96407345-cafee580-11fe-11eb-8d85-960e5b1402f6.png)

Which I solved by adding...

```
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
```
to both `repo-table.component.spec.ts` and `repo-page.component.spec.ts`. And, adding `HttpClientTestingModule` to `imports:` and adding `HttpClient` to `providers"` section like this...

`providers: [Apollo, HttpClient]`

All this got me here ...

![image](https://user-images.githubusercontent.com/40276600/96407536-3ba60200-11ff-11eb-9cae-9adcc9ad4e2a.png)

If you are wondering about `ChromeHeadless have not captured in 120000 ms, killing.`. I increased the duration from 1 minutes to 2 minutes since the `styles.scss` takes long to compile and by that time `Chromeheadless` times out.

I made that change in `karma.conf.js`. I also changed `autoWatch` to `false` and `singleRun` to `true`.

```
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['ChromeHeadless'],
singleRun: true,
captureTimeout: 120000
```
So I guess that's it, and here are the files like I promised.

**repo-table.component.spec.ts**
```
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RepoTableComponent } from './repo-table.component';
import { TableModule, LinkModule, PaginationModule } from 'carbon-components-angular';
import { Apollo } from 'apollo-angular';
import { GraphQLModule } from '../../graphql.module';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

describe('RepoTableComponent', () => {
let component: RepoTableComponent;
let fixture: ComponentFixture;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RepoTableComponent ],
imports: [
TableModule,
LinkModule,
PaginationModule,
GraphQLModule,
HttpClientTestingModule
],
providers: [Apollo, HttpClient]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(RepoTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

```

**repo-page.component.spec.js**

```
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RepoPageComponent } from './repo-page.component';
import { GridModule, TableModule, LinkModule, PaginationModule } from 'carbon-components-angular';
import { RepoTableComponent } from '../repo-table/repo-table.component';
import { Apollo } from 'apollo-angular';
import { GraphQLModule } from '../../graphql.module';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

describe('RepoPageComponent', () => {
let component: RepoPageComponent;
let fixture: ComponentFixture;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RepoPageComponent, RepoTableComponent ],
imports: [
GridModule,
TableModule,
LinkModule,
PaginationModule,
GraphQLModule,
HttpClientTestingModule
],
providers: [Apollo, HttpClient]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(RepoPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
```

I really hope this helps other people since to get here it took me 3 days of headbanging, and I almost gave up.

Contributor guide

No contributing guide indexed for this repository

Research direction

Compare the Step 3 tutorial instructions with the reported files: typings.d.ts, tsconfig.app.json, tsconfig.spec.json, graphql.module.ts, repo-table-component.ts, and the two component specs. Run the documented build, serve, lint, and test commands against the tutorial project, then update the guidance so the reported setup and test failures are accurately covered and completion is verifiable.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, graphql, node.js, typescript
Domain
documentation, frontend, testing
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.