wallabyjs / public

Repository for Wallaby.js questions and issues
http://wallabyjs.com
759 stars 45 forks source link

Module is not defined error #1170

Closed jbprat closed 7 years ago

jbprat commented 7 years ago

Issue description or question

Hello, I am trying to setup sublime + wallaby with an Angular 4 project built with angular-cli, using angular-cli webpack implementation. When starting wallaby I have this error:

​​​​​[Info]: Thu, 25 May 2017 15:12:31 GMT wallaby:workers Sandbox (active) [kvs3c] error: Uncaught Error: Cannot find module 'undefined'​​​​​ ​​​​​[Info]: Thu, 25 May 2017 15:12:31 GMT wallaby:workers Failed to map the stack to user code, entry message: Uncaught Error: Cannot find module 'undefined', stack: Uncaught Error: Cannot find module 'undefined'​​​​​ ​​​​​[Info]: at http://localhost:56392/wallaby-webpack.js?1495725150605:1​​​​​

I followed your ngCliWebpackSample git project.

Wallaby.js configuration file

var wallabyWebpack = require('wallaby-webpack');
var path = require('path');

var compilerOptions = Object.assign(
  require('./tsconfig.json').compilerOptions,
  require('./src/main/webapp/tsconfig.spec.json').compilerOptions);

module.exports = function (wallaby) {

  var webpackPostprocessor = wallabyWebpack({
    entryPatterns: [
      'src/main/webapp/wallabyTest.js',
      'src/main/webapp/app/**/*spec.js'
    ],

    module: {
      loaders: [
        {test: /\.css$/, loader: 'raw-loader'},
        {test: /\.html$/, loader: 'raw-loader'},
        {test: /\.js$/, loader: 'angular2-template-loader', exclude: /node_modules/},
        {test: /\.json$/, loader: 'json-loader'},
        {test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'sass-loader']},
        {test: /\.(jpg|png)$/, loader: 'url-loader?limit=128000'}
      ]
    },

    resolve: {
      modules: [
        path.join(wallaby.projectCacheDir, 'src/main/webapp/app'),
        path.join(wallaby.projectCacheDir, 'src/main/webapp')
      ]

    }
  });

  return {
    files: [
      {pattern: 'src/**/*.ts', load: false},
      {pattern: 'src/**/*.d.ts', ignore: true},
      {pattern: 'src/**/*.css', load: false},
      {pattern: 'src/**/*.sass', load: false},
      {pattern: 'src/**/*.html', load: false},
      {pattern: 'src/**/*.json', load: false},
      {pattern: 'src/**/*spec.ts', ignore: true}
    ],

    tests: [
      {pattern: 'src/main/webapp/app/**/*spec.ts', load: false}
    ],

    testFramework: 'jasmine',

    compilers: {
      'src/main/webapp/**/*.ts': wallaby.compilers.typeScript(compilerOptions)
    },

    middleware: function (app, express) {
      var path = require('path');
      app.use('/favicon.ico', express.static(path.join(__dirname, 'src/main/webapp/favicon.ico')));
      app.use('/assets', express.static(path.join(__dirname, 'src/main/webapp/assets')));
    },

    env: {
      kind: 'electron'
    },

    postprocessor: webpackPostprocessor,

    setup: function () {
      window.__moduleBundler.loadTests();
    },

    debug: true
  };
};

Component code

/*
 Created on Dec 05, 2016

 Copyright (c) 2017 Dealflo Limited. All Rights Reserved.

 This software is the proprietary information of Dealflo Limited.
 All rights reserved.

 This software is the confidential and proprietary information of Dealflo Limited.
 You shall not disclose such Confidential Information and
 shall use it only in accordance with the terms of the license agreement you
 entered into with Dealflo Limited.
 */
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { BreadCrumbsComponent } from './bread-crumbs.component';
import { TextModule } from '../../core/modules/module.entity';
import { Observable } from 'rxjs/Observable';
import { NgReduxTestingModule } from '@angular-redux/store/testing';
import { NgRedux } from '@angular-redux/store';
import { setComponentModuleTestingData } from '../../../utils';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/toArray';
import 'rxjs/add/operator/do';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';

TestBed.initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

const mockNgRedux: any = {
  configureStore: () => {},
  dispatch: () => {},
  select: () => Observable.of(3),
};
NgRedux.instance = mockNgRedux;

const mockModule5Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }]
  }
};
const mockModule3Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }]
  }
};

const mockModule6Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }]
  }
};
const mockModule4Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }]
  }
};
const mockModule2Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }]
  }
};
const mockModule1Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }]
  }
};
const mockModule12Items = {
  'type': 'BreadCrumbModule',
  'slots': {
    'crumbs': [<TextModule>{
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }, {
      'type': 'TextModule',
      'text': 'Customer Verification'
    }, {
      'type': 'TextModule',
      'text': 'Customer Signing'
    }, {
      'type': 'TextModule',
      'text': 'Dealer Completion'
    }]
  }
};
// Variables
let fixture: ComponentFixture<BreadCrumbsComponent>, component: BreadCrumbsComponent;

describe('Component: BreadCrumbsComponent', () => {
  compileAndCreate();
  // Reset TestBed after each test.
  afterEach(() => {
    TestBed.resetTestingModule();
  });

  it('should create a BreadCrumbsComponent', async(() => {
      expect(component).toBeDefined();
      const returnBootstrapGrildClass = spyOn(component, 'returnBootstrapGridClass');
      const returnStepClass = spyOn(component, 'returnStepClass');

      expect(returnBootstrapGrildClass).toBeTruthy();
      expect(returnStepClass).toBeTruthy();
  }));

  describe('after render component, get a 5 step menu', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule5Items);
      fixture.detectChanges();
    }));

    it('should create 5 text modules', async(() => {
      const li = fixture.debugElement.queryAll(By.css('li'));

      expect(li.length).toBe(5);
    }));

    describe('check breadcrumbs classes', () => {
      beforeEach(async(() => {
        setComponentModuleTestingData(component, fixture, mockModule5Items);
        fixture.detectChanges();
      }));

      it ('should call fucntions ', () => {
        expect(component.returnBootstrapGridClass()).toContain('breadcrumbs_md_5ths');
        expect(component.returnStepClass(3)).toContain('active_bread_crumbs_step');
        expect(component.returnStepClass(2)).toContain('previous_bread_crumbs_step');
      });

      it ('should add previous and active steps classes after first step passed', async(() => {
        const de = fixture.debugElement;
        const el = de.queryAll(By.css('li'));

        expect(el[0].nativeElement.classList.contains('previous_bread_crumbs_step')).toBeTruthy();
        expect(el[2].nativeElement.classList.contains('active_bread_crumbs_step')).toBeTruthy();
      }));

      it ('should add the right grid class to each list element', async(() => {
        const de = fixture.debugElement;
        const el = de.query(By.css('li'));

        expect(el).toBeDefined;
        expect(el.nativeElement.classList.contains('breadcrumbs_md_5ths')).toBeTruthy();
      }));
    });
  });

  describe('after render component,  get a 3 crumbs information', () => {

    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule3Items);
      fixture.detectChanges();
    }));

    it ('should create 3 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(3);
    });
  });

  describe('after render component,  get an empty crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, null);
    }));

    it ('should create 0 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(0);
    });
  });

  describe('after render component,  get a 6 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule6Items);
    }));

    it ('should create 6 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(6);
    });
  });
  describe('after render component,  get a 4 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule4Items);
    }));

    it ('should create 4 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(4);
    });
  });

  describe('after render component,  get a 3 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule3Items);
    }));

    it ('should create 3 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(3);
    });
  });

  describe('after render component,  get a 2 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule2Items);
    }));

    it ('should create 2 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(2);
    });
  });

  describe('after render component,  get a 1 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule1Items);
    }));

    it ('should create 1 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(1);
    });
  });

  describe('after render component,  get a 12 crumbs information', () => {
    beforeEach(async(() => {
      setComponentModuleTestingData(component, fixture, mockModule12Items);
    }));

    it ('should create 12 text modules', () => {
      const li = fixture.debugElement.queryAll(By.css('li'));
      expect(li.length).toBe(12);
    });
  });
});

function compileAndCreate() {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [NgReduxTestingModule],
      declarations: [
        BreadCrumbsComponent,
      ],
    }).compileComponents().then(() => {
      fixture = TestBed.createComponent(BreadCrumbsComponent);
      component = fixture.componentInstance;
    });
  }));
}

Package.json

In case it helps, my package.json is here.

{
  "name": "cwf-ux",
  "version": "0.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "ng": "ng",
    "start": "concurrently --prefix \"[{name}]\" --names \"SERVE,WATCH\" -c \"white.bgBlue.bold,white.bgMagenta.bold\" \"ng serve\" \"gulp watch\"",
    "build": "ng build --output-hashing=all",
    "test": "ng test --watch=true --code-coverage",
    "test-coverage": "ng test --watch=true --code-coverage",
    "test-once": "ng test --watch=false",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "protractor",
    "precommit": "concurrently --prefix \"[{name}]\" --names \"TS-LINT,SASS-LINT\" -c \"bgBlue.bold,bgMagenta.bold\" \"gulp ts-lint\" \"gulp sass-lint\""
  },
  "pre-commit": [
    "test-once",
    "precommit"
  ],
  "private": true,
  "dependencies": {
    "@angular-redux/form": "^6.1.1",
    "@angular-redux/router": "^6.1.0",
    "@angular-redux/store": "^6.2.1",
    "@angular/animations": "^4.1.0",
    "@angular/common": "^4.1.0",
    "@angular/compiler": "^4.1.0",
    "@angular/compiler-cli": "^4.1.0",
    "@angular/core": "^4.1.0",
    "@angular/forms": "^4.1.0",
    "@angular/http": "^4.1.0",
    "@angular/material": "2.0.0-beta.5",
    "@angular/platform-browser": "^4.1.0",
    "@angular/platform-browser-dynamic": "^4.1.0",
    "@angular/platform-server": "^4.1.0",
    "@angular/router": "^4.1.0",
    "@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.14",
    "@types/jquery": "^2.0.41",
    "@types/lodash": "^4.14.61",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "font-awesome": "^4.7.0",
    "gulp-cached": "^1.1.1",
    "lodash": "^4.17.4",
    "redux": "^3.6.0",
    "redux-logger": "^3.0.1",
    "redux-observable": "^0.14.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "^5.0.1",
    "tassign": "^1.0.0",
    "ts-helpers": "^1.1.1",
    "typescript": "^2.2.2",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular-redux/store": "^6.1.0",
    "@angular/cli": "^1.0.4",
    "@angular/compiler-cli": "^4.1.0",
    "@angular/core": "^4.1.0",
    "@types/jasmine": "2.5.38",
    "@types/node": "^6.0.42",
    "@types/selenium-webdriver": "^2.53.36",
    "bootstrap-sass": "^3.3.7",
    "canonical-path": "0.0.2",
    "codelyzer": "^2.1.1",
    "concurrently": "^3.1.0",
    "electron": "^1.6.8",
    "gulp": "^3.9.1",
    "gulp-debug": "^3.1.0",
    "gulp-if": "^2.0.2",
    "gulp-sass-lint": "^1.3.2",
    "gulp-scss-lint": "^0.4.0",
    "gulp-tslint": "^7.1.0",
    "gulp-typescript": "^3.1.4",
    "jasmine-ajax": "^3.3.1",
    "jasmine-core": "~2.5.2",
    "jasmine-spec-reporter": "~3.2.0",
    "karma": "^1.4.1",
    "karma-chrome-launcher": "~2.0.0",
    "karma-cli": "~1.0.1",
    "karma-coverage": "^1.1.1",
    "karma-coverage-istanbul-reporter": "^0.2.0",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "karma-phantomjs-launcher": "^1.0.4",
    "ng2-bootstrap": "^1.3.3",
    "node-sass": "^4.5.3",
    "pre-commit": "^1.2.2",
    "protractor": "~5.1.0",
    "traceur": "0.0.111",
    "ts-node": "~2.0.0",
    "tslint": "~4.5.0",
    "typescript": "~2.1.0",
    "wallaby-webpack": "*",
    "webdriver-manager": "12.0.4",
    "webpack": "^2.6.1"
  }
}

Code editor or IDE name and version

Sublime Text v3 build 3126

OS name and version

Windows 10 build 14393

ArtemGovorov commented 7 years ago

Hello,

When something goes wrong, wallaby normally reports the details to the Failing Tests output (Ctrl +) and it's the best place to start looking into. Wallaby console has a lot of debugging information reported and should only be used when troubleshooting some issues that are not clear from the Failing Tests output.

If you open the Failing Tests panel, you should be able to see some additional details:

screen shot 2017-05-26 at 11 36 53 am

The angular2-template-loader module needs to be installed as described in the step 4 of the sample repo readme.

While looking into the details you've provided, I have also noticed a couple of more things.

  var webpackPostprocessor = wallabyWebpack({
    ...

    resolve: {
      modules: [
        ...
      ],
      alias: {
        '@angular-redux/store/testing': path.resolve(__dirname, 'node_modules/@angular-redux/store/lib/testing/index.js')
      }
    }
  });
...
jbprat commented 7 years ago

Thanks for the tips!