2016-10-09 1 views
3

Я использую Angular2 final (2.0.2) с угловым кли. Я пытаюсь настроить его для запуска модульных тестов с помощью PhantomJS. Выполнение спецификаций с помощью Chrome и карма-хромированных работ - все тесты проходят. Выполнение этого же с Phantomjs-prebuilt 2.1.13 и karma-phantomjs-launcher 1.0.2 тестов не удается.Почему мои модульные тесты проходят с Chrome и не работают с PhantomJS?

Я добавил пул phantomjs в массив плагинов в файле karma.conf, а также PahntomJS в массиве браузеров.

Ошибка я получаю:

PhantomJS 2.1.1 (Mac OS X 0.0.0) DataTableFormat should transform date in milliseconds FAILED ReferenceError: Can't find variable: Intl in src/main/js/test.ts (line 53565) [email protected]:///Users/sninio/dev/csp-ui/~/@angular/common/src/facade/intl.js:117:0 <- src/main/js/test.ts:53565:20 webpack:///Users/sninio/dev/csp-ui/~/@angular/common/src/facade/intl.js:148:36 <- src/main/js/test.ts:53596:59 [email protected]:///Users/sninio/dev/csp-ui/~/@angular/common/src/facade/intl.js:157:0 <- src/main/js/test.ts:53605:39 [email protected]:///Users/sninio/dev/csp-ui/~/@angular/common/src/facade/intl.js:192:0 <- src/main/js/test.ts:53640:29 [email protected]:///Users/sninio/dev/csp-ui/~/@angular/common/src/pipes/date_pipe.js:92:0 <- src/main/js/test.ts:70473:90 [email protected]:///Users/sninio/dev/csp-ui/src/main/js/app/pages/+platform/events/data-table/data-table.pipe.ts:9:4418 <- src/main/js/test.ts:52698:5787 webpack:///Users/sninio/dev/csp-ui/src/main/js/app/pages/+platform/events/data-table/data-table.pipe.spec.ts:20:30 <- src/main/js/test.ts:60923:30 [email protected]:///Users/sninio/dev/csp-ui/~/@angular/core/bundles/core-testing.umd.j <- src/main/js/test.ts:2997:28 webpack:///Users/sninio/dev/csp-ui/~/@angular/core/bundles/core-testing.umd.js:951:32 <- src/main/js/test.ts:3084:56 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:203:0 <- src/main/js/test.ts:98886:33 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/proxy.js:72:0 <- src/main/js/test.ts:68790:45 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:202:0 <- src/main/js/test.ts:98885:42 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:96:0 <- src/main/js/test.ts:98779:49 webpack:///Users/sninio/dev/csp-ui/~/zone.js/dist/jasmine-patch.js:91:27 <- src/main/js/test.ts:68526:53 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/jasmine-patch.js:119:0 <- src/main/js/test.ts:68554:46 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/jasmine-patch.js:119:0 <- src/main/js/test.ts:68554:46 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:236:0 <- src/main/js/test.ts:98919:42 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:136:0 <- src/main/js/test.ts:98819:57 [email protected]:///Users/sninio/dev/csp-ui/~/zone.js/dist/zone.js:368:0 <- src/main/js/test.ts:99051:42 PhantomJS 2.1.1 (Mac OS X 0.0.0) DataTableFormat should transform date string FAILED

Может быть, мне не хватает какой-то конфигурации в файле test.ts созданный угловой кли?

UPDATE: Кажется, единственные тесты, которые не импорт DatePipe и JsonPipe.
Я попытался также импортировать @angular/common/testing в test.ts, но это не поможет - они не экспортируются в соответствующие index.js.
Также попытался импортировать весь @angular/common/pipes, но это тоже не сработало.

здесь Труба:

import { Pipe, PipeTransform } from "@angular/core"; 
import { DatePipe, JsonPipe } from "@angular/common"; 

@Pipe({name: 'dataTableFormat'}) 
export class DataTablePipe implements PipeTransform { 

    // values with type 'json' are parsed to json. As a result, string values may be displayed with quotes ("<string>"). 
    // To avoid that, we remove these quotes with this regex 
    private quotesExp: RegExp = /^\"|\"$/gi; 

    constructor(private datePipe: DatePipe, private jsonPipe: JsonPipe) { 

    } 

    transform(value: any, type: string): string { 
     switch (type) { 
      case "date": 
       return this.datePipe.transform(value, 'short'); 
      case "json": 
       return this.jsonPipe.transform(value).replace(this.quotesExp, ""); 
      default: 
       return value; 
     } 
    } 
} 

и спецификации:

import { inject, TestBed } from "@angular/core/testing"; 
import { DataTablePipe } from "./data-table.pipe"; 
import { DatePipe, JsonPipe } from "@angular/common"; 

describe('DataTableFormat',() => { 

    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      providers: [ 
       DatePipe, JsonPipe 
      ] 
     }); 

    }); 

    it('should transform date in milliseconds', inject([DatePipe, JsonPipe], (datePipe, jsonPipe) => { 
     let pipe = new DataTablePipe(datePipe, jsonPipe); 
     let testDate: Date = new Date(); 

     expect(pipe.transform(testDate.getTime(), 'date')).toBe(datePipe.transform(testDate, 'short')); 
    })); 

    it('should transform date string', inject([DatePipe, JsonPipe], (datePipe, jsonPipe) => { 
     let pipe = new DataTablePipe(datePipe, jsonPipe); 
     let testDate: Date = new Date(); 

     expect(pipe.transform(testDate.toISOString(), 'date')).toBe(datePipe.transform(testDate, 'short')); 
    })); 

    it('should transform json', inject([DatePipe, JsonPipe], (datePipe, jsonPipe) => { 
     let pipe = new DataTablePipe(datePipe, jsonPipe); 
     let testJson = { 
      prop1: "val1", 
      prop2: "val2" 
     }; 

     expect(pipe.transform(testJson, 'json')).toBe(jsonPipe.transform(testJson)); 
    })); 

}); 

вот мой test.ts файл - не менять много от одного порожденного angular-cli ...

import "./polyfills.ts"; 
import "zone.js/dist/long-stack-trace-zone"; 
import "zone.js/dist/proxy.js"; 
import "zone.js/dist/sync-test"; 
import "zone.js/dist/jasmine-patch"; 
import "zone.js/dist/async-test"; 
import "zone.js/dist/fake-async-test"; 


// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 
declare var __karma__: any; 
declare var require: any; 

// Prevent Karma from running prematurely. 
__karma__.loaded = function() { 
}; 

//noinspection TypeScriptUnresolvedVariable 
Promise.all([ 
    System.import('@angular/core/testing'), 
    System.import('@angular/platform-browser-dynamic/testing'), 
    System.import('../../../node_modules/nvd3/build/nv.d3.min.js'), 
]) 
// First, initialize the Angular testing environment. 
    .then(([testing, testingBrowser]) => { 
     testing.getTestBed().initTestEnvironment(
      testingBrowser.BrowserDynamicTestingModule, 
      testingBrowser.platformBrowserDynamicTesting() 
     ); 
    }) 
    // Then we find all the tests. 
    .then(() => require.context('./', true, /\.spec\.ts/)) 
    // And load the modules. 
    .then(context => context.keys().map(context)) 
    // Finally, start Karma to run the tests. 
    .then(__karma__.start, __karma__.error); 

Любая идея, почему это работает для Chrome, а не PhantomJS?

+0

Что делать, если вы используете 'TestBed' для создания своего канала, а не' inject' и 'new'? – jonrsharpe

+0

На самом деле это не связано с инъекцией - я ошибся. Другие тесты также терпят неудачу. –

+0

Пожалуйста, дайте [mcve]. – jonrsharpe

ответ

11

Поскольку PhantomJS не реализует Intl реализацию Angular2 зависит, решение было установить НПМ пакет INTL polyfill и редактировать polyfills.ts включить

import 'intl'; 
import 'intl/locale-data/jsonp/en.js'; 

Смотрите здесь: https://github.com/angular/angular/issues/3333
здесь: https://github.com/angular/angular/issues/10809
и здесь: https://coryrylan.com/blog/adding-the-internationalization-polyfill-to-a-angular-cli-project

+2

Это классно, но поскольку вы специально заправляете PhantomJS, я рекомендую вам добавить в ваш файл 'test.ts' импорт, включая другие локали, на которые вы положитесь. –

2

Теперь у вас есть поддержка Intl во всех браузерах. polyfill.io - отличный сервис, который будет загружать только полиполк, если требуемый браузер действительно нуждается в нем. Это довольно хорошее решение, но что, если вы хотите, чтобы ваш полиполк был связан с вашими сценариями? Вы потенциально получаете лучшую производительность, и ваше приложение не полагается на сторонний CDN, который, если он идет вниз, требует вашего приложения. Итак, каков следующий вариант?

Ну, с Угловой CLI на самом деле довольно легко. Сначала мы будем использовать npm, чтобы установить Intl polyfill прямо в наше приложение с угловыми углами. Для этого выполните npm install intl --save. После установки в проект Angular CLI перейдите в файл /src/polyfills.ts. Здесь вы можете добавить следующие строки.

import 'intl'; 
import 'intl/locale-data/jsonp/en.js'; 

Это все! Теперь, когда ваш проект будет создан, он добавит многопользовательский полигон и службу на английском языке. Вы можете добавить дополнительную языковую поддержку, импортировав больше языковых файлов.Теперь недостатком этого является то, что даже если браузер поддерживает Intl, он все равно должен загрузить код. Вы могли бы смягчить это, используя обнаружение функции и динамическую загрузку. Большая часть о полифиллинге - это то, что поддержка браузеров для Intl улучшается, мы сможем полностью отбросить зависимость!