atularen / ngx-monaco-editor

Monaco Editor component for Angular 2 and Above
https://www.npmjs.com/package/ngx-monaco-editor
MIT License
428 stars 155 forks source link

How to get monaco global accesible in unit tests - Karma/Jasmine #200

Open parky128 opened 3 years ago

parky128 commented 3 years ago

I am making use of @materia-ui/ngx-monaco-editor which wraps this library and am having trouble getting the monaco global to be recognised during unit test runs with Karma+Jasmine.

Component

import {
    Component,
    OnInit } from '@angular/core';
import { MonacoEditorLoaderService } from '@materia-ui/ngx-monaco-editor';
import { filter, take } from 'rxjs/operators';

@Component({
    selector: 'my-editor',
    templateUrl: './my-editor.component.html',
    styleUrls: ['./my-editor.component.scss']
})

export class MyEditorComponent implements OnInit {

    public modelUri: monaco.Uri;

    constructor(private monacoLoaderService: MonacoEditorLoaderService) {
        this.monacoLoaderService.isMonacoLoaded$.pipe(
            filter(isLoaded => isLoaded === true),
            take(1),
        ).subscribe(() => {
            this.monacoLoaderService.isMonacoLoaded$
                .pipe(
                    filter(isLoaded => isLoaded),
                    take(1)
                )
                .subscribe(() => {
                    // This seems to be the issue during test runs - monaco is not defined
                    monaco.languages.json.jsonDefaults.setDiagnosticsOptions({});
                })
            })
    }
}

In my component file, monaco is being resolved from interfaces exposed in the @materia-ui/ngx-monaco-editor:

enter image description here

Test Spec

describe('MyEditorComponent Test Suite:', () => {
    let component: MyEditorComponent;
    let fixture: ComponentFixture<MyEditorComponent>;
    let tagsService: TagsService;
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [MyEditorComponent],
            providers: [ MonacoEditorLoaderService ],
            schemas: [CUSTOM_ELEMENTS_SCHEMA]

        }).compileComponents();
    }));

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

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

When it comes to unit testing my component, I get errors from Karma to tell me that monaco is not defined: enter image description here

I am struggling with getting monaco to be correctly picked up by Karma, at least I believe thats my problem here.

Whats the right approach here to get things loading in my test suite correctly?

zewa666 commented 3 years ago

Is the Editor actually loading in your unit tests? Can you show your Karma config with focus on bundling/proxying the Monaco assets?

TaylorShane commented 3 years ago

I'm having the same issue. The monaco namespace is undefined in my unit tests.

For example, I have this reference to the namespace in my component:

const markups: any[] = [];
markups.push({
    range: new monaco.Range(linePosition, 1, linePosition, 20),
    options: { isWholeLine: true, inlineClassName: markupClasses },
});

In my unit test browser console, I get: image

My karma.conf.js file looks like this:

const grid = require('url').parse(process.env.SELENIUM_URL || '');
const path = require('path');

module.exports = function (config) {
  config.set({
    basePath: '',
    hostname: process.env.SELENIUM_URL ? require('ip').address() : 'localhost',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-webdriver-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false
    },
    coverageIstanbulReporter: {
      dir: path.join(__dirname, '../dist/coverage/'),
      reports: ['text-summary', 'html', 'lcovonly'],
      fixWebpackSourcePaths: true
    },
    customLaunchers: {
      'Chrome-Webdriver': {
        base: 'WebDriver',
        config: {
          hostname: grid.hostname,
          port: grid.port
        },
        browserName: 'chrome'
      }
    },
    files: [
    {
      pattern: './../node_modules/ngx-monaco-editor/assets/monaco/**/*.js',
      watched: false,
      included: false,
      served: true
    },
    {
      pattern: '../node_modules/ngx-monaco-editor/assets/monaco/**/*.css',
      watched: false,
      included: false,
      served: true
    }
  ],
  proxies: {
    dir: path.join(__dirname, '../dist/coverage/'),
    "/assets/monaco/": '/absolute' + path.resolve("../node_modules/ngx-monaco-editor/assets/monaco/")
  },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: !process.env.SELENIUM_URL,
    browsers: [process.env.SELENIUM_URL ? 'Chrome-Webdriver' : 'Chrome'],
    singleRun: process.env.SELENIUM_URL,
    browserNoActivityTimeout: 100000
  });
};

Any suggestions would be greatly appreciated.

zewa666 commented 3 years ago

@TaylorShane my karma.conf looks very similar except one thing. In the proxies section I have

"/assets/monaco/": '/absolute' + path.resolve("./node_modules/ngx-monaco-editor/assets/monaco/")

note the ./node_modules vs your ../node_modules

perhaps thats the missing part?

TaylorShane commented 3 years ago

@zewa666 thanks so much, that was it. Much appreciated!

TaylorShane commented 3 years ago

@zewa666 Thanks again, that did resolve the issue with Karma not finding the loader.js file and karma now shows the editor in the browser of running tests. But whenever the unit test gets to a reference to the monaco namespace the test fails because the namespace is still undefined.

For example, references like this:

new monaco.Range(linePosition, 1, linePosition, 1)
const model = monaco.editor.getModels()[0];
const diffmodel1 = monaco.editor.getModels()[1];

I'm using version 7.0.0

zewa666 commented 3 years ago

This sounds potentially like an issue of how your testbed is setup with the dependency on the ngx-monaco module. It needs to be instantiated and done before you get into your unit test as that should trigger the loader to get the monaco global available

musclemike commented 2 years ago
// https://karma-runner.github.io/1.0/config/configuration-file.html

const path = require('path');

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-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, './coverage/test'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    singleRun: false,
    browsers: ['Chrome'],
    customLaunchers: {
      ChromeHeadless: {
        base: 'Chrome',
        flags: [
          '--headless',
          '--disable-gpu',
          '--no-sandbox',
          '--remote-debugging-port=9222',
        ]
      }
    },
    restartOnFileChange: true,
    files: [
      { pattern: './node_modules/ngx-monaco-editor/assets/monaco/**/*.js', watched: false, included: false, served: true },
      { pattern: './node_modules/ngx-monaco-editor/assets/monaco/**/*.css', watched: false, included: false, served: true }
    ],
    proxies: {
      '/api': 'http://127.0.0.1:8081',
      '/assets/monaco/': '/absolute' + path.resolve("./node_modules/ngx-monaco-editor/assets/monaco/")
    },
    proxyValidateSSL: false
  });
};

getting the following error: Unbenannt