diff --git a/.github/workflows/coverage-report.yml b/.github/workflows/coverage-report.yml index 9cc7bb4..52702d4 100644 --- a/.github/workflows/coverage-report.yml +++ b/.github/workflows/coverage-report.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/deployment-actions.yml b/.github/workflows/deployment-actions.yml index 9406589..4d167cb 100644 --- a/.github/workflows/deployment-actions.yml +++ b/.github/workflows/deployment-actions.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/deployment-staging.yml b/.github/workflows/deployment-staging.yml index c8fcac1..dc9fd3f 100644 --- a/.github/workflows/deployment-staging.yml +++ b/.github/workflows/deployment-staging.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 0a5f7c2..1a4799f 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} @@ -33,8 +33,11 @@ jobs: runs-on: macos-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: + # Install Firefox on macOS-arm64 since it is not included in the runner as of 27 Apr 2024 + - name: Install firefox + run: brew install --cask firefox - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 @@ -51,7 +54,7 @@ jobs: runs-on: windows-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index dafc0fd..09b111a 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/staging-fetch.yml b/.github/workflows/staging-fetch.yml index 9f9b5dc..29d1792 100644 --- a/.github/workflows/staging-fetch.yml +++ b/.github/workflows/staging-fetch.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [16.x] steps: - name: Checkout Upstream uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index e201533..38b52b5 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ CATcher.iml !.vscode/launch.json # misc +/.angular/cache /.sass-cache /connect.lock /coverage diff --git a/.nvmrc b/.nvmrc index 4ec320b..2ab3d4b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14.17.6 +v16.20.2 diff --git a/package.json b/package.json index d05590c..c4716f5 100644 --- a/package.json +++ b/package.json @@ -29,29 +29,29 @@ } }, "dependencies": { - "@angular/animations": "^12.2.17", - "@angular/cdk": "^12.2.13", - "@angular/common": "^12.2.17", - "@angular/compiler": "^12.2.17", - "@angular/core": "^12.2.17", - "@angular/forms": "^12.2.17", - "@angular/localize": "^12.2.17", - "@angular/material": "^12.2.13", - "@angular/platform-browser": "^12.2.17", - "@angular/platform-browser-dynamic": "^12.2.17", - "@angular/router": "^12.2.17", + "@angular/animations": "^13.4.0", + "@angular/cdk": "^13.3.9", + "@angular/common": "^13.4.0", + "@angular/compiler": "^13.4.0", + "@angular/core": "^13.4.0", + "@angular/forms": "^13.4.0", + "@angular/localize": "^13.4.0", + "@angular/material": "^13.3.9", + "@angular/platform-browser": "^13.4.0", + "@angular/platform-browser-dynamic": "^13.4.0", + "@angular/router": "^13.4.0", "@apollo/client": "3.3.0", "@github/markdown-toolbar-element": "^2.1.1", "@octokit/rest": "^16.37.0", - "ajv": "^6.11.0", - "apollo-angular": "^2.6.0", + "@octokit/core": "^4.2.1", + "apollo-angular": "^3.0.1", "arcsecond": "^4.1.0", "core-js": "^3.16.4", "diff-match-patch": "^1.0.4", "graphql": "^15.0.0", "karma-spec-reporter": "0.0.32", "moment": "^2.24.0", - "ngx-markdown": "^12.0.1", + "ngx-markdown": "^13.1.0", "ngx-mat-select-search": "^3.3.3", "rxjs": "6.6.7", "tslib": "^2.0.0", @@ -59,15 +59,15 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~12.2.18", + "@angular-devkit/build-angular": "~13.3.11", + "@angular/cli": "^13.3.11", + "@angular/compiler-cli": "^13.4.0", + "@angular/language-service": "^13.4.0", "@angular-eslint/builder": "12.7.0", - "@angular-eslint/eslint-plugin": "12.7.0", - "@angular-eslint/eslint-plugin-template": "12.7.0", - "@angular-eslint/schematics": "12.7.0", - "@angular-eslint/template-parser": "12.7.0", - "@angular/cli": "^12.2.18", - "@angular/compiler-cli": "^12.2.17", - "@angular/language-service": "^12.2.17", + "@angular-eslint/eslint-plugin": "13.5.0", + "@angular-eslint/eslint-plugin-template": "13.5.0", + "@angular-eslint/schematics": "13.5.0", + "@angular-eslint/template-parser": "13.5.0", "@graphql-codegen/cli": "2.16.4", "@graphql-codegen/fragment-matcher": "^1.17.7", "@graphql-codegen/typescript": "1.17.7", @@ -80,10 +80,10 @@ "@types/jasmine": "^3.8.2", "@types/jasminewd2": "2.0.8", "@types/node": "^15.6.1", - "@typescript-eslint/eslint-plugin": "4.28.2", - "@typescript-eslint/parser": "4.28.2", + "@typescript-eslint/eslint-plugin": "5.0.0", + "@typescript-eslint/parser": "5.0.0", "angular-cli-ghpages": "^1.0.0-rc.2", - "eslint": "^7.26.0", + "eslint": "^8.57.0", "husky": "^4.2.5", "jasmine": "^3.9.0", "jasmine-core": "~3.8.0", @@ -100,6 +100,6 @@ "scuri": "^0.9.4", "ts-node": "^10.9.2", "tslint-config-prettier": "^1.18.0", - "typescript": "4.3.5" + "typescript": "4.6.4" } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e82cbd1..1bfd303 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { NavigationEnd, Router } from '@angular/router'; import { ApolloLink, InMemoryCache } from '@apollo/client/core'; import { setContext } from '@apollo/client/link/context'; -import { Apollo } from 'apollo-angular'; +import { Apollo, ApolloModule } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { MarkdownModule, MarkedOptions } from 'ngx-markdown'; import 'reflect-metadata'; @@ -55,6 +55,7 @@ import { SharedModule } from './shared/shared.module'; useFactory: markedOptionsFactory } }), + ApolloModule, AppRoutingModule ], providers: [ diff --git a/src/app/core/services/loading.service.ts b/src/app/core/services/loading.service.ts index 788decb..080c4bb 100644 --- a/src/app/core/services/loading.service.ts +++ b/src/app/core/services/loading.service.ts @@ -1,17 +1,7 @@ import { DOCUMENT } from '@angular/common'; -import { - ComponentFactory, - ComponentFactoryResolver, - ComponentRef, - Inject, - Injectable, - Injector, - OnDestroy, - Renderer2, - ViewContainerRef -} from '@angular/core'; +import { ComponentRef, Inject, Injectable, Injector, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core'; import { ThemePalette } from '@angular/material/core'; -import { MatProgressSpinnerDefaultOptions, MatSpinner, ProgressSpinnerMode } from '@angular/material/progress-spinner'; +import { MatProgressSpinnerDefaultOptions, MatProgressSpinner, ProgressSpinnerMode } from '@angular/material/progress-spinner'; import { BehaviorSubject } from 'rxjs'; import { pairwise } from 'rxjs/operators'; @@ -24,21 +14,14 @@ import { pairwise } from 'rxjs/operators'; }) export class LoadingService implements OnDestroy { private isLoading = new BehaviorSubject(false); - readonly spinnerFactory: ComponentFactory; - spinnerContainerRef: ViewContainerRef | null = null; - spinnerComponentRef: ComponentRef | null = null; + spinnerComponentRef: ComponentRef | null = null; private animationMode: ProgressSpinnerMode = 'indeterminate'; private options?: MatProgressSpinnerDefaultOptions; private spinnerTheme: ThemePalette = 'primary'; private classList: string[] = []; - constructor( - readonly componentFactoryResolver: ComponentFactoryResolver, - readonly injector: Injector, - @Inject(DOCUMENT) private document: Document - ) { - this.spinnerFactory = this.componentFactoryResolver.resolveComponentFactory(MatSpinner); + constructor(public spinnerContainerRef: ViewContainerRef, readonly injector: Injector, @Inject(DOCUMENT) private document: Document) { // Subscribe to changes this.isLoading .pipe(pairwise()) @@ -157,7 +140,7 @@ export class LoadingService implements OnDestroy { // Creates and formats the spinner to the specification provided private createSpinner(injector: Injector) { - const spinnerRef = this.spinnerFactory.create(injector); + const spinnerRef = this.spinnerContainerRef.createComponent(MatProgressSpinner, { injector }); if (this.options) { spinnerRef.instance.diameter = this.options.diameter; spinnerRef.instance.strokeWidth = this.options.strokeWidth; diff --git a/src/app/shared/issue-tables/issue-paginator.ts b/src/app/shared/issue-tables/issue-paginator.ts index 6bf1382..9339f06 100644 --- a/src/app/shared/issue-tables/issue-paginator.ts +++ b/src/app/shared/issue-tables/issue-paginator.ts @@ -5,7 +5,7 @@ export function paginateData(paginator: MatPaginator, data: Issue[]): Issue[] { paginator.length = data.length; let result = getDataForPage(paginator.pageIndex, paginator.pageSize, data); if (result.length === 0) { - paginator.pageIndex -= 1; + paginator.pageIndex = paginator.pageIndex - 1; result = getDataForPage(paginator.pageIndex, paginator.pageSize, data); } return result; diff --git a/src/polyfills.ts b/src/polyfills.ts index 42175fa..9bd7388 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -22,16 +22,6 @@ import '@angular/localize/init'; * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ -// import 'classlist.js'; // Run `npm install --save classlist.js`. - -/** - * Web Animations `@angular/platform-browser/animations` - * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. - * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). - */ -// import 'web-animations-js'; // Run `npm install --save web-animations-js`. - /** * By default, zone.js will patch all possible macroTask and DomEvents * user can disable parts of macroTask/DomEvents patch by setting following flags diff --git a/src/test.ts b/src/test.ts index 89fe27c..e3d1eb5 100644 --- a/src/test.ts +++ b/src/test.ts @@ -7,7 +7,9 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang declare const require: any; // First, initialize the Angular testing environment. -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false } +}); // Then we find all the tests. const context = require.context('../tests', true, /\.spec\.ts$/); // And load the modules. diff --git a/tests/helper/mock.view.container.ref.ts b/tests/helper/mock.view.container.ref.ts index 13d8fc7..3960762 100644 --- a/tests/helper/mock.view.container.ref.ts +++ b/tests/helper/mock.view.container.ref.ts @@ -1,4 +1,14 @@ -import { ComponentRef, ElementRef, EmbeddedViewRef, Injector, TemplateRef, ViewContainerRef, ViewRef } from '@angular/core'; +import { + ComponentRef, + ElementRef, + EmbeddedViewRef, + Injector, + NgModuleRef, + TemplateRef, + Type, + ViewContainerRef, + ViewRef +} from '@angular/core'; export class MockViewContainerRef implements ViewContainerRef { element: ElementRef; @@ -16,8 +26,7 @@ export class MockViewContainerRef implements ViewContainerRef { return null as any; } - createComponent(componentFactory: any, index?: number, injector?: any, projectableNodes?: any[], ngModuleRef?: any): ComponentRef { - // Implement the required method with a fake return value or logic. + createComponent(componentType: any, options?: any): ComponentRef { return null as any; } diff --git a/tests/karma.conf.js b/tests/karma.conf.js index 60d91f5..af6ffa1 100644 --- a/tests/karma.conf.js +++ b/tests/karma.conf.js @@ -20,7 +20,7 @@ module.exports = function (config) { reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, - reporters: ['spec'], + reporters: ['spec', 'coverage-istanbul'], specReporter: { maxLogLines: 5, // limit number of lines per test suppressErrorSummary: true, diff --git a/tests/services/loading.service.spec.ts b/tests/services/loading.service.spec.ts index f35e464..de1158d 100644 --- a/tests/services/loading.service.spec.ts +++ b/tests/services/loading.service.spec.ts @@ -1,7 +1,7 @@ import { DOCUMENT } from '@angular/common'; -import { ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, Renderer2, ViewContainerRef } from '@angular/core'; +import { ComponentRef, ElementRef, Injector, Renderer2, ViewContainerRef } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; -import { MatSpinner } from '@angular/material/progress-spinner'; +import { MatProgressSpinner } from '@angular/material/progress-spinner'; import { LoadingService } from '../../src/app/core/services/loading.service'; import { MockMatSpinner } from '../helper/mock.mat.spinner'; import { MockViewContainerRef } from '../helper/mock.view.container.ref'; @@ -11,11 +11,9 @@ describe('LoadingService', () => { let mockRenderer: jasmine.SpyObj; let mockComponentInjector: jasmine.SpyObj; let elementRef: ElementRef; - let mockComponentRef: ComponentRef; + let mockComponentRef: ComponentRef; let mockInjector: jasmine.SpyObj; let loadingService: LoadingService; - let mockComponentFactory: jasmine.SpyObj>; - let mockComponentFactoryResolver: jasmine.SpyObj; let mockViewContainerRef: MockViewContainerRef; let document: Document; @@ -58,27 +56,21 @@ describe('LoadingService', () => { injector: mockComponentInjector, onDestroy: null as any, destroy: () => {}, - componentType: MatSpinner - } as unknown) as ComponentRef; + componentType: MatProgressSpinner + } as unknown) as ComponentRef; - mockComponentFactory = jasmine.createSpyObj>({ - create: mockComponentRef - }); - - mockComponentFactoryResolver = jasmine.createSpyObj({ - resolveComponentFactory: mockComponentFactory - }); mockInjector = jasmine.createSpyObj('Injector', { get: mockRenderer }); mockViewContainerRef = new MockViewContainerRef(mockInjector); + spyOn(mockViewContainerRef, 'createComponent').and.returnValue(mockComponentRef); await TestBed.configureTestingModule({ providers: [ - { provide: ComponentFactoryResolver, useValue: mockComponentFactoryResolver }, + { provide: ViewContainerRef, useValue: mockViewContainerRef }, { provide: Injector, useValue: mockInjector }, - { provide: MatSpinner, useClass: MockMatSpinner }, + { provide: MatProgressSpinner, useClass: MockMatSpinner }, LoadingService ] }).compileComponents();