UNPKG

16.3 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright Google Inc. All Rights Reserved.
4 *
5 * Use of this source code is governed by an MIT-style license that can be
6 * found in the LICENSE file at https://angular.io/license
7 */
8import { Injector, NgModule, NgZone, OpaqueToken, ReflectiveInjector } from '@angular/core';
9import { AsyncTestCompleter } from './async_test_completer';
10import { ComponentFixture } from './component_fixture';
11import { stringify } from './facade/lang';
12import { TestingCompilerFactory } from './test_compiler';
13var UNDEFINED = new Object();
14/**
15 * An abstract class for inserting the root test component element in a platform independent way.
16 *
17 * @experimental
18 */
19export var TestComponentRenderer = (function () {
20 function TestComponentRenderer() {
21 }
22 TestComponentRenderer.prototype.insertRootElement = function (rootElementId) { };
23 return TestComponentRenderer;
24}());
25var _nextRootElementId = 0;
26/**
27 * @experimental
28 */
29export var ComponentFixtureAutoDetect = new OpaqueToken('ComponentFixtureAutoDetect');
30/**
31 * @experimental
32 */
33export var ComponentFixtureNoNgZone = new OpaqueToken('ComponentFixtureNoNgZone');
34/**
35 * @whatItDoes Configures and initializes environment for unit testing and provides methods for
36 * creating components and services in unit tests.
37 * @description
38 *
39 * TestBed is the primary api for writing unit tests for Angular applications and libraries.
40 *
41 * @stable
42 */
43export var TestBed = (function () {
44 function TestBed() {
45 this._instantiated = false;
46 this._compiler = null;
47 this._moduleRef = null;
48 this._moduleWithComponentFactories = null;
49 this._compilerOptions = [];
50 this._moduleOverrides = [];
51 this._componentOverrides = [];
52 this._directiveOverrides = [];
53 this._pipeOverrides = [];
54 this._providers = [];
55 this._declarations = [];
56 this._imports = [];
57 this._schemas = [];
58 this._activeFixtures = [];
59 this.platform = null;
60 this.ngModule = null;
61 }
62 /**
63 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
64 * angular module. These are common to every test in the suite.
65 *
66 * This may only be called once, to set up the common providers for the current test
67 * suite on the current platform. If you absolutely need to change the providers,
68 * first use `resetTestEnvironment`.
69 *
70 * Test modules and platforms for individual platforms are available from
71 * '@angular/<platform_name>/testing'.
72 *
73 * @experimental
74 */
75 TestBed.initTestEnvironment = function (ngModule, platform) {
76 var testBed = getTestBed();
77 testBed.initTestEnvironment(ngModule, platform);
78 return testBed;
79 };
80 /**
81 * Reset the providers for the test injector.
82 *
83 * @experimental
84 */
85 TestBed.resetTestEnvironment = function () { getTestBed().resetTestEnvironment(); };
86 TestBed.resetTestingModule = function () {
87 getTestBed().resetTestingModule();
88 return TestBed;
89 };
90 /**
91 * Allows overriding default compiler providers and settings
92 * which are defined in test_injector.js
93 */
94 TestBed.configureCompiler = function (config) {
95 getTestBed().configureCompiler(config);
96 return TestBed;
97 };
98 /**
99 * Allows overriding default providers, directives, pipes, modules of the test injector,
100 * which are defined in test_injector.js
101 */
102 TestBed.configureTestingModule = function (moduleDef) {
103 getTestBed().configureTestingModule(moduleDef);
104 return TestBed;
105 };
106 /**
107 * Compile components with a `templateUrl` for the test's NgModule.
108 * It is necessary to call this function
109 * as fetching urls is asynchronous.
110 */
111 TestBed.compileComponents = function () { return getTestBed().compileComponents(); };
112 TestBed.overrideModule = function (ngModule, override) {
113 getTestBed().overrideModule(ngModule, override);
114 return TestBed;
115 };
116 TestBed.overrideComponent = function (component, override) {
117 getTestBed().overrideComponent(component, override);
118 return TestBed;
119 };
120 TestBed.overrideDirective = function (directive, override) {
121 getTestBed().overrideDirective(directive, override);
122 return TestBed;
123 };
124 TestBed.overridePipe = function (pipe, override) {
125 getTestBed().overridePipe(pipe, override);
126 return TestBed;
127 };
128 TestBed.get = function (token, notFoundValue) {
129 if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
130 return getTestBed().get(token, notFoundValue);
131 };
132 TestBed.createComponent = function (component) {
133 return getTestBed().createComponent(component);
134 };
135 /**
136 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
137 * angular module. These are common to every test in the suite.
138 *
139 * This may only be called once, to set up the common providers for the current test
140 * suite on the current platform. If you absolutely need to change the providers,
141 * first use `resetTestEnvironment`.
142 *
143 * Test modules and platforms for individual platforms are available from
144 * '@angular/<platform_name>/testing'.
145 *
146 * @experimental
147 */
148 TestBed.prototype.initTestEnvironment = function (ngModule, platform) {
149 if (this.platform || this.ngModule) {
150 throw new Error('Cannot set base providers because it has already been called');
151 }
152 this.platform = platform;
153 this.ngModule = ngModule;
154 };
155 /**
156 * Reset the providers for the test injector.
157 *
158 * @experimental
159 */
160 TestBed.prototype.resetTestEnvironment = function () {
161 this.resetTestingModule();
162 this.platform = null;
163 this.ngModule = null;
164 };
165 TestBed.prototype.resetTestingModule = function () {
166 this._compiler = null;
167 this._moduleOverrides = [];
168 this._componentOverrides = [];
169 this._directiveOverrides = [];
170 this._pipeOverrides = [];
171 this._moduleRef = null;
172 this._moduleWithComponentFactories = null;
173 this._compilerOptions = [];
174 this._providers = [];
175 this._declarations = [];
176 this._imports = [];
177 this._schemas = [];
178 this._instantiated = false;
179 this._activeFixtures.forEach(function (fixture) { return fixture.destroy(); });
180 this._activeFixtures = [];
181 };
182 TestBed.prototype.configureCompiler = function (config) {
183 this._assertNotInstantiated('TestBed.configureCompiler', 'configure the compiler');
184 this._compilerOptions.push(config);
185 };
186 TestBed.prototype.configureTestingModule = function (moduleDef) {
187 this._assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module');
188 if (moduleDef.providers) {
189 (_a = this._providers).push.apply(_a, moduleDef.providers);
190 }
191 if (moduleDef.declarations) {
192 (_b = this._declarations).push.apply(_b, moduleDef.declarations);
193 }
194 if (moduleDef.imports) {
195 (_c = this._imports).push.apply(_c, moduleDef.imports);
196 }
197 if (moduleDef.schemas) {
198 (_d = this._schemas).push.apply(_d, moduleDef.schemas);
199 }
200 var _a, _b, _c, _d;
201 };
202 TestBed.prototype.compileComponents = function () {
203 var _this = this;
204 if (this._moduleWithComponentFactories || this._instantiated) {
205 return Promise.resolve(null);
206 }
207 var moduleType = this._createCompilerAndModule();
208 return this._compiler.compileModuleAndAllComponentsAsync(moduleType)
209 .then(function (moduleAndComponentFactories) {
210 _this._moduleWithComponentFactories = moduleAndComponentFactories;
211 });
212 };
213 TestBed.prototype._initIfNeeded = function () {
214 if (this._instantiated) {
215 return;
216 }
217 if (!this._moduleWithComponentFactories) {
218 try {
219 var moduleType = this._createCompilerAndModule();
220 this._moduleWithComponentFactories =
221 this._compiler.compileModuleAndAllComponentsSync(moduleType);
222 }
223 catch (e) {
224 if (e.compType) {
225 throw new Error(("This test module uses the component " + stringify(e.compType) + " which is using a \"templateUrl\", but they were never compiled. ") +
226 "Please call \"TestBed.compileComponents\" before your test.");
227 }
228 else {
229 throw e;
230 }
231 }
232 }
233 var ngZone = new NgZone({ enableLongStackTrace: true });
234 var ngZoneInjector = ReflectiveInjector.resolveAndCreate([{ provide: NgZone, useValue: ngZone }], this.platform.injector);
235 this._moduleRef = this._moduleWithComponentFactories.ngModuleFactory.create(ngZoneInjector);
236 this._instantiated = true;
237 };
238 TestBed.prototype._createCompilerAndModule = function () {
239 var _this = this;
240 var providers = this._providers.concat([{ provide: TestBed, useValue: this }]);
241 var declarations = this._declarations;
242 var imports = [this.ngModule, this._imports];
243 var schemas = this._schemas;
244 var DynamicTestModule = (function () {
245 function DynamicTestModule() {
246 }
247 DynamicTestModule.decorators = [
248 { type: NgModule, args: [{ providers: providers, declarations: declarations, imports: imports, schemas: schemas },] },
249 ];
250 /** @nocollapse */
251 DynamicTestModule.ctorParameters = function () { return []; };
252 return DynamicTestModule;
253 }());
254 var compilerFactory = this.platform.injector.get(TestingCompilerFactory);
255 this._compiler =
256 compilerFactory.createTestingCompiler(this._compilerOptions.concat([{ useDebug: true }]));
257 this._moduleOverrides.forEach(function (entry) { return _this._compiler.overrideModule(entry[0], entry[1]); });
258 this._componentOverrides.forEach(function (entry) { return _this._compiler.overrideComponent(entry[0], entry[1]); });
259 this._directiveOverrides.forEach(function (entry) { return _this._compiler.overrideDirective(entry[0], entry[1]); });
260 this._pipeOverrides.forEach(function (entry) { return _this._compiler.overridePipe(entry[0], entry[1]); });
261 return DynamicTestModule;
262 };
263 TestBed.prototype._assertNotInstantiated = function (methodName, methodDescription) {
264 if (this._instantiated) {
265 throw new Error(("Cannot " + methodDescription + " when the test module has already been instantiated. ") +
266 ("Make sure you are not using `inject` before `" + methodName + "`."));
267 }
268 };
269 TestBed.prototype.get = function (token, notFoundValue) {
270 if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
271 this._initIfNeeded();
272 if (token === TestBed) {
273 return this;
274 }
275 // Tests can inject things from the ng module and from the compiler,
276 // but the ng module can't inject things from the compiler and vice versa.
277 var result = this._moduleRef.injector.get(token, UNDEFINED);
278 return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue) : result;
279 };
280 TestBed.prototype.execute = function (tokens, fn) {
281 var _this = this;
282 this._initIfNeeded();
283 var params = tokens.map(function (t) { return _this.get(t); });
284 return fn.apply(void 0, params);
285 };
286 TestBed.prototype.overrideModule = function (ngModule, override) {
287 this._assertNotInstantiated('overrideModule', 'override module metadata');
288 this._moduleOverrides.push([ngModule, override]);
289 };
290 TestBed.prototype.overrideComponent = function (component, override) {
291 this._assertNotInstantiated('overrideComponent', 'override component metadata');
292 this._componentOverrides.push([component, override]);
293 };
294 TestBed.prototype.overrideDirective = function (directive, override) {
295 this._assertNotInstantiated('overrideDirective', 'override directive metadata');
296 this._directiveOverrides.push([directive, override]);
297 };
298 TestBed.prototype.overridePipe = function (pipe, override) {
299 this._assertNotInstantiated('overridePipe', 'override pipe metadata');
300 this._pipeOverrides.push([pipe, override]);
301 };
302 TestBed.prototype.createComponent = function (component) {
303 var _this = this;
304 this._initIfNeeded();
305 var componentFactory = this._moduleWithComponentFactories.componentFactories.find(function (compFactory) { return compFactory.componentType === component; });
306 if (!componentFactory) {
307 throw new Error("Cannot create the component " + stringify(component) + " as it was not imported into the testing module!");
308 }
309 var noNgZone = this.get(ComponentFixtureNoNgZone, false);
310 var autoDetect = this.get(ComponentFixtureAutoDetect, false);
311 var ngZone = noNgZone ? null : this.get(NgZone, null);
312 var testComponentRenderer = this.get(TestComponentRenderer);
313 var rootElId = "root" + _nextRootElementId++;
314 testComponentRenderer.insertRootElement(rootElId);
315 var initComponent = function () {
316 var componentRef = componentFactory.create(_this, [], "#" + rootElId);
317 return new ComponentFixture(componentRef, ngZone, autoDetect);
318 };
319 var fixture = !ngZone ? initComponent() : ngZone.run(initComponent);
320 this._activeFixtures.push(fixture);
321 return fixture;
322 };
323 return TestBed;
324}());
325var _testBed = null;
326/**
327 * @experimental
328 */
329export function getTestBed() {
330 return _testBed = _testBed || new TestBed();
331}
332/**
333 * Allows injecting dependencies in `beforeEach()` and `it()`.
334 *
335 * Example:
336 *
337 * ```
338 * beforeEach(inject([Dependency, AClass], (dep, object) => {
339 * // some code that uses `dep` and `object`
340 * // ...
341 * }));
342 *
343 * it('...', inject([AClass], (object) => {
344 * object.doSomething();
345 * expect(...);
346 * })
347 * ```
348 *
349 * Notes:
350 * - inject is currently a function because of some Traceur limitation the syntax should
351 * eventually
352 * becomes `it('...', @Inject (object: AClass, async: AsyncTestCompleter) => { ... });`
353 *
354 * @stable
355 */
356export function inject(tokens, fn) {
357 var testBed = getTestBed();
358 if (tokens.indexOf(AsyncTestCompleter) >= 0) {
359 return function () {
360 // Return an async test method that returns a Promise if AsyncTestCompleter is one of
361 // the
362 // injected tokens.
363 return testBed.compileComponents().then(function () {
364 var completer = testBed.get(AsyncTestCompleter);
365 testBed.execute(tokens, fn);
366 return completer.promise;
367 });
368 };
369 }
370 else {
371 return function () { return testBed.execute(tokens, fn); };
372 }
373}
374/**
375 * @experimental
376 */
377export var InjectSetupWrapper = (function () {
378 function InjectSetupWrapper(_moduleDef) {
379 this._moduleDef = _moduleDef;
380 }
381 InjectSetupWrapper.prototype._addModule = function () {
382 var moduleDef = this._moduleDef();
383 if (moduleDef) {
384 getTestBed().configureTestingModule(moduleDef);
385 }
386 };
387 InjectSetupWrapper.prototype.inject = function (tokens, fn) {
388 var _this = this;
389 return function () {
390 _this._addModule();
391 return inject(tokens, fn)();
392 };
393 };
394 return InjectSetupWrapper;
395}());
396export function withModule(moduleDef, fn) {
397 if (fn === void 0) { fn = null; }
398 if (fn) {
399 return function () {
400 var testBed = getTestBed();
401 if (moduleDef) {
402 testBed.configureTestingModule(moduleDef);
403 }
404 return fn();
405 };
406 }
407 return new InjectSetupWrapper(function () { return moduleDef; });
408}
409//# sourceMappingURL=test_bed.js.map
\No newline at end of file