| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  | import {CssRule, processRules, ShadowCss} from '@angular/compiler/src/shadow_css'; | 
					
						
							| 
									
										
										
										
											2017-03-02 12:12:46 -08:00
										 |  |  | import {normalizeCSS} from '@angular/platform-browser/testing/src/browser_util'; | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 14:42:55 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |   describe('ShadowCss', function() { | 
					
						
							| 
									
										
										
										
											2015-05-26 09:25:39 -07:00
										 |  |  |     function s(css: string, contentAttr: string, hostAttr: string = '') { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const shadowCss = new ShadowCss(); | 
					
						
							|  |  |  |       const shim = shadowCss.shimCssText(css, contentAttr, hostAttr); | 
					
						
							|  |  |  |       const nlRegexp = /\n/g; | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  |       return normalizeCSS(shim.replace(nlRegexp, '')); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |     it('should handle empty string', () => { | 
					
						
							|  |  |  |       expect(s('', 'contenta')).toEqual(''); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should add an attribute to every rule', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = 'one {color: red;}two {color: red;}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = 'one[contenta] {color:red;}two[contenta] {color:red;}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 17:27:44 -07:00
										 |  |  |     it('should handle invalid css', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = 'one {color: red;}garbage'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = 'one[contenta] {color:red;}garbage'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should add an attribute to every selector', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = 'one, two {color: red;}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = 'one[contenta], two[contenta] {color:red;}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |     it('should support newlines in the selector and content ', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = 'one, \ntwo {\ncolor: red;}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = 'one[contenta], two[contenta] {color:red;}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     it('should handle media rules', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = '@media screen and (max-width:800px, max-height:100%) {div {font-size:50px;}}'; | 
					
						
							|  |  |  |       const expected = | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |           '@media screen and (max-width:800px, max-height:100%) {div[contenta] {font-size:50px;}}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-30 16:26:24 -07:00
										 |  |  |     it('should handle page rules', () => { | 
					
						
							|  |  |  |       const css = '@page {div {font-size:50px;}}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = '@page {div[contenta] {font-size:50px;}}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2016-09-30 16:26:24 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should handle document rules', () => { | 
					
						
							|  |  |  |       const css = '@document url(http://www.w3.org/) {div {font-size:50px;}}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = '@document url(http://www.w3.org/) {div[contenta] {font-size:50px;}}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2016-09-30 16:26:24 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     it('should handle media rules with simple rules', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = '@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = | 
					
						
							|  |  |  |           '@media screen and (max-width:800px) {div[contenta] {font-size:50px;}} div[contenta] {}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 21:18:11 -04:00
										 |  |  |     it('should handle support rules', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = '@supports (display: flex) {section {display: flex;}}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const expected = '@supports (display:flex) {section[contenta] {display:flex;}}'; | 
					
						
							|  |  |  |       expect(s(css, 'contenta')).toEqual(expected); | 
					
						
							| 
									
										
										
										
											2016-04-17 21:18:11 -04:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-02 14:59:35 +02:00
										 |  |  |     // Check that the browser supports unprefixed CSS animation
 | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     it('should handle keyframes rules', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = '@keyframes foo {0% {transform:translate(-50%) scaleX(0);}}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta')).toEqual(css); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-05-26 12:30:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     it('should handle -webkit-keyframes rules', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = '@-webkit-keyframes foo {0% {-webkit-transform:translate(-50%) scaleX(0);}}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta')).toEqual(css); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-05-26 12:30:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     it('should handle complicated selectors', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s('one::before {}', 'contenta')).toEqual('one[contenta]::before {}'); | 
					
						
							|  |  |  |       expect(s('one two {}', 'contenta')).toEqual('one[contenta] two[contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one > two {}', 'contenta')).toEqual('one[contenta] > two[contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one + two {}', 'contenta')).toEqual('one[contenta] + two[contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one ~ two {}', 'contenta')).toEqual('one[contenta] ~ two[contenta] {}'); | 
					
						
							|  |  |  |       const res = s('.one.two > three {}', 'contenta');  // IE swap classes
 | 
					
						
							|  |  |  |       expect( | 
					
						
							|  |  |  |           res == '.one.two[contenta] > three[contenta] {}' || | 
					
						
							|  |  |  |           res == '.two.one[contenta] > three[contenta] {}') | 
					
						
							| 
									
										
										
										
											2015-05-27 10:22:30 +02:00
										 |  |  |           .toEqual(true); | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s('one[attr="value"] {}', 'contenta')).toEqual('one[attr="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr=value] {}', 'contenta')).toEqual('one[attr="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr^="value"] {}', 'contenta')).toEqual('one[attr^="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr$="value"] {}', 'contenta')).toEqual('one[attr$="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr*="value"] {}', 'contenta')).toEqual('one[attr*="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr|="value"] {}', 'contenta')).toEqual('one[attr|="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr~="value"] {}', 'contenta')).toEqual('one[attr~="value"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr="va lue"] {}', 'contenta')).toEqual('one[attr="va lue"][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('one[attr] {}', 'contenta')).toEqual('one[attr][contenta] {}'); | 
					
						
							|  |  |  |       expect(s('[is="one"] {}', 'contenta')).toEqual('[is="one"][contenta] {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |     describe((':host'), () => { | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should handle no context', () => { | 
					
						
							|  |  |  |         expect(s(':host {}', 'contenta', 'a-host')).toEqual('[a-host] {}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should handle tag selector', () => { | 
					
						
							|  |  |  |         expect(s(':host(ul) {}', 'contenta', 'a-host')).toEqual('ul[a-host] {}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should handle class selector', () => { | 
					
						
							|  |  |  |         expect(s(':host(.x) {}', 'contenta', 'a-host')).toEqual('.x[a-host] {}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should handle attribute selector', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host([a="b"]) {}', 'contenta', 'a-host')).toEqual('[a="b"][a-host] {}'); | 
					
						
							|  |  |  |         expect(s(':host([a=b]) {}', 'contenta', 'a-host')).toEqual('[a="b"][a-host] {}'); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should handle multiple tag selectors', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host(ul,li) {}', 'contenta', 'a-host')).toEqual('ul[a-host], li[a-host] {}'); | 
					
						
							|  |  |  |         expect(s(':host(ul,li) > .z {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('ul[a-host] > .z[contenta], li[a-host] > .z[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should handle multiple class selectors', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host(.x,.y) {}', 'contenta', 'a-host')).toEqual('.x[a-host], .y[a-host] {}'); | 
					
						
							|  |  |  |         expect(s(':host(.x,.y) > .z {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('.x[a-host] > .z[contenta], .y[a-host] > .z[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should handle multiple attribute selectors', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host([a="b"],[c=d]) {}', 'contenta', 'a-host')) | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |             .toEqual('[a="b"][a-host], [c="d"][a-host] {}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-10-10 09:15:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 13:56:04 -08:00
										 |  |  |       it('should handle pseudo selectors', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host(:before) {}', 'contenta', 'a-host')).toEqual('[a-host]:before {}'); | 
					
						
							|  |  |  |         expect(s(':host:before {}', 'contenta', 'a-host')).toEqual('[a-host]:before {}'); | 
					
						
							|  |  |  |         expect(s(':host:nth-child(8n+1) {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('[a-host]:nth-child(8n+1) {}'); | 
					
						
							|  |  |  |         expect(s(':host:nth-of-type(8n+1) {}', 'contenta', 'a-host')) | 
					
						
							| 
									
										
										
										
											2016-11-07 13:56:04 -08:00
										 |  |  |             .toEqual('[a-host]:nth-of-type(8n+1) {}'); | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host(.class):before {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('.class[a-host]:before {}'); | 
					
						
							|  |  |  |         expect(s(':host.class:before {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('.class[a-host]:before {}'); | 
					
						
							|  |  |  |         expect(s(':host(:not(p)):before {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('[a-host]:not(p):before {}'); | 
					
						
							| 
									
										
										
										
											2016-10-10 09:15:15 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-11-07 16:55:34 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // see b/63672152
 | 
					
						
							|  |  |  |       it('should handle unexpected selectors in the most reasonable way', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s('cmp:host {}', 'contenta', 'a-host')).toEqual('cmp[a-host] {}'); | 
					
						
							|  |  |  |         expect(s('cmp:host >>> {}', 'contenta', 'a-host')).toEqual('cmp[a-host] {}'); | 
					
						
							|  |  |  |         expect(s('cmp:host child {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('cmp[a-host] child[contenta] {}'); | 
					
						
							|  |  |  |         expect(s('cmp:host >>> child {}', 'contenta', 'a-host')).toEqual('cmp[a-host] child {}'); | 
					
						
							|  |  |  |         expect(s('cmp :host {}', 'contenta', 'a-host')).toEqual('cmp [a-host] {}'); | 
					
						
							|  |  |  |         expect(s('cmp :host >>> {}', 'contenta', 'a-host')).toEqual('cmp [a-host] {}'); | 
					
						
							|  |  |  |         expect(s('cmp :host child {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('cmp [a-host] child[contenta] {}'); | 
					
						
							|  |  |  |         expect(s('cmp :host >>> child {}', 'contenta', 'a-host')).toEqual('cmp [a-host] child {}'); | 
					
						
							| 
									
										
										
										
											2017-11-07 16:55:34 -08:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |     describe((':host-context'), () => { | 
					
						
							|  |  |  |       it('should handle tag selector', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host-context(div) {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('div[a-host], div [a-host] {}'); | 
					
						
							|  |  |  |         expect(s(':host-context(ul) > .y {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('ul[a-host] > .y[contenta], ul [a-host] > .y[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should handle class selector', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host-context(.x) {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('.x[a-host], .x [a-host] {}'); | 
					
						
							| 
									
										
										
										
											2016-09-30 11:42:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host-context(.x) > .y {}', 'contenta', 'a-host')) | 
					
						
							|  |  |  |             .toEqual('.x[a-host] > .y[contenta], .x [a-host] > .y[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-09-30 11:42:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |       it('should handle attribute selector', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host-context([a="b"]) {}', 'contenta', 'a-host')) | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |             .toEqual('[a="b"][a-host], [a="b"] [a-host] {}'); | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |         expect(s(':host-context([a=b]) {}', 'contenta', 'a-host')) | 
					
						
							| 
									
										
										
										
											2016-10-04 15:40:31 -07:00
										 |  |  |             .toEqual('[a=b][a-host], [a="b"] [a-host] {}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should support polyfill-next-selector', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       let css = s('polyfill-next-selector {content: \'x > y\'} z {}', 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('x[contenta] > y[contenta]{}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s('polyfill-next-selector {content: "x > y"} z {}', 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('x[contenta] > y[contenta]{}'); | 
					
						
							| 
									
										
										
										
											2016-09-30 13:20:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s(`polyfill-next-selector {content: 'button[priority="1"]'} z {}`, 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('button[priority="1"][contenta]{}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should support polyfill-unscoped-rule', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       let css = s('polyfill-unscoped-rule {content: \'#menu > .bar\';color: blue;}', 'contenta'); | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  |       expect(css).toContain('#menu > .bar {;color:blue;}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s('polyfill-unscoped-rule {content: "#menu > .bar";color: blue;}', 'contenta'); | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  |       expect(css).toContain('#menu > .bar {;color:blue;}'); | 
					
						
							| 
									
										
										
										
											2016-09-30 13:20:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s(`polyfill-unscoped-rule {content: 'button[priority="1"]'}`, 'contenta'); | 
					
						
							| 
									
										
										
										
											2016-09-30 13:20:48 -07:00
										 |  |  |       expect(css).toContain('button[priority="1"] {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-10 10:38:24 -07:00
										 |  |  |     it('should support multiple instances polyfill-unscoped-rule', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const css = | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |           s('polyfill-unscoped-rule {content: \'foo\';color: blue;}' + | 
					
						
							|  |  |  |                 'polyfill-unscoped-rule {content: \'bar\';color: blue;}', | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |             'contenta'); | 
					
						
							| 
									
										
										
										
											2016-08-26 16:11:57 -07:00
										 |  |  |       expect(css).toContain('foo {;color:blue;}'); | 
					
						
							|  |  |  |       expect(css).toContain('bar {;color:blue;}'); | 
					
						
							| 
									
										
										
										
											2015-07-10 10:38:24 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     it('should support polyfill-rule', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       let css = s('polyfill-rule {content: \':host.foo .bar\';color: blue;}', 'contenta', 'a-host'); | 
					
						
							|  |  |  |       expect(css).toEqual('.foo[a-host] .bar[contenta] {;color:blue;}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s('polyfill-rule {content: ":host.foo .bar";color:blue;}', 'contenta', 'a-host'); | 
					
						
							|  |  |  |       expect(css).toEqual('.foo[a-host] .bar[contenta] {;color:blue;}'); | 
					
						
							| 
									
										
										
										
											2016-09-30 13:20:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       css = s(`polyfill-rule {content: 'button[priority="1"]'}`, 'contenta', 'a-host'); | 
					
						
							|  |  |  |       expect(css).toEqual('button[priority="1"][contenta] {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should handle ::shadow', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s('x::shadow > y {}', 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('x[contenta] > y[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should handle /deep/', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s('x /deep/ y {}', 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('x[contenta] y {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should handle >>>', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s('x >>> y {}', 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('x[contenta] y {}'); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-07 13:37:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |     it('should handle ::ng-deep', () => { | 
					
						
							|  |  |  |       let css = '::ng-deep y {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta')).toEqual('y {}'); | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |       css = 'x ::ng-deep y {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta')).toEqual('x[contenta] y {}'); | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |       css = ':host > ::ng-deep .x {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta', 'h')).toEqual('[h] > .x {}'); | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |       css = ':host ::ng-deep > .x {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta', 'h')).toEqual('[h] > .x {}'); | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |       css = ':host > ::ng-deep > .x {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s(css, 'contenta', 'h')).toEqual('[h] > > .x {}'); | 
					
						
							| 
									
										
										
										
											2017-06-21 16:53:37 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     it('should pass through @import directives', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s(styleStr, 'contenta'); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |       expect(css).toEqual(styleStr); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-15 12:15:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     it('should shim rules after @import', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const styleStr = '@import url("a"); div {}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s(styleStr, 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('@import url("a"); div[contenta] {}'); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should leave calc() unchanged', () => { | 
					
						
							| 
									
										
										
										
											2016-08-13 06:20:58 +08:00
										 |  |  |       const styleStr = 'div {height:calc(100% - 55px);}'; | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       const css = s(styleStr, 'contenta'); | 
					
						
							|  |  |  |       expect(css).toEqual('div[contenta] {height:calc(100% - 55px);}'); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |     it('should strip comments', () => { | 
					
						
							|  |  |  |       expect(s('/* x */b {c}', 'contenta')).toEqual('b[contenta] {c}'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |     it('should ignore special characters in comments', () => { | 
					
						
							|  |  |  |       expect(s('/* {;, */b {c}', 'contenta')).toEqual('b[contenta] {c}'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |     it('should support multiline comments', () => { | 
					
						
							|  |  |  |       expect(s('/* \n */b {c}', 'contenta')).toEqual('b[contenta] {c}'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-12 16:39:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should keep sourceMappingURL comments', () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |       expect(s('b {c}/*# sourceMappingURL=data:x */', 'contenta')) | 
					
						
							|  |  |  |           .toEqual('b[contenta] {c}/*# sourceMappingURL=data:x */'); | 
					
						
							|  |  |  |       expect(s('b {c}/* #sourceMappingURL=data:x */', 'contenta')) | 
					
						
							|  |  |  |           .toEqual('b[contenta] {c}/* #sourceMappingURL=data:x */'); | 
					
						
							| 
									
										
										
										
											2016-08-12 16:39:43 +08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-18 22:11:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should keep sourceURL comments', () => { | 
					
						
							|  |  |  |       expect(s('/*# sourceMappingURL=data:x */b {c}/*# sourceURL=xxx */', 'contenta')) | 
					
						
							|  |  |  |           .toEqual('b[contenta] {c}/*# sourceMappingURL=data:x *//*# sourceURL=xxx */'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |   describe('processRules', () => { | 
					
						
							|  |  |  |     describe('parse rules', () => { | 
					
						
							|  |  |  |       function captureRules(input: string): CssRule[] { | 
					
						
							| 
									
										
										
										
											2016-09-30 13:06:14 -07:00
										 |  |  |         const result: CssRule[] = []; | 
					
						
							|  |  |  |         processRules(input, (cssRule) => { | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |           result.push(cssRule); | 
					
						
							|  |  |  |           return cssRule; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should work with empty css', () => { | 
					
						
							|  |  |  |         expect(captureRules('')).toEqual([]); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should capture a rule without body', () => { | 
					
						
							|  |  |  |         expect(captureRules('a;')).toEqual([new CssRule('a', '')]); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:14:18 -07:00
										 |  |  |       it('should capture css rules with body', () => { | 
					
						
							|  |  |  |         expect(captureRules('a {b}')).toEqual([new CssRule('a', 'b')]); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should capture css rules with nested rules', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         expect(captureRules('a {b {c}} d {e}')).toEqual([ | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |           new CssRule('a', 'b {c}'), | 
					
						
							|  |  |  |           new CssRule('d', 'e'), | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         ]); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 15:47:48 +08:00
										 |  |  |       it('should capture multiple rules where some have no body', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         expect(captureRules('@import a ; b {c}')).toEqual([ | 
					
						
							| 
									
										
										
										
											2017-11-08 15:27:27 -08:00
										 |  |  |           new CssRule('@import a', ''), | 
					
						
							|  |  |  |           new CssRule('b', 'c'), | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         ]); | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('modify rules', () => { | 
					
						
							|  |  |  |       it('should allow to change the selector while preserving whitespaces', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         expect(processRules( | 
					
						
							| 
									
										
										
										
											2016-09-30 13:06:14 -07:00
										 |  |  |                    '@import a; b {c {d}} e {f}', | 
					
						
							|  |  |  |                    (cssRule: CssRule) => new CssRule(cssRule.selector + '2', cssRule.content))) | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |             .toEqual('@import a2; b2 {c {d}} e2 {f}'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should allow to change the content', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         expect(processRules( | 
					
						
							| 
									
										
										
										
											2016-09-30 13:06:14 -07:00
										 |  |  |                    'a {b}', | 
					
						
							|  |  |  |                    (cssRule: CssRule) => new CssRule(cssRule.selector, cssRule.content + '2'))) | 
					
						
							| 
									
										
										
										
											2015-10-30 15:09:04 -07:00
										 |  |  |             .toEqual('a {b2}'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-10-29 10:57:54 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-03-23 14:10:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | } |