UNPKG

shallow-render

Version:

Shallow rendering test utility for Angular

228 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rendering = void 0; const testing_1 = require("@angular/core/testing"); const platform_browser_1 = require("@angular/platform-browser"); const output_proxy_1 = require("../tools/output-proxy"); const query_match_1 = require("./query-match"); /** * Contains all information about a rendered test component including * utilities for querying and toggling rendered states of directives * * This is not intended for direct instantion. These are created via the `render` method on an instance of `Shallow` * * @link https://getsaf.github.io/shallow-render/#rendering */ class Rendering { constructor(fixture, element, instance, bindings, _setup) { this.fixture = fixture; this.element = element; this.instance = instance; this.bindings = bindings; this._setup = _setup; this.outputs = (0, output_proxy_1.outputProxy)(this.instance); ///////////////////////////////////////////////////////////////////////////// // The following methods MUST be arrow functions so they can be deconstructured // off of the class ///////////////////////////////////////////////////////////////////////////// /** * Search for a component with a CSS celector * * The result is either a `DebugElement` OR an Array of `DebugElement`. Your test * must give proper treatment to the result based on the expected results. * * For example, if your test expects a single result, you may treat the result as a `DebugElement` or an array of `DebugElement`s with one entry. * * @example * expect(find('h1.large').nativeElement.textContent).toBe('Foo'); * * // If your query results in multiple matches, you may iterate over the matches but if you attempt * // to treat the collection of matches as a single match, the test will fail due to a mismatched * // usage of the query results in the test. * * // This would throw an error if the query resulted in multiple matches * expect(find('h1.large').nativeElement.textContent).toBe('Foo'); * * const results = find('h1.large'); * expect(results.length).toBe(3); * expect(results.map(result => result.nativeElement.textContent)).toEqual([ * 'Foo', * 'Bar', * 'Baz' * ]) * * @link https://getsaf.github.io/shallow-render/#querying */ this.find = (cssOrDirective, options) => { const query = typeof cssOrDirective === 'string' ? platform_browser_1.By.css(cssOrDirective) : platform_browser_1.By.directive(this._setup.mockCache.find(cssOrDirective) || cssOrDirective); const mainQuery = this.fixture.debugElement.queryAll(query); const found = options && options.query ? this.fixture.debugElement.queryAll(platform_browser_1.By.css(options.query)).filter(item => mainQuery.includes(item)) : mainQuery; if (found.includes(this.element)) { throw new Error(`Don't search for your test component, it is automatically returned by the shallow renderer`); } return (0, query_match_1.createQueryMatch)(found); }; /** * Search for a component by it's class * * The result is either an instance of the component OR an Array of component instances. Your test * must give proper treatment to the result based on the expected results. * * For example, if your test expects a single result, you may treat the result as a single component instance or an array of instances with one entry. * * @example * expect(find(ItemComponent).label).toBe('Foo'); * * // If your query results in multiple matches, you may iterate over the matches but if you attempt * // to treat the collection of matches as a single match, the test will fail due to a mismatched * // usage of the query results in the test. * * // This would throw an error if the query resulted in multiple matches * expect(findComponent(ItemComponent).label).toBe('Foo'); * * const results = findComponent(ItemComponent); * expect(results.length).toBe(3); * expect(results.map(result => result.label)).toEqual([ * 'Foo', * 'Bar', * 'Baz' * ]) * * @link https://getsaf.github.io/shallow-render/#querying */ this.findComponent = (component, options) => this.findDirective(component, options); /** * Search for a directive by it's class * * Note: For structural directives, @see Rendering#findStructuralDirective * * The result is either an instance of the directive OR an Array of directive instances. Your test * must give proper treatment to the result based on the expected results. * * For example, if your test expects a single result, you may treat the result as a single directive instance or an array of instances with one entry. * * @example * expect(findDirective(MyDirective).label).toBe('Foo'); * * // If your query results in multiple matches, you may iterate over the matches but if you attempt * // to treat the collection of matches as a single match, the test will fail due to a mismatched * // usage of the query results in the test. * * // This would throw an error if the query resulted in multiple matches * expect(findDirective(MyDirective).label).toBe('Foo'); * * const results = findDirective(MyDirective); * expect(results.length).toBe(3); * expect(results.map(result => result.label)).toEqual([ * 'Foo', * 'Bar', * 'Baz' * ]) * * @link https://getsaf.github.io/shallow-render/#querying */ this.findDirective = (directive, options) => { const directiveOrMock = this._setup.mockCache.find(directive) || directive; const foundElements = options && options.query ? this.fixture.debugElement.queryAll(platform_browser_1.By.css(options.query)) : this.find(directive, options); const foundDirectives = foundElements .map(result => { try { return result.injector.get(directiveOrMock); } catch (e) { return undefined; } }) .filter(i => i); if (foundDirectives.some(i => i === this.instance)) { throw new Error(`Don't search for your test component, it is automatically returned by the shallow renderer`); } return (0, query_match_1.createQueryMatch)(foundDirectives); }; /** * @deprecated Use inject instead */ this.get = (queryClass) => testing_1.TestBed.inject(queryClass); /** * Get the instance of a provider via Angular's injection system. * * This is identical to `TestBed.inject` */ this.inject = testing_1.TestBed.inject.bind(testing_1.TestBed); /** * Search for a structural directive by it's class * * The result is either an instance of the directive OR an Array of directive instances. Your test * must give proper treatment to the result based on the expected results. * * For example, if your test expects a single result, you may treat the result as a single directive instance or an array of directives with one entry. * * @example * expect(find(MyDirective).label).toBe('Foo'); * * // If your query results in multiple matches, you may iterate over the matches but if you attempt * // to treat the collection of matches as a single match, the test will fail due to a mismatched * // usage of the query results in the test. * * // This would throw an error if the query resulted in multiple matches * expect(findStructuralDirective(MyDirective).label).toBe('Foo'); * * const results = findStructuralDirective(MyDirective); * expect(results.length).toBe(3); * expect(results.map(result => result.label)).toEqual([ * 'Foo', * 'Bar', * 'Baz' * ]) * * @link https://getsaf.github.io/shallow-render/#querying */ this.findStructuralDirective = (directiveClass, options) => (0, query_match_1.createQueryMatch)(this.fixture.debugElement .queryAllNodes(node => { try { const instance = node.injector.get(directiveClass); if (instance) { return options && options.query ? options.query(instance) : true; } } catch (e) { } return false; }) .map(node => node.injector.get(directiveClass))); /** * Toggle on and off the rendering of child templates into a structural directive * * @link https://getsaf.github.io/shallow-render/#structural-directives */ this.renderStructuralDirective = (directiveClassOrObject, renderContents = true) => { const directives = typeof directiveClassOrObject === 'function' ? this.findStructuralDirective(directiveClassOrObject) : directiveClassOrObject.length ? directiveClassOrObject : [directiveClassOrObject]; if (!directives.length) { throw new Error(`Tried to render a structural directive but none were found.`); } directives.forEach(foundDirective => { if (!('renderContents' in foundDirective)) { const directiveName = Object.getPrototypeOf(foundDirective).constructor.name; throw new Error(`You may only manually render mocked directives with "renderStructuralDirective". Tried to render a structural directive (${directiveName}) but the directive is not mocked.`); } if (renderContents) { foundDirective.renderContents(); } else { foundDirective.clearContents(); } }); }; } } exports.Rendering = Rendering; //# sourceMappingURL=rendering.js.map