[6a3a178] | 1 | /**
|
---|
| 2 | * AngularJS-Material-Mocks
|
---|
| 3 | *
|
---|
| 4 | * Developers interested in running their own custom unit tests WITH angular-material.js loaded...
|
---|
| 5 | * must also include this *mocks* file. Similar to `angular-mocks.js`, `angular-material-mocks.js`
|
---|
| 6 | * will override and disable specific AngularJS Material performance settings:
|
---|
| 7 | *
|
---|
| 8 | * - Disabled Theme CSS rule generations
|
---|
| 9 | * - Forces $mdAria.expectWithText() to be synchronous
|
---|
| 10 | * - Mocks $$rAF.throttle()
|
---|
| 11 | * - Captures flush exceptions from $$rAF
|
---|
| 12 | */
|
---|
| 13 | // eslint-disable-next-line no-shadow-restricted-names
|
---|
| 14 | (function(window, angular, undefined) {
|
---|
| 15 |
|
---|
| 16 | 'use strict';
|
---|
| 17 |
|
---|
| 18 | // Allow our code to know when they are running inside of a test so they can expose extra services
|
---|
| 19 | // that should NOT be exposed to the public but that should be tested.
|
---|
| 20 | //
|
---|
| 21 | // As an example, see input.js which exposes some animation-related methods.
|
---|
| 22 | window._mdMocksIncluded = true;
|
---|
| 23 |
|
---|
| 24 | /**
|
---|
| 25 | * @ngdoc module
|
---|
| 26 | * @name ngMaterial-mock
|
---|
| 27 | * @packageName angular-material-mocks
|
---|
| 28 | *
|
---|
| 29 | * @description
|
---|
| 30 | * The `ngMaterial-mock` module provides support
|
---|
| 31 | */
|
---|
| 32 | angular.module('ngMaterial-mock', ['ngMock', 'ngAnimateMock', 'material.core']).config([
|
---|
| 33 | '$provide',
|
---|
| 34 | function($provide) {
|
---|
| 35 | $provide.factory('$material', [
|
---|
| 36 | '$animate', '$timeout',
|
---|
| 37 | function($animate, $timeout) {
|
---|
| 38 | return {
|
---|
| 39 | flushOutstandingAnimations: function() {
|
---|
| 40 | // this code is placed in a try-catch statement
|
---|
| 41 | // since 1.3 and 1.4 handle their animations differently
|
---|
| 42 | // and there may be situations where follow-up animations
|
---|
| 43 | // are run in one version and not the other
|
---|
| 44 | try {
|
---|
| 45 | $animate.flush();
|
---|
| 46 | // eslint-disable-next-line no-empty
|
---|
| 47 | } catch (e) {}
|
---|
| 48 | },
|
---|
| 49 | flushInterimElement: function() {
|
---|
| 50 | this.flushOutstandingAnimations();
|
---|
| 51 | $timeout.flush();
|
---|
| 52 | this.flushOutstandingAnimations();
|
---|
| 53 | $timeout.flush();
|
---|
| 54 | this.flushOutstandingAnimations();
|
---|
| 55 | $timeout.flush();
|
---|
| 56 | }
|
---|
| 57 | };
|
---|
| 58 | }
|
---|
| 59 | ]);
|
---|
| 60 |
|
---|
| 61 | /**
|
---|
| 62 | * AngularJS Material dynamically generates Style tags
|
---|
| 63 | * based on themes and palettes; for each ng-app.
|
---|
| 64 | *
|
---|
| 65 | * For testing, we want to disable generation and
|
---|
| 66 | * <style> DOM injections. So we clear the huge THEME
|
---|
| 67 | * styles while testing...
|
---|
| 68 | */
|
---|
| 69 | $provide.constant('$MD_THEME_CSS', '/**/');
|
---|
| 70 |
|
---|
| 71 | /**
|
---|
| 72 | * Add throttle() and wrap .flush() to catch `no callbacks present`
|
---|
| 73 | * errors
|
---|
| 74 | */
|
---|
| 75 | $provide.decorator('$$rAF', function throttleInjector($delegate) {
|
---|
| 76 | $delegate.throttle = function(cb) {
|
---|
| 77 | return function() {
|
---|
| 78 | cb.apply(this, arguments);
|
---|
| 79 | };
|
---|
| 80 | };
|
---|
| 81 |
|
---|
| 82 | const ngFlush = $delegate.flush;
|
---|
| 83 | $delegate.flush = function() {
|
---|
| 84 | try {
|
---|
| 85 | ngFlush();
|
---|
| 86 | // eslint-disable-next-line no-empty
|
---|
| 87 | } catch (e) {}
|
---|
| 88 | };
|
---|
| 89 |
|
---|
| 90 | return $delegate;
|
---|
| 91 | });
|
---|
| 92 |
|
---|
| 93 | /**
|
---|
| 94 | * Capture $timeout.flush() errors: "No deferred tasks to be flushed"
|
---|
| 95 | * errors
|
---|
| 96 | */
|
---|
| 97 | $provide.decorator('$timeout', function throttleInjector($delegate) {
|
---|
| 98 | const ngFlush = $delegate.flush;
|
---|
| 99 | $delegate.flush = function() {
|
---|
| 100 | const args = Array.prototype.slice.call(arguments);
|
---|
| 101 | try {
|
---|
| 102 | ngFlush.apply($delegate, args);
|
---|
| 103 | // eslint-disable-next-line no-empty
|
---|
| 104 | } catch (e) {}
|
---|
| 105 | };
|
---|
| 106 |
|
---|
| 107 | return $delegate;
|
---|
| 108 | });
|
---|
| 109 | }
|
---|
| 110 | ]);
|
---|
| 111 |
|
---|
| 112 | /**
|
---|
| 113 | * Stylesheet Mocks used by `animateCss.spec.js`
|
---|
| 114 | */
|
---|
| 115 | window.createMockStyleSheet = function createMockStyleSheet(doc, wind) {
|
---|
| 116 | doc = doc ? doc[0] : window.document;
|
---|
| 117 | wind = wind || window;
|
---|
| 118 |
|
---|
| 119 | const node = doc.createElement('style');
|
---|
| 120 | const head = doc.getElementsByTagName('head')[0];
|
---|
| 121 | head.appendChild(node);
|
---|
| 122 |
|
---|
| 123 | const ss = doc.styleSheets[doc.styleSheets.length - 1];
|
---|
| 124 |
|
---|
| 125 | return {
|
---|
| 126 | addRule: function(selector, styles) {
|
---|
| 127 | styles = addVendorPrefix(styles);
|
---|
| 128 |
|
---|
| 129 | try {
|
---|
| 130 | ss.insertRule(selector + '{ ' + styles + '}', 0);
|
---|
| 131 | } catch (e) {
|
---|
| 132 | try {
|
---|
| 133 | ss.addRule(selector, styles);
|
---|
| 134 | // eslint-disable-next-line no-empty
|
---|
| 135 | } catch (e2) {}
|
---|
| 136 | }
|
---|
| 137 | },
|
---|
| 138 |
|
---|
| 139 | destroy: function() {
|
---|
| 140 | head.removeChild(node);
|
---|
| 141 | }
|
---|
| 142 | };
|
---|
| 143 |
|
---|
| 144 | /**
|
---|
| 145 | * Decompose styles, attached specific vendor prefixes
|
---|
| 146 | * and recompose...
|
---|
| 147 | * e.g.
|
---|
| 148 | * 'transition:0.5s linear all; font-size:100px;'
|
---|
| 149 | * becomes
|
---|
| 150 | * '-webkit-transition:0.5s linear all; transition:0.5s linear all; font-size:100px;'
|
---|
| 151 | */
|
---|
| 152 | function addVendorPrefix(styles) {
|
---|
| 153 | const cache = {};
|
---|
| 154 |
|
---|
| 155 | // Decompose into cache registry
|
---|
| 156 | styles.match(/([-A-Za-z]*)\w:\w*([A-Za-z0-9.\-\s]*)/gi).forEach(function(style) {
|
---|
| 157 | const pair = style.split(':');
|
---|
| 158 | const key = pair[0];
|
---|
| 159 |
|
---|
| 160 | switch (key) {
|
---|
| 161 | case 'transition':
|
---|
| 162 | case 'transform':
|
---|
| 163 | case 'animation':
|
---|
| 164 | case 'transition-duration':
|
---|
| 165 | case 'animation-duration':
|
---|
| 166 | cache[key] = cache['-webkit-' + key] = pair[1];
|
---|
| 167 | break;
|
---|
| 168 | default:
|
---|
| 169 | cache[key] = pair[1];
|
---|
| 170 | }
|
---|
| 171 | });
|
---|
| 172 |
|
---|
| 173 | // Recompose full style object (as string)
|
---|
| 174 | styles = '';
|
---|
| 175 | angular.forEach(cache, function(value, key) {
|
---|
| 176 | styles = styles + key + ':' + value + '; ';
|
---|
| 177 | });
|
---|
| 178 |
|
---|
| 179 | return styles;
|
---|
| 180 | }
|
---|
| 181 | };
|
---|
| 182 | })(window, window.angular);
|
---|