\`
                })
                export class MyComponent {
                  myImage = 'url(foo.jpg)';
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
           }
         };
         const template = `
          MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
            type: MyComponent,
            selectors: [["my-component"]],
            decls: 1,
            vars: 1,
            template:  function MyComponent_Template(rf, ctx) {
              if (rf & 1) {
                $r3$.ɵɵelement(0, "div");
              }
              if (rf & 2) {
                $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
                $r3$.ɵɵstyleProp("background-image", ctx.myImage);
              }
            },
            encapsulation: 2
          });
        `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should support [style.foo.suffix] style bindings with a suffix', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component, NgModule} from '@angular/core';
             @Component({
               selector: 'my-component',
               template: \`
\`
             })
             export class MyComponent {
             }
             @NgModule({declarations: [MyComponent]})
             export class MyModule {}
         `
        }
      };
      const template = `
          template:  function MyComponent_Template(rf, ctx) {
            if (rf & 1) {
              $r3$.ɵɵelement(0, "div");
            }
            if (rf & 2) {
              $r3$.ɵɵstyleProp("font-size", 12, "px");
            }
          }
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should not create instructions for empty style bindings', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component, NgModule} from '@angular/core';
            @Component({
              selector: 'my-component',
              template: \`
\`
            })
            export class MyComponent {
            }
            @NgModule({declarations: [MyComponent]})
            export class MyModule {}
          `
        }
      };
      const result = compile(files, angularFiles);
      expect(result.source).not.toContain('styling');
    });
  });
  describe('[class]', () => {
    it('should create class styling instructions on the element', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
\`
                })
                export class MyComponent {
                  myClassExp = {'foo':true}
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          template: function MyComponent_Template(rf, $ctx$) {
            if (rf & 1) {
              $r3$.ɵɵelement(0, "div");
            }
            if (rf & 2) {
              $r3$.ɵɵclassMap($ctx$.myClassExp);
            }
          }
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should place initial, multi, singular and application followed by attribute class instructions in the template code in that order',
       () => {
         const files = {
           app: {
             'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
\`
                })
                export class MyComponent {
                  myClassExp = {a:true, b:true};
                  yesToApple = true;
                  yesToOrange = true;
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
           }
         };
         const template = `
          …
          MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
              type: MyComponent,
              selectors:[["my-component"]],
              decls: 1,
              vars: 5,
              consts: [[${AttributeMarker.Classes}, "grape"]],
              template:  function MyComponent_Template(rf, $ctx$) {
                if (rf & 1) {
                  $r3$.ɵɵelement(0, "div", 0);
                }
                if (rf & 2) {
                  $r3$.ɵɵclassMap($ctx$.myClassExp);
                  $r3$.ɵɵclassProp("apple", $ctx$.yesToApple)("orange", $ctx$.yesToOrange);
                  $r3$.ɵɵattribute("class", "banana");
                }
              },
              encapsulation: 2
            });
        `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should not generate the styling apply instruction if there are only static style/class attributes',
       () => {
         const files = {
           app: {
             'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
\`
                })
                export class MyComponent {}
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
           }
         };
         const template = `
          …
          MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
              type: MyComponent,
              selectors:[["my-component"]],
              decls: 1,
              vars: 2,
              consts: [[${AttributeMarker.Classes}, "foo", ${AttributeMarker.Styles}, "width", "100px"]],
              template:  function MyComponent_Template(rf, $ctx$) {
                if (rf & 1) {
                  $r3$.ɵɵelement(0, "div", 0);
                }
                if (rf & 2) {
                  $r3$.ɵɵattribute("class", "round")("style", "height:100px", $r3$.ɵɵsanitizeStyle);
                }
              },
              encapsulation: 2
            });
        `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should not create instructions for empty class bindings', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component, NgModule} from '@angular/core';
            @Component({
              selector: 'my-component',
              template: \`
\`
            })
            export class MyComponent {
            }
            @NgModule({declarations: [MyComponent]})
            export class MyModule {}
          `
        }
      };
      const result = compile(files, angularFiles);
      expect(result.source).not.toContain('styling');
    });
  });
  describe('[style] mixed with [class]', () => {
    it('should split [style] and [class] bindings into a separate instructions', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
\`
                })
                export class MyComponent {
                  myStyleExp = [{color:'red'}, {color:'blue', duration:1000}]
                  myClassExp = 'foo bar apple';
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          template: function MyComponent_Template(rf, $ctx$) {
            if (rf & 1) {
              $r3$.ɵɵelement(0, "div");
            }
            if (rf & 2) {
              $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
              $r3$.ɵɵstyleMap($ctx$.myStyleExp);
              $r3$.ɵɵclassMap($ctx$.myClassExp);
            }
          }
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should stamp out pipe definitions in the creation block if used by styling bindings',
       () => {
         const files = {
           app: {
             'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
\`
                })
                export class MyComponent {
                  myStyleExp = [{color:'red'}, {color:'blue', duration:1000}]
                  myClassExp = 'foo bar apple';
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
           }
         };
         const template = `
          template: function MyComponent_Template(rf, $ctx$) {
            if (rf & 1) {
              $r3$.ɵɵelementStart(0, "div");
              $r3$.ɵɵpipe(1, "stylePipe");
              $r3$.ɵɵpipe(2, "classPipe");
              $r3$.ɵɵelementEnd();
            }
            if (rf & 2) {
              $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
              $r3$.ɵɵstyleMap($r3$.ɵɵpipeBind1(1, 4, $ctx$.myStyleExp));
              $r3$.ɵɵclassMap($r3$.ɵɵpipeBind1(2, 6, $ctx$.myClassExp));
            }
          }
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should properly offset multiple style pipe references for styling bindings', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
                    
                         {{ item }}
\`
                })
                export class MyComponent {
                  myStyleExp = {};
                  fooExp = 'foo';
                  barExp = 'bar';
                  bazExp = 'baz';
                  items = [1,2,3];
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          template: function MyComponent_Template(rf, $ctx$) {
            if (rf & 1) {
              $r3$.ɵɵelementStart(0, "div");
              $r3$.ɵɵpipe(1, "pipe");
              $r3$.ɵɵpipe(2, "pipe");
              $r3$.ɵɵpipe(3, "pipe");
              $r3$.ɵɵpipe(4, "pipe");
              $r3$.ɵɵtext(5);
              $r3$.ɵɵelementEnd();
            }
            if (rf & 2) {
              $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
              $r3$.ɵɵstyleMap($r3$.ɵɵpipeBind2(1, 8, $ctx$.myStyleExp, 1000));
              $r3$.ɵɵclassMap($r3$.ɵɵpureFunction0(20, _c0));
              $r3$.ɵɵstyleProp("bar", $r3$.ɵɵpipeBind2(2, 11, $ctx$.barExp, 3000))("baz", $r3$.ɵɵpipeBind2(3, 14, $ctx$.bazExp, 4000));
              $r3$.ɵɵclassProp("foo", $r3$.ɵɵpipeBind2(4, 17, $ctx$.fooExp, 2000));
              $r3$.ɵɵadvance(5);
             $r3$.ɵɵtextInterpolate1(" ", $ctx$.item, "");
            }
          }
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should always generate select() statements before any styling instructions', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
                    
                    
                    
                    
                  \`
                })
                export class MyComponent {
                  w1 = '100px';
                  h1 = '100px';
                  a1 = true;
                  r1 = true;
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          …
          template: function MyComponent_Template(rf, $ctx$) {
            …
            if (rf & 2) {
              $r3$.ɵɵstyleProp("width", $ctx$.w1);
              $r3$.ɵɵadvance(1);
              $r3$.ɵɵstyleProp("height", $ctx$.h1);
              $r3$.ɵɵadvance(1);
              $r3$.ɵɵclassProp("active", $ctx$.a1);
              $r3$.ɵɵadvance(1);
              $r3$.ɵɵclassProp("removed", $ctx$.r1);
            }
          }
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
  });
  describe('@Component host styles/classes', () => {
    it('should generate style/class instructions for a host component creation definition', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule, HostBinding} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: '',
                  host: {
                    'style': 'width:200px; height:500px',
                    'class': 'foo baz'
                  }
                })
                export class MyComponent {
                  @HostBinding('style')
                  myStyle = {width:'100px'};
                  @HostBinding('class')
                  myClass = {bar:false};
                  @HostBinding('style.color')
                  myColorProp = 'red';
                  @HostBinding('class.foo')
                  myFooClass = 'red';
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
            if (rf & 1) {
              $r3$.ɵɵallocHostVars(6);
              $r3$.ɵɵelementHostAttrs($e0_attrs$);
            }
            if (rf & 2) {
              $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
              $r3$.ɵɵstyleMap(ctx.myStyle);
              $r3$.ɵɵclassMap(ctx.myClass);
              $r3$.ɵɵstyleProp("color", ctx.myColorProp);
              $r3$.ɵɵclassProp("foo", ctx.myFooClass);
            }
          },
          decls: 0,
          vars: 0,
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should generate style/class instructions for multiple host binding definitions', () => {
      const files = {
        app: {
          'spec.ts': `
                import {Component, NgModule, HostBinding} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: '',
                  host: {
                    '[style.height.pt]': 'myHeightProp',
                    '[class.bar]': 'myBarClass'
                  }
                })
                export class MyComponent {
                  myHeightProp = 20;
                  myBarClass = true;
                  @HostBinding('style')
                  myStyle = {};
                  @HostBinding('style.width')
                  myWidthProp = '500px';
                  @HostBinding('class.foo')
                  myFooClass = true;
                  @HostBinding('class')
                  myClasses = {a:true, b:true};
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
        }
      };
      const template = `
          hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
            if (rf & 1) {
              $r3$.ɵɵallocHostVars(8);
            }
            if (rf & 2) {
              $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
              $r3$.ɵɵstyleMap(ctx.myStyle);
              $r3$.ɵɵclassMap(ctx.myClasses);
              $r3$.ɵɵstyleProp("height", ctx.myHeightProp, "pt")("width", ctx.myWidthProp);
              $r3$.ɵɵclassProp("bar", ctx.myBarClass)("foo", ctx.myFooClass);
            }
          },
          decls: 0,
          vars: 0,
          `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should generate override instructions for only single-level styling bindings when !important is present',
       () => {
         const files = {
           app: {
             'spec.ts': `
                import {Component, NgModule, HostBinding} from '@angular/core';
                @Component({
                  selector: 'my-component',
                  template: \`
                    
                  \`,
                  host: {
                    '[style!important]': 'myStyleExp',
                    '[class!important]': 'myClassExp'
                  }
                })
                export class MyComponent {
                  @HostBinding('class.foo!important')
                  myFooClassExp = true;
                  @HostBinding('style.width!important')
                  myWidthExp = '100px';
                  myBarClassExp = true;
                  myHeightExp = '200px';
                }
                @NgModule({declarations: [MyComponent]})
                export class MyModule {}
            `
           }
         };
         const template = `
            function MyComponent_Template(rf, ctx) {
              if (rf & 1) {
                $r3$.ɵɵelement(0, "div");
              }
              if (rf & 2) {
                $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
                $r3$.ɵɵstyleMap(ctx.myStyleExp);
                $r3$.ɵɵclassMap(ctx.myClassExp);
                $r3$.ɵɵstyleProp("height", ctx.myHeightExp);
                $r3$.ɵɵclassProp("bar", ctx.myBarClassExp);
              }
            },
          `;
         const hostBindings = `
            hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
              if (rf & 1) {
                $r3$.ɵɵallocHostVars(6);
              }
              if (rf & 2) {
                $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
                $r3$.ɵɵstyleMap(ctx.myStyleExp);
                $r3$.ɵɵclassMap(ctx.myClassExp);
                $r3$.ɵɵstyleProp("width", ctx.myWidthExp);
                $r3$.ɵɵclassProp("foo", ctx.myFooClassExp);
              }
            },
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, hostBindings, 'Incorrect template');
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should generate styling instructions for multiple directives that contain host binding definitions',
       () => {
         const files = {
           app: {
             'spec.ts': `
                import {Directive, Component, NgModule, HostBinding} from '@angular/core';
                @Directive({selector: '[myClassDir]'})
                export class ClassDirective {
                  @HostBinding('class')
                  myClassMap = {red: true};
                }
                @Directive({selector: '[myWidthDir]'})
                export class WidthDirective {
                  @HostBinding('style.width')
                  myWidth = 200;
                  @HostBinding('class.foo')
                  myFooClass = true;
                }
                @Directive({selector: '[myHeightDir]'})
                export class HeightDirective {
                  @HostBinding('style.height')
                  myHeight = 200;
                  @HostBinding('class.bar')
                  myBarClass = true;
                }
                @Component({
                  selector: 'my-component',
                  template: '
',
                })
                export class MyComponent {
                }
                @NgModule({declarations: [MyComponent, WidthDirective, HeightDirective, ClassDirective]})
                export class MyModule {}
            `
           }
         };
         // NOTE: IF YOU ARE CHANGING THIS COMPILER SPEC, YOU MAY NEED TO CHANGE THE DIRECTIVE
         // DEF THAT'S HARD-CODED IN `ng_class.ts`.
         const template = `
          function ClassDirective_HostBindings(rf, ctx, elIndex) {
            if (rf & 1) {
              $r3$.ɵɵallocHostVars(2);
            }
            if (rf & 2) {
              $r3$.ɵɵclassMap(ctx.myClassMap);
            }
          }
          …
          function WidthDirective_HostBindings(rf, ctx, elIndex) {
            if (rf & 1) {
              $r3$.ɵɵallocHostVars(2);
            }
            if (rf & 2) {
              $r3$.ɵɵstyleProp("width", ctx.myWidth);
              $r3$.ɵɵclassProp("foo", ctx.myFooClass);
            }
          }
          …
          function HeightDirective_HostBindings(rf, ctx, elIndex) {
            if (rf & 1) {
              $r3$.ɵɵallocHostVars(2);
            }
            if (rf & 2) {
              $r3$.ɵɵstyleProp("height", ctx.myHeight);
              $r3$.ɵɵclassProp("bar", ctx.myBarClass);
            }
          }
          …
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
  });
  describe('interpolations', () => {
    it('should generate the proper update instructions for interpolated classes', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: \`
                
                
                
                
                
                
                
                
                
                
              \`
            })
            export class MyComponent {
            }
          `
        }
      };
      const template = `
      …
        if (rf & 2) {
          $r3$.ɵɵclassMapInterpolateV(["a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i", ctx.nine, "j"]);
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate8("a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate7("a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate6("a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate5("a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate4("a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate3("a", ctx.one, "b", ctx.two, "c", ctx.three, "d");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate2("a", ctx.one, "b", ctx.two, "c");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMapInterpolate1("a", ctx.one, "b");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵclassMap(ctx.one);
      }
      …
      `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect handling of interpolated classes');
    });
    it('should throw for interpolations inside `style`', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: '
'
            })
            export class MyComponent {
            }
          `
        }
      };
      expect(() => compile(files, angularFiles)).toThrowError(/Unexpected interpolation/);
    });
    it('should throw for interpolations inside individual class bindings', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: '
'
            })
            export class MyComponent {
            }
          `
        }
      };
      expect(() => compile(files, angularFiles)).toThrowError(/Unexpected interpolation/);
    });
    it('should generate the proper update instructions for interpolated style properties', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: \`
                
                
                
                
                
                
                
                
                
                
              \`
            })
            export class MyComponent {
            }
          `
        }
      };
      const template = `
      …
        if (rf & 2) {
          $r3$.ɵɵstylePropInterpolateV("color", ["a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i", ctx.nine, "j"]);
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate8("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate7("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate6("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate5("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate4("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate3("color", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate2("color", "a", ctx.one, "b", ctx.two, "c");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstylePropInterpolate1("color", "a", ctx.one, "b");
          $r3$.ɵɵadvance(1);
          $r3$.ɵɵstyleProp("color", ctx.one);
      }
      …
      `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
    });
    it('should generate update instructions for interpolated style properties with a suffix',
       () => {
         const files = {
           app: {
             'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: \`
                
              \`
            })
            export class MyComponent {
            }
          `
           }
         };
         const template = `
            …
            if (rf & 2) {
              $r3$.ɵɵstylePropInterpolate2("width", "a", ctx.one, "b", ctx.two, "c", "px");
            }
            …
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
       });
    it('should generate update instructions for interpolated style properties with !important',
       () => {
         const files = {
           app: {
             'spec.ts': `
            import {Component} from '@angular/core';
            @Component({
              template: \`
                
              \`
            })
            export class MyComponent {
            }
          `
           }
         };
         const template = `
            …
            if (rf & 2) {
              $r3$.ɵɵstylePropInterpolate2("width", "a", ctx.one, "b", ctx.two, "c");
            }
            …
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
       });
  });
  describe('instruction chaining', () => {
    it('should chain classProp instruction calls', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component} from '@angular/core';
             @Component({
               template: \`
\`
             })
             export class MyComponent {
               yesToApple = true;
               yesToOrange = true;
               tesToTomato = false;
             }
         `
        }
      };
      const template = `
       …
       MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
        …
        template: function MyComponent_Template(rf, $ctx$) {
          …
          if (rf & 2) {
            $r3$.ɵɵclassProp("apple", $ctx$.yesToApple)("orange", $ctx$.yesToOrange)("tomato", $ctx$.yesToTomato);
          }
        },
        encapsulation: 2
      });
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should chain styleProp instruction calls', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component} from '@angular/core';
             @Component({
               template: \`
\`
             })
             export class MyComponent {
               color = 'red';
               border = '1px solid purple';
               transition = 'all 1337ms ease';
             }
         `
        }
      };
      const template = `
       …
       MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
        …
        template: function MyComponent_Template(rf, $ctx$) {
          …
          if (rf & 2) {
            $r3$.ɵɵstyleProp("color", $ctx$.color)("border", $ctx$.border)("transition", $ctx$.transition);
          }
        },
        encapsulation: 2
      });
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should chain mixed styleProp and classProp calls', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component} from '@angular/core';
             @Component({
               template: \`
\`
             })
             export class MyComponent {
               color = 'red';
               border = '1px solid purple';
               transition = 'all 1337ms ease';
               yesToApple = true;
               yesToOrange = true;
               tesToTomato = false;
             }
         `
        }
      };
      const template = `
       …
       MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
        …
        template: function MyComponent_Template(rf, $ctx$) {
          …
          if (rf & 2) {
            $r3$.ɵɵstyleProp("color", $ctx$.color)("border", $ctx$.border)("transition", $ctx$.transition);
            $r3$.ɵɵclassProp("apple", $ctx$.yesToApple)("orange", $ctx$.yesToOrange)("tomato", $ctx$.yesToTomato);
          }
        },
        encapsulation: 2
      });
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should chain style interpolations of the same kind', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component} from '@angular/core';
             @Component({
               template: \`
\`
             })
             export class MyComponent {
             }
         `
        }
      };
      const template = `
       …
       MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
        …
        template: function MyComponent_Template(rf, $ctx$) {
          …
          if (rf & 2) {
            $r3$.ɵɵstylePropInterpolate1("color", "a", ctx.one, "b")("border", "a", ctx.one, "b")("transition", "a", ctx.one, "b");
          }
        },
        encapsulation: 2
      });
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should chain style interpolations of multiple kinds', () => {
      const files = {
        app: {
          'spec.ts': `
             import {Component} from '@angular/core';
             @Component({
               template: \`
\`
             })
             export class MyComponent {
             }
         `
        }
      };
      const template = `
       …
       MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
        …
        template: function MyComponent_Template(rf, $ctx$) {
          …
          if (rf & 2) {
            $r3$.ɵɵstylePropInterpolate1("color", "a", ctx.one, "b")("border", "a", ctx.one, "b");
            $r3$.ɵɵstylePropInterpolate2("transition", "a", ctx.one, "b", ctx.two, "c")("width", "a", ctx.one, "b", ctx.two, "c");
            $r3$.ɵɵstylePropInterpolate3("height", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d")("top", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d");
          }
        },
        encapsulation: 2
      });
     `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
    it('should break into multiple chains if there are other styling instructions in between',
       () => {
         const files = {
           app: {
             'spec.ts': `
                  import {Component} from '@angular/core';
                  @Component({
                    template: \`
\`
                  })
                  export class MyComponent {
                    transition = 'all 1337ms ease';
                    width = '42px';
                    yesToApple = true;
                    yesToOrange = true;
                  }
              `
           }
         };
         const template = `
            …
            MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
              …
              template: function MyComponent_Template(rf, $ctx$) {
                …
                if (rf & 2) {
                  $r3$.ɵɵstylePropInterpolate1("color", "a", ctx.one, "b")("border", "a", ctx.one, "b");
                  $r3$.ɵɵstyleProp("transition", ctx.transition)("width", ctx.width);
                  $r3$.ɵɵstylePropInterpolate1("height", "a", ctx.one, "b")("top", "a", ctx.one, "b");
                  $r3$.ɵɵclassProp("apple", ctx.yesToApple)("orange", ctx.yesToOrange);
                }
              },
              encapsulation: 2
            });
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should break into multiple chains if there are other styling interpolation instructions in between',
       () => {
         const files = {
           app: {
             'spec.ts': `
                  import {Component} from '@angular/core';
                  @Component({
                    template: \`
\`
                  })
                  export class MyComponent {
                    transition = 'all 1337ms ease';
                    width = '42px';
                  }
              `
           }
         };
         const template = `
            …
            MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
              …
              template: function MyComponent_Template(rf, $ctx$) {
                …
                if (rf & 2) {
                  $r3$.ɵɵstylePropInterpolate1("color", "a", ctx.one, "b")("border", "a", ctx.one, "b");
                  $r3$.ɵɵstylePropInterpolate2("transition", "a", ctx.one, "b", ctx.two, "c");
                  $r3$.ɵɵstylePropInterpolate3("width", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d");
                  $r3$.ɵɵstylePropInterpolate1("height", "a", ctx.one, "b")("top", "a", ctx.one, "b");
                }
              },
              encapsulation: 2
            });
          `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should chain styling instructions inside host bindings', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component, HostBinding} from '@angular/core';
            @Component({
              template: '',
              host: {
                '[class.apple]': 'yesToApple',
                '[style.color]': 'color',
                '[class.tomato]': 'yesToTomato',
                '[style.transition]': 'transition'
              }
            })
            export class MyComponent {
              color = 'red';
              transition = 'all 1337ms ease';
              yesToApple = true;
              tesToTomato = false;
              @HostBinding('style.border')
              border = '1px solid purple';
              @HostBinding('class.orange')
              yesToOrange = true;
            }
           `
        }
      };
      const template = `
         …
         MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({
          …
          hostBindings: function MyComponent_HostBindings(rf, $ctx$, elIndex) {
            …
            if (rf & 2) {
              $r3$.ɵɵstyleProp("color", $ctx$.color)("transition", $ctx$.transition)("border", $ctx$.border);
              $r3$.ɵɵclassProp("apple", $ctx$.yesToApple)("tomato", $ctx$.yesToTomato)("orange", $ctx$.yesToOrange);
            }
          },
          …
        });
       `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
  });
  it('should count only non-style and non-class host bindings on Components', () => {
    const files = {
      app: {
        'spec.ts': `
          import {Component, NgModule, HostBinding} from '@angular/core';
          @Component({
            selector: 'my-component',
            template: '',
            host: {
              'style': 'width:200px; height:500px',
              'class': 'foo baz',
              'title': 'foo title'
            }
          })
          export class MyComponent {
            @HostBinding('style')
            myStyle = {width:'100px'};
            @HostBinding('class')
            myClass = {bar:false};
            @HostBinding('id')
            id = 'some id';
            @HostBinding('title')
            title = 'some title';
            @Input('name')
            name = '';
          }
          @NgModule({declarations: [MyComponent]})
          export class MyModule {}
        `
      }
    };
    const template = `
      const $_c0$ = ["title", "foo title", ${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"];
      …
      hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
        if (rf & 1) {
          $r3$.ɵɵallocHostVars(6);
          $r3$.ɵɵelementHostAttrs($_c0$);
        }
        if (rf & 2) {
          $r3$.ɵɵhostProperty("id", ctx.id)("title", ctx.title);
          $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
          $r3$.ɵɵstyleMap(ctx.myStyle);
          $r3$.ɵɵclassMap(ctx.myClass);
        }
      }
    `;
    const result = compile(files, angularFiles);
    expectEmit(result.source, template, 'Incorrect template');
  });
  it('should count only non-style and non-class host bindings on Directives', () => {
    const files = {
      app: {
        'spec.ts': `
          import {Directive, Component, NgModule, HostBinding} from '@angular/core';
          @Directive({selector: '[myWidthDir]'})
          export class WidthDirective {
            @HostBinding('style.width')
            myWidth = 200;
            @HostBinding('class.foo')
            myFooClass = true;
            @HostBinding('id')
            id = 'some id';
            @HostBinding('title')
            title = 'some title';
          }
        `
      }
    };
    const template = `
      hostBindings: function WidthDirective_HostBindings(rf, ctx, elIndex) {
        if (rf & 1) {
          $r3$.ɵɵallocHostVars(4);
        }
        if (rf & 2) {
          $r3$.ɵɵhostProperty("id", ctx.id)("title", ctx.title);
          $r3$.ɵɵstyleProp("width", ctx.myWidth);
          $r3$.ɵɵclassProp("foo", ctx.myFooClass);
        }
      }
    `;
    const result = compile(files, angularFiles);
    expectEmit(result.source, template, 'Incorrect template');
  });
  describe('new styling refactor', () => {
    it('should generate a `styleSanitizer` instruction when one or more sanitizable style properties are statically detected',
       () => {
         const files = {
           app: {
             'spec.ts': `
            import {Component, NgModule} from '@angular/core';
            @Component({
              selector: 'my-app',
              template: \`
                
              \`
            })
            export class MyAppComp {
              bgExp = '';
            }
          `
           }
         };
         const template = `
        template: function MyAppComp_Template(rf, ctx) {
          …
          if (rf & 2) {
            $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
            $r3$.ɵɵstyleProp("background-image", ctx.bgExp);
          }
          …
        }
      `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should generate a `styleSanitizer` instruction when a `styleMap` instruction is used',
       () => {
         const files = {
           app: {
             'spec.ts': `
            import {Component, NgModule} from '@angular/core';
            @Component({
              selector: 'my-app',
              template: \`
                
              \`
            })
            export class MyAppComp {
              mapExp = {};
            }
          `
           }
         };
         const template = `
        template: function MyAppComp_Template(rf, ctx) {
          …
          if (rf & 2) {
            $r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
            $r3$.ɵɵstyleMap(ctx.mapExp);
          }
          …
        }
      `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('shouldn\'t generate a `styleSanitizer` instruction when class-based instructions are used',
       () => {
         const files = {
           app: {
             'spec.ts': `
            import {Component, NgModule} from '@angular/core';
            @Component({
              selector: 'my-app',
              template: \`
                
              \`
            })
            export class MyAppComp {
              mapExp = {};
              nameExp = true;
            }
          `
           }
         };
         const template = `
        template: function MyAppComp_Template(rf, ctx) {
          …
          if (rf & 2) {
            $r3$.ɵɵclassMap(ctx.mapExp);
            $r3$.ɵɵclassProp("name", ctx.nameExp);
          }
          …
        }
      `;
         const result = compile(files, angularFiles);
         expectEmit(result.source, template, 'Incorrect template');
       });
    it('should generate the correct amount of host bindings when styling is present', () => {
      const files = {
        app: {
          'spec.ts': `
            import {Component, Directive, NgModule} from '@angular/core';
            @Directive({
              selector: '[my-dir]',
              host: {
                '[title]': 'title',
                '[class.foo]': 'foo',
                '[@anim]': \`{
                  value: _animValue,
                  params: {
                    param1: _animParam1,
                    param2: _animParam2
                  }
                }\`
              }
            })
            export class MyDir {
              title = '';
              foo = true;
              _animValue = null;
              _animParam1 = null;
              _animParam2 = null;
            }
            @Component({
              selector: 'my-app',
              template: \`
                
              \`
            })
            export class MyAppComp {}
            @NgModule({declarations: [MyAppComp, MyDir]})
            export class MyModule {}
          `
        }
      };
      const template = `
          hostBindings: function MyDir_HostBindings(rf, ctx, elIndex) {
            …
            $r3$.ɵɵallocHostVars(9);
            …
            if (rf & 2) {
              $r3$.ɵɵhostProperty("title", ctx.title);
              $r3$.ɵɵupdateSyntheticHostBinding("@anim",
                $r3$.ɵɵpureFunction2(6, _c1, ctx._animValue,
                $r3$.ɵɵpureFunction2(3, _c0, ctx._animParam1, ctx._animParam2)));
              $r3$.ɵɵclassProp("foo", ctx.foo);
            }
          }
      `;
      const result = compile(files, angularFiles);
      expectEmit(result.source, template, 'Incorrect template');
    });
  });
});