Skip to content
Snippets Groups Projects
Commit 682d1035 authored by François Agneray's avatar François Agneray
Browse files

Adding jest for unit tests

parent 24429a6d
No related branches found
No related tags found
1 merge request!29Develop
Pipeline #5980 failed
Pipeline: anis-next

#5981

    Showing with 1969 additions and 448 deletions
    ...@@ -15,6 +15,7 @@ list: ...@@ -15,6 +15,7 @@ list:
    @echo " shell_client > shell into angular client container" @echo " shell_client > shell into angular client container"
    @echo " build_client > generate the angular client dist application (html, css, js)" @echo " build_client > generate the angular client dist application (html, css, js)"
    @echo " test_client > Starts the angular client unit tests" @echo " test_client > Starts the angular client unit tests"
    @echo " client_coverage > Run nginx web server test client coverage"
    @echo " install_server > install server dependencies" @echo " install_server > install server dependencies"
    @echo " shell_server > shell into php server container" @echo " shell_server > shell into php server container"
    @echo " test_server > Starts the server php unit tests" @echo " test_server > Starts the server php unit tests"
    ...@@ -54,7 +55,10 @@ build_client: ...@@ -54,7 +55,10 @@ build_client:
    @docker-compose exec client ng build @docker-compose exec client ng build
    test_client: test_client:
    @docker-compose exec client ng test --no-watch --code-coverage @docker-compose exec client npx jest
    client_coverage:
    @docker run --name anis-client-code-coverage -d -p 8888:80 -v $(CURDIR)/client/coverage/anis-client:/usr/share/nginx/html:ro nginx
    install_server: install_server:
    @docker run --init -it --rm --user $(UID):$(GID) \ @docker run --init -it --rm --user $(UID):$(GID) \
    ......
    stages: stages:
    - install_dependencies - install_dependencies
    - test
    - sonar - sonar
    - build - build
    - dockerize - dockerize
    ...@@ -20,6 +21,20 @@ install_dependencies: ...@@ -20,6 +21,20 @@ install_dependencies:
    - cd client - cd client
    - yarn install - yarn install
    test:
    image: node:16-slim
    stage: test
    cache:
    key: ${CI_COMMIT_REF_SLUG}_client
    paths:
    - node_modules
    policy: pull
    script:
    - npx jest --coverage --coverageReporters lcov
    artifacts:
    paths:
    - client/coverage
    sonar_scanner: sonar_scanner:
    image: sonarsource/sonar-scanner-cli:latest image: sonarsource/sonar-scanner-cli:latest
    stage: sonar stage: sonar
    ...@@ -37,7 +52,7 @@ sonar_scanner: ...@@ -37,7 +52,7 @@ sonar_scanner:
    -Dsonar.host.url=$SONARQUBE_URL -Dsonar.host.url=$SONARQUBE_URL
    -Dsonar.login=$SONAR_TOKEN_CLIENT -Dsonar.login=$SONAR_TOKEN_CLIENT
    -Dsonar.exclusions=**.spec.ts -Dsonar.exclusions=**.spec.ts
    -Dsonar.typescript.lcov.reportPaths=./coverage/anis-next/lcov.info -Dsonar.typescript.lcov.reportPaths=./coverage/anis-client/lcov.info
    build: build:
    image: node:16-slim image: node:16-slim
    ......
    ...@@ -89,24 +89,6 @@ ...@@ -89,24 +89,6 @@
    "options": { "options": {
    "browserTarget": "client:build" "browserTarget": "client:build"
    } }
    },
    "test": {
    "builder": "@angular-devkit/build-angular:karma",
    "options": {
    "main": "src/test.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "tsconfig.spec.json",
    "karmaConfig": "karma.conf.js",
    "inlineStyleLanguage": "scss",
    "assets": [
    "src/favicon.ico",
    "src/assets"
    ],
    "styles": [
    "src/styles.scss"
    ],
    "scripts": []
    }
    } }
    } }
    } }
    ......
    const { pathsToModuleNameMapper } = require('ts-jest/utils');
    const { compilerOptions } = require('./tsconfig');
    module.exports = {
    preset: 'jest-preset-angular',
    testMatch: ['**/+(*.)+(spec).+(ts|js)'],
    setupFilesAfterEnv: ['<rootDir>/src/test.ts'],
    collectCoverage: false,
    collectCoverageFrom: ['src/**/*.ts'],
    coverageReporters: ['html'],
    coverageDirectory: 'coverage/anis-client',
    moduleDirectories: ["node_modules", "./"],
    moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
    prefix: '<rootDir>/',
    }),
    };
    // Karma configuration file, see link for more information
    // https://karma-runner.github.io/1.0/config/configuration-file.html
    module.exports = function (config) {
    config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
    require('karma-jasmine'),
    require('karma-chrome-launcher'),
    require('karma-jasmine-html-reporter'),
    require('karma-coverage'),
    require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
    jasmine: {
    // you can add configuration options for Jasmine here
    // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
    // for example, you can disable the random execution with `random: false`
    // or set a specific seed with `seed: 4321`
    },
    clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    jasmineHtmlReporter: {
    suppressAll: true // removes the duplicated traces
    },
    coverageReporter: {
    dir: require('path').join(__dirname, './coverage/client'),
    subdir: '.',
    reporters: [
    { type: 'html' },
    { type: 'text-summary' }
    ]
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true
    });
    };
    ...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
    "ng": "ng", "ng": "ng",
    "start": "ng serve", "start": "ng serve",
    "build": "ng build", "build": "ng build",
    "watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development"
    "test": "ng test"
    }, },
    "private": true, "private": true,
    "dependencies": { "dependencies": {
    ...@@ -42,13 +41,11 @@ ...@@ -42,13 +41,11 @@
    "@angular/compiler-cli": "~12.0.4", "@angular/compiler-cli": "~12.0.4",
    "@types/d3": "^5.7.2", "@types/d3": "^5.7.2",
    "@types/jasmine": "~3.6.0", "@types/jasmine": "~3.6.0",
    "@types/jest": "^26.0.24",
    "@types/node": "^12.11.1", "@types/node": "^12.11.1",
    "jasmine-core": "~3.7.0", "jasmine-core": "~3.7.0",
    "karma": "~6.3.0", "jest": "^27.0.6",
    "karma-chrome-launcher": "~3.1.0", "jest-preset-angular": "^9.0.5",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "typescript": "~4.2.3" "typescript": "~4.2.3"
    } }
    } }
    import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing';
    import { RouterTestingModule } from '@angular/router/testing';
    import { of } from 'rxjs';
    import { provideMockStore, MockStore } from '@ngrx/store/testing';
    import { AppComponent } from './app.component';
    import { AppConfigService } from 'src/app/app-config.service';
    import * as authActions from 'src/app/auth/auth.actions';
    describe('AppComponent', () => {
    let component: AppComponent;
    let fixture: ComponentFixture<AppComponent>;
    let store: MockStore;
    let config: AppConfigService
    beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [
    AppComponent
    ],
    providers: [
    provideMockStore({ }),
    AppConfigService
    ]
    }).compileComponents();
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    store = TestBed.inject(MockStore);
    config = TestBed.inject(AppConfigService);
    }));
    it('should create the app', () => {
    expect(component).toBeDefined();
    });
    it('authenticationEnabled() should give authentication enabled config key value', () => {
    config.authenticationEnabled = true;
    expect(component.authenticationEnabled()).toBeTruthy();
    });
    it('login() should dispatch login action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.login();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.login());
    });
    it('logout() should dispatch logout action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.logout();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.logout());
    });
    it('openEditProfile() should dispatch open edit profile action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.openEditProfile();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.openEditProfile());
    });
    it('isAnisAdmin() should return observable true if user is authenticated', () => {
    component.userRoles = of(['user']);
    component.isAnisAdmin().subscribe(isAuthenticated => expect(isAuthenticated).toBeFalsy());
    component.userRoles = of(['user', 'anis_admin']);
    component.isAnisAdmin().subscribe(isAuthenticated => expect(isAuthenticated).toBeTruthy());
    });
    });
    ...@@ -17,7 +17,7 @@ import * as fromAuth from '../../auth/auth.reducer'; ...@@ -17,7 +17,7 @@ import * as fromAuth from '../../auth/auth.reducer';
    import * as authActions from '../../auth/auth.actions'; import * as authActions from '../../auth/auth.actions';
    import * as authSelector from '../../auth/auth.selector'; import * as authSelector from '../../auth/auth.selector';
    import { UserProfile } from '../../auth/user-profile.model'; import { UserProfile } from '../../auth/user-profile.model';
    import { AppConfigService } from 'src/app/app-config.service'; import { AppConfigService } from '../../app-config.service';
    @Component({ @Component({
    selector: 'app-root', selector: 'app-root',
    ......
    import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing';
    import { RouterTestingModule } from '@angular/router/testing';
    import { NotFoundPageComponent } from './not-found-page.component';
    describe('NotFoundPageComponent', () => {
    let component: NotFoundPageComponent;
    let fixture: ComponentFixture<NotFoundPageComponent>;
    beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [
    NotFoundPageComponent
    ]
    }).compileComponents();
    fixture = TestBed.createComponent(NotFoundPageComponent);
    component = fixture.componentInstance;
    }));
    it('should create the not found page component', () => {
    expect(component).toBeDefined();
    });
    });
    import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing';
    import { RouterTestingModule } from '@angular/router/testing';
    import { UnauthorizedComponent } from './unauthorized.component';
    describe('UnauthorizedComponent', () => {
    let component: UnauthorizedComponent;
    let fixture: ComponentFixture<UnauthorizedComponent>;
    beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [
    UnauthorizedComponent
    ]
    }).compileComponents();
    fixture = TestBed.createComponent(UnauthorizedComponent);
    component = fixture.componentInstance;
    }));
    it('should create the unauthorized component', () => {
    expect(component).toBeDefined();
    });
    });
    import { Component, Input } from '@angular/core';
    import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing';
    import { RouterTestingModule } from '@angular/router/testing';
    import { provideMockStore, MockStore } from '@ngrx/store/testing';
    import { AppConfigService } from 'src/app/app-config.service';
    import { UserProfile } from 'src/app/auth/user-profile.model';
    import { Instance } from 'src/app/metamodel/models';
    import * as authActions from 'src/app/auth/auth.actions';
    import { PortalHomeComponent } from './portal-home.component';
    describe('PortalHomeComponent', () => {
    @Component({ selector: 'app-navbar', template: '' })
    class NavbarStubComponent {
    @Input() links: {label: string, icon: string, routerLink: string}[];
    @Input() isAuthenticated: boolean;
    @Input() userProfile: UserProfile = null;
    @Input() baseHref: string;
    @Input() authenticationEnabled: boolean;
    }
    @Component({ selector: 'app-instance-card', template: '' })
    class InstanceCardStubComponent {
    @Input() instance: Instance;
    }
    let component: PortalHomeComponent;
    let fixture: ComponentFixture<PortalHomeComponent>;
    let store: MockStore;
    let config: AppConfigService
    beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
    imports: [
    RouterTestingModule
    ],
    declarations: [
    PortalHomeComponent,
    NavbarStubComponent,
    InstanceCardStubComponent
    ],
    providers: [
    provideMockStore({ }),
    AppConfigService
    ]
    }).compileComponents();
    fixture = TestBed.createComponent(PortalHomeComponent);
    component = fixture.componentInstance;
    store = TestBed.inject(MockStore);
    config = TestBed.inject(AppConfigService);
    }));
    it('should create the portal home component', () => {
    expect(component).toBeDefined();
    });
    it('getBaseHref() should give base href config key value', () => {
    config.baseHref = '/my-project';
    expect(component.getBaseHref()).toBe('/my-project');
    });
    it('authenticationEnabled() should give authentication enabled config key value', () => {
    config.authenticationEnabled = true;
    expect(component.getAuthenticationEnabled()).toBeTruthy();
    });
    it('login() should dispatch login action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.login();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.login());
    });
    it('logout() should dispatch logout action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.logout();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.logout());
    });
    it('openEditProfile() should dispatch open edit profile action', () => {
    const spy = jest.spyOn(store, 'dispatch');
    component.openEditProfile();
    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(authActions.openEditProfile());
    });
    });
    // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'jest-preset-angular/setup-jest';
    import 'zone.js/testing'; Object.defineProperty(window, 'CSS', { value: null });
    import { getTestBed } from '@angular/core/testing'; Object.defineProperty(window, 'getComputedStyle', {
    import { value: () => {
    BrowserDynamicTestingModule, return {
    platformBrowserDynamicTesting display: 'none',
    } from '@angular/platform-browser-dynamic/testing'; appearance: ['-webkit-appearance'],
    };
    },
    });
    declare const require: { Object.defineProperty(document, 'doctype', {
    context(path: string, deep?: boolean, filter?: RegExp): { value: '<!DOCTYPE html>',
    keys(): string[]; });
    <T>(id: string): T; Object.defineProperty(document.body.style, 'transform', {
    }; value: () => {
    }; return {
    enumerable: true,
    // First, initialize the Angular testing environment. configurable: true,
    getTestBed().initTestEnvironment( };
    BrowserDynamicTestingModule, },
    platformBrowserDynamicTesting() });
    );
    // Then we find all the tests.
    const context = require.context('./', true, /\.spec\.ts$/);
    // And load the modules.
    context.keys().map(context);
    /* To learn more about this file see: https://angular.io/config/tsconfig. */
    { {
    "compileOnSave": false, "compileOnSave": false,
    "compilerOptions": { "compilerOptions": {
    ......
    /* To learn more about this file see: https://angular.io/config/tsconfig. */ /* To learn more about this file see: https://angular.io/config/tsconfig. */
    { {
    "extends": "./tsconfig.json", "extends": "./tsconfig.json",
    "compilerOptions": { "compilerOptions": {
    "outDir": "./out-tsc/spec", "outDir": "./out-tsc/spec",
    "types": [ "types": [
    "jasmine" "jest"
    ] ],
    }, "esModuleInterop": true,
    "files": [ "emitDecoratorMetadata": true
    "src/test.ts", },
    "src/polyfills.ts" "files": ["src/test.ts", "src/polyfills.ts"],
    ], "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
    "include": [
    "src/**/*.spec.ts",
    "src/**/*.d.ts"
    ]
    } }
    This diff is collapsed.
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment