describe(`${name} shadow dom strategy`, () => {

        it('should support simple components',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<simple>' +
                                 '<div>A</div>' +
                                 '</simple>',
                   directives: [simple]
                 }),
                 simpleTemplate
               ])
                 .then((protoViews) => {
                   tb.createRootViews(protoViews);

                   expect(tb.rootEl).toHaveText('SIMPLE(A)');

                   async.done();
                 });
           }));

        it('should not show the light dom even if there is not content tag',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<empty>' +
                                 '<div>A</div>' +
                                 '</empty>',
                   directives: [empty]
                 }),
                 emptyTemplate
               ])
                 .then((protoViews) => {
                   tb.createRootViews(protoViews);

                   expect(tb.rootEl).toHaveText('');

                   async.done();
                 });
           }));

        it('should support dynamic components',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<dynamic>' +
                                 '<div>A</div>' +
                                 '</dynamic>',
                   directives: [dynamicComponent]
                 }),
                 simpleTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
                   tb.createComponentView(views[1].viewRef, 0, protoViews[2]);

                   expect(tb.rootEl).toHaveText('SIMPLE(A)');

                   async.done();
                 });
           }));

        it('should support multiple content tags',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<multiple-content-tags>' +
                                 '<div>B</div>' +
                                 '<div>C</div>' +
                                 '<div class="left">A</div>' +
                                 '</multiple-content-tags>',
                   directives: [multipleContentTagsComponent]
                 }),
                 multipleContentTagsTemplate
               ])
                 .then((protoViews) => {
                   tb.createRootViews(protoViews);

                   expect(tb.rootEl).toHaveText('(A, BC)');

                   async.done();
                 });
           }));

        it('should redistribute only direct children',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<multiple-content-tags>' +
                                 '<div>B<div class="left">A</div></div>' +
                                 '<div>C</div>' +
                                 '</multiple-content-tags>',
                   directives: [multipleContentTagsComponent]
                 }),
                 multipleContentTagsTemplate
               ])
                 .then((protoViews) => {
                   tb.createRootViews(protoViews);

                   expect(tb.rootEl).toHaveText('(, BAC)');

                   async.done();
                 });
           }));

        it("should redistribute direct child viewcontainers when the light dom changes",
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<multiple-content-tags>' +
                                 '<div><div template="manual" class="left">A</div></div>' +
                                 '<div>B</div>' +
                                 '</multiple-content-tags>',
                   directives: [multipleContentTagsComponent, manualViewportDirective]
                 }),
                 multipleContentTagsTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(protoViews);
                   var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
                   expect(tb.rootEl).toHaveText('(, B)');

                   var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);

                   expect(tb.rootEl).toHaveText('(, AB)');

                   tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);

                   expect(tb.rootEl).toHaveText('(, B)');

                   async.done();
                 });
           }));

        it("should redistribute when the light dom changes",
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<multiple-content-tags>' +
                                 '<div template="manual" class="left">A</div>' +
                                 '<div>B</div>' +
                                 '</multiple-content-tags>',
                   directives: [multipleContentTagsComponent, manualViewportDirective]
                 }),
                 multipleContentTagsTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(protoViews);
                   var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;

                   expect(tb.rootEl).toHaveText('(, B)');

                   var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);

                   expect(tb.rootEl).toHaveText('(A, B)');

                   tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);

                   expect(tb.rootEl).toHaveText('(, B)');

                   async.done();
                 });
           }));

        it("should support nested components",
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<outer-with-indirect-nested>' +
                                 '<div>A</div>' +
                                 '<div>B</div>' +
                                 '</outer-with-indirect-nested>',
                   directives: [outerWithIndirectNestedComponent]
                 }),
                 outerWithIndirectNestedTemplate,
                 simpleTemplate
               ])
                 .then((protoViews) => {
                   tb.createRootViews(protoViews);

                   expect(tb.rootEl).toHaveText('OUTER(SIMPLE(AB))');

                   async.done();
                 });
           }));

        it("should support nesting with content being direct child of a nested component",
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<outer>' +
                                 '<div template="manual" class="left">A</div>' +
                                 '<div>B</div>' +
                                 '<div>C</div>' +
                                 '</outer>',
                   directives: [outerComponent, manualViewportDirective]
                 }),
                 outerTemplate,
                 innerTemplate,
                 innerInnerTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(protoViews);
                   var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;

                   expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(,BC)))');

                   tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);

                   expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
                   async.done();
                 });
           }));

        it('should redistribute when the shadow dom changes',
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '<conditional-content>' +
                                 '<div class="left">A</div>' +
                                 '<div>B</div>' +
                                 '<div>C</div>' +
                                 '</conditional-content>',
                   directives: [conditionalContentComponent]
                 }),
                 conditionalContentTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(protoViews);
                   var childProtoView = protoViews[2].elementBinders[0].nestedProtoView;

                   expect(tb.rootEl).toHaveText('(, ABC)');

                   var childView = tb.createViewInContainer(views[2].viewRef, 0, 0, childProtoView);

                   expect(tb.rootEl).toHaveText('(A, BC)');

                   tb.destroyViewInContainer(views[2].viewRef, 0, 0, childView.viewRef);

                   expect(tb.rootEl).toHaveText('(, ABC)');

                   async.done();
                 });
           }));

        it("should support tabs with view caching",
           inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
             tb.compileAll([
                 mainDir,
                 new ViewDefinition({
                   componentId: 'main',
                   template: '(<tab><span>0</span></tab>' +
                                 '<tab><span>1</span></tab>' +
                                 '<tab><span>2</span></tab>)',
                   directives: [tabComponent]
                 }),
                 tabTemplate
               ])
                 .then((protoViews) => {
                   var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
                   var tabProtoView = protoViews[2];
                   var tabChildProtoView = tabProtoView.elementBinders[0].nestedProtoView;

                   var tab1View = tb.createComponentView(views[1].viewRef, 0, tabProtoView);
                   var tab2View = tb.createComponentView(views[1].viewRef, 1, tabProtoView);
                   var tab3View = tb.createComponentView(views[1].viewRef, 2, tabProtoView);

                   expect(tb.rootEl).toHaveText('()');

                   var tabChildView =
                       tb.createViewInContainer(tab1View.viewRef, 0, 0, tabChildProtoView);

                   expect(tb.rootEl).toHaveText('(TAB(0))');

                   tb.renderer.dehydrateView(tabChildView.viewRef);
                   tb.renderer.detachViewInContainer(tab1View.viewRef, 0, 0, tabChildView.viewRef);

                   tb.renderer.attachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
                   tb.renderer.hydrateView(tabChildView.viewRef);

                   expect(tb.rootEl).toHaveText('(TAB(1))');

                   tb.renderer.dehydrateView(tabChildView.viewRef);
                   tb.renderer.detachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);

                   tb.renderer.attachViewInContainer(tab3View.viewRef, 0, 0, tabChildView.viewRef);
                   tb.renderer.hydrateView(tabChildView.viewRef);

                   expect(tb.rootEl).toHaveText('(TAB(2))');

                   async.done();
                 });
           }));

        // Implement once ElementRef support changing a class
        // it("should redistribute when a class has been added or removed");
        // it('should not lose focus', () => {
        //  var temp = `<simple>aaa<input type="text" id="focused-input" ng-class="{'aClass' :
        //  showClass}"> bbb</simple>`;
        //
        //  compile(temp, (view, lc) => {
        //    var input = view.rootNodes[1];
        //    input.focus();
        //
        //    expect(document.activeElement.id).toEqual("focused-input");
        //
        //    // update class of input
        //
        //    expect(document.activeElement.id).toEqual("focused-input");
        //  });
        //});
      });
 describe('compiler', function() {
   var mockStepFactory;
   function createCompiler(processClosure, urlData = null) {
     if (isBlank(urlData)) {
       urlData = MapWrapper.create();
     }
     var tplLoader = new FakeTemplateLoader(urlData);
     mockStepFactory = new MockStepFactory([new MockStep(processClosure)]);
     return new Compiler(mockStepFactory, tplLoader);
   }
   it('should run the steps and build the ProtoView of the root element', inject([AsyncTestCompleter], (async) => {
     var compiler = createCompiler((parent, current, control) => {
       current.inheritedProtoView.bindVariable('b', 'a');
     });
     compiler.compile(new Template({
       componentId: 'someComponent',
       inline: '<div></div>'
     })).then((protoView) => {
       expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({'a': 'b'}));
       async.done();
     });
   }));
   it('should use the inline template and compile in sync', inject([AsyncTestCompleter], (async) => {
     var compiler = createCompiler(EMPTY_STEP);
     compiler.compile(new Template({
       componentId: 'someId',
       inline: 'inline component'
     })).then((protoView) => {
       expect(DOM.getInnerHTML(protoView.render.delegate.element)).toEqual('inline component');
       async.done();
     });
   }));
   it('should load url templates', inject([AsyncTestCompleter], (async) => {
     var urlData = MapWrapper.createFromStringMap({'someUrl': 'url component'});
     var compiler = createCompiler(EMPTY_STEP, urlData);
     compiler.compile(new Template({
       componentId: 'someId',
       absUrl: 'someUrl'
     })).then((protoView) => {
       expect(DOM.getInnerHTML(protoView.render.delegate.element)).toEqual('url component');
       async.done();
     });
   }));
   it('should report loading errors', inject([AsyncTestCompleter], (async) => {
     var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
     PromiseWrapper.catchError(compiler.compile(new Template({
       componentId: 'someId',
       absUrl: 'someUrl'
     })), (e) => {
       expect(e.message).toContain(`Failed to load the template "someId"`);
       async.done();
     });
   }));
   it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
     var subTasksCompleted = false;
     var completer = PromiseWrapper.completer();
     var compiler = createCompiler((parent, current, control) => {
       ListWrapper.push(mockStepFactory.subTaskPromises, completer.promise.then((_) => {
         subTasksCompleted = true;
       }));
     });
     var pvPromise = compiler.compile(new Template({
       componentId: 'someId',
       inline: 'some component'
     }));
     expect(pvPromise).toBePromise();
     expect(subTasksCompleted).toEqual(false);
     completer.resolve(null);
     pvPromise.then((protoView) => {
       expect(subTasksCompleted).toEqual(true);
       async.done();
     });
   }));
 });
示例#3
0
  describe('runner', () => {
    var injector: Injector;
    var runner;

    function createRunner(defaultBindings = null) {
      if (isBlank(defaultBindings)) {
        defaultBindings = [];
      }
      runner = new Runner([
        defaultBindings,
        bind(Sampler).toFactory(
            (_injector) => {
              injector = _injector;
              return new MockSampler();
            },
            [Injector]),
        bind(Metric).toFactory(() => new MockMetric(), []),
        bind(Validator).toFactory(() => new MockValidator(), []),
        bind(WebDriverAdapter).toFactory(() => new MockWebDriverAdapter(), [])
      ]);
      return runner;
    }

    it('should set SampleDescription.id', inject([AsyncTestCompleter], (async) => {
         createRunner()
             .sample({id: 'someId'})
             .then((_) => injector.get(SampleDescription))
             .then((desc) => {
               expect(desc.id).toBe('someId');
               async.done();
             });
       }));

    it('should merge SampleDescription.description', inject([AsyncTestCompleter], (async) => {
         createRunner([bind(Options.DEFAULT_DESCRIPTION).toValue({'a': 1})])
             .sample({id: 'someId', bindings: [bind(Options.SAMPLE_DESCRIPTION).toValue({'b': 2})]})
             .then((_) => injector.get(SampleDescription))
             .then((desc) => {
               expect(desc.description)
                   .toEqual(
                       {'forceGc': false, 'userAgent': 'someUserAgent', 'a': 1, 'b': 2, 'v': 11});
               async.done();
             });
       }));

    it('should fill SampleDescription.metrics from the Metric',
       inject([AsyncTestCompleter], (async) => {
         createRunner()
             .sample({id: 'someId'})
             .then((_) => injector.get(SampleDescription))
             .then((desc) => {

               expect(desc.metrics).toEqual({'m1': 'some metric'});
               async.done();
             });
       }));

    it('should bind Options.EXECUTE', inject([AsyncTestCompleter], (async) => {
         var execute = () => {};
         createRunner()
             .sample({id: 'someId', execute: execute})
             .then((_) => {
               expect(injector.get(Options.EXECUTE)).toEqual(execute);
               async.done();
             });
       }));

    it('should bind Options.PREPARE', inject([AsyncTestCompleter], (async) => {
         var prepare = () => {};
         createRunner()
             .sample({id: 'someId', prepare: prepare})
             .then((_) => {
               expect(injector.get(Options.PREPARE)).toEqual(prepare);
               async.done();
             });
       }));

    it('should bind Options.MICRO_METRICS', inject([AsyncTestCompleter], (async) => {
         createRunner()
             .sample({id: 'someId', microMetrics: {'a': 'b'}})
             .then((_) => {
               expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
               async.done();
             });
       }));

    it('should overwrite bindings per sample call', inject([AsyncTestCompleter], (async) => {
         createRunner([
           bind(Options.DEFAULT_DESCRIPTION)
               .toValue({'a': 1}),
         ])
             .sample({
               id: 'someId',
               bindings: [
                 bind(Options.DEFAULT_DESCRIPTION)
                     .toValue({'a': 2}),
               ]
             })
             .then((_) => injector.get(SampleDescription))
             .then((desc) => {

               expect(desc.description['a']).toBe(2);
               async.done();
             });

       }));

  });
  describe('StyleUrlResolver', () => {
    let styleUrlResolver;

    beforeEach(() => { styleUrlResolver = new StyleUrlResolver(new UrlResolver()); });

    it('should resolve "url()" urls', () => {
      var css = `
      .foo {
        background-image: url("double.jpg");
        background-image: url('simple.jpg');
        background-image: url(noquote.jpg);
      }`;
      var expectedCss = `
      .foo {
        background-image: url('http://ng.io/double.jpg');
        background-image: url('http://ng.io/simple.jpg');
        background-image: url('http://ng.io/noquote.jpg');
      }`;

      var resolvedCss = styleUrlResolver.resolveUrls(css, 'http://ng.io');
      expect(resolvedCss).toEqual(expectedCss);
    });

    it('should resolve "@import" urls', () => {
      var css = `
      @import '1.css';
      @import "2.css";
      `;
      var expectedCss = `
      @import 'http://ng.io/1.css';
      @import 'http://ng.io/2.css';
      `;

      var resolvedCss = styleUrlResolver.resolveUrls(css, 'http://ng.io');
      expect(resolvedCss).toEqual(expectedCss);
    });

    it('should resolve "@import url()" urls', () => {
      var css = `
      @import url('3.css');
      @import url("4.css");
      @import url(5.css);
      `;
      var expectedCss = `
      @import url('http://ng.io/3.css');
      @import url('http://ng.io/4.css');
      @import url('http://ng.io/5.css');
      `;

      var resolvedCss = styleUrlResolver.resolveUrls(css, 'http://ng.io');
      expect(resolvedCss).toEqual(expectedCss);
    });

    it('should support media query in "@import"', () => {
      var css = `
      @import 'print.css' print;
      @import url(print.css) print;
      `;
      var expectedCss = `
      @import 'http://ng.io/print.css' print;
      @import url('http://ng.io/print.css') print;
      `;

      var resolvedCss = styleUrlResolver.resolveUrls(css, 'http://ng.io');
      expect(resolvedCss).toEqual(expectedCss);
    });
  });
示例#5
0
  describe('CssSelector.parse', () => {
    it('should detect element names', () => {
      var cssSelector = CssSelector.parse('sometag')[0];
      expect(cssSelector.element).toEqual('sometag');
      expect(cssSelector.toString()).toEqual('sometag');
    });

    it('should detect class names', () => {
      var cssSelector = CssSelector.parse('.someClass')[0];
      expect(cssSelector.classNames).toEqual(['someclass']);

      expect(cssSelector.toString()).toEqual('.someclass');
    });

    it('should detect attr names', () => {
      var cssSelector = CssSelector.parse('[attrname]')[0];
      expect(cssSelector.attrs).toEqual(['attrname', '']);

      expect(cssSelector.toString()).toEqual('[attrname]');
    });

    it('should detect attr values', () => {
      var cssSelector = CssSelector.parse('[attrname=attrvalue]')[0];
      expect(cssSelector.attrs).toEqual(['attrname', 'attrvalue']);
      expect(cssSelector.toString()).toEqual('[attrname=attrvalue]');
    });

    it('should detect multiple parts', () => {
      var cssSelector = CssSelector.parse('sometag[attrname=attrvalue].someclass')[0];
      expect(cssSelector.element).toEqual('sometag');
      expect(cssSelector.attrs).toEqual(['attrname', 'attrvalue']);
      expect(cssSelector.classNames).toEqual(['someclass']);

      expect(cssSelector.toString()).toEqual('sometag.someclass[attrname=attrvalue]');
    });

    it('should detect multiple attributes', () => {
      var cssSelector = CssSelector.parse('input[type=text][control]')[0];
      expect(cssSelector.element).toEqual('input');
      expect(cssSelector.attrs).toEqual(['type', 'text', 'control', '']);

      expect(cssSelector.toString()).toEqual('input[type=text][control]');
    });

    it('should detect :not', () => {
      var cssSelector = CssSelector.parse('sometag:not([attrname=attrvalue].someclass)')[0];
      expect(cssSelector.element).toEqual('sometag');
      expect(cssSelector.attrs.length).toEqual(0);
      expect(cssSelector.classNames.length).toEqual(0);

      var notSelector = cssSelector.notSelectors[0];
      expect(notSelector.element).toEqual(null);
      expect(notSelector.attrs).toEqual(['attrname', 'attrvalue']);
      expect(notSelector.classNames).toEqual(['someclass']);

      expect(cssSelector.toString()).toEqual('sometag:not(.someclass[attrname=attrvalue])');
    });

    it('should detect :not without truthy', () => {
      var cssSelector = CssSelector.parse(':not([attrname=attrvalue].someclass)')[0];
      expect(cssSelector.element).toEqual("*");

      var notSelector = cssSelector.notSelectors[0];
      expect(notSelector.attrs).toEqual(['attrname', 'attrvalue']);
      expect(notSelector.classNames).toEqual(['someclass']);

      expect(cssSelector.toString()).toEqual('*:not(.someclass[attrname=attrvalue])');
    });

    it('should throw when nested :not', () => {
      expect(() => { CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0]; })
          .toThrowError('Nesting :not is not allowed in a selector');
    });

    it('should throw when multiple selectors in :not', () => {
      expect(() => { CssSelector.parse('sometag:not(a,b)'); })
          .toThrowError('Multiple selectors in :not are not supported');
    });

    it('should detect lists of selectors', () => {
      var cssSelectors = CssSelector.parse('.someclass,[attrname=attrvalue], sometag');
      expect(cssSelectors.length).toEqual(3);

      expect(cssSelectors[0].classNames).toEqual(['someclass']);
      expect(cssSelectors[1].attrs).toEqual(['attrname', 'attrvalue']);
      expect(cssSelectors[2].element).toEqual('sometag');
    });

    it('should detect lists of selectors with :not', () => {
      var cssSelectors =
          CssSelector.parse('input[type=text], :not(textarea), textbox:not(.special)');
      expect(cssSelectors.length).toEqual(3);

      expect(cssSelectors[0].element).toEqual('input');
      expect(cssSelectors[0].attrs).toEqual(['type', 'text']);

      expect(cssSelectors[1].element).toEqual('*');
      expect(cssSelectors[1].notSelectors[0].element).toEqual('textarea');

      expect(cssSelectors[2].element).toEqual('textbox');
      expect(cssSelectors[2].notSelectors[0].classNames).toEqual(['special']);
    });
  });
示例#6
0
  describe('exceptions', () => {
    it('should call the on error callback when it is defined',
       inject([AsyncTestCompleter], (async) => {
         macroTask(() => {
           _zone.overrideOnErrorHandler(logError);

           var exception = new BaseException('sync');

           _zone.run(() => { throw exception; });

           expect(_errors.length).toBe(1);
           expect(_errors[0]).toBe(exception);
           async.done();
         });
       }));

    it('should call onError for errors from microtasks', inject([AsyncTestCompleter], (async) => {
         _zone.overrideOnErrorHandler(logError);

         var exception = new BaseException('async');

         macroTask(() => { _zone.run(() => { microTask(() => { throw exception; }); }); });

         macroTask(() => {
           expect(_errors.length).toBe(1);
           expect(_errors[0]).toEqual(exception);
           async.done();
         }, 80);
       }));

    it('should call onError when onTurnDone throws and the zone is sync',
       inject([AsyncTestCompleter], (async) => {
         var exception = new BaseException('fromOnTurnDone');

         _zone.overrideOnErrorHandler(logError);
         _zone.overrideOnTurnDone(() => { throw exception; });

         macroTask(() => { _zone.run(() => {}); });

         macroTask(() => {
           expect(_errors.length).toBe(1);
           expect(_errors[0]).toEqual(exception);
           async.done();
         }, 80);
       }));

    it('should call onError when onTurnDone throws and the zone is async',
       inject([AsyncTestCompleter], (async) => {
         var asyncRan = false;

         var exception = new BaseException('fromOnTurnDone');

         _zone.overrideOnErrorHandler(logError);
         _zone.overrideOnTurnDone(() => { throw exception; });

         macroTask(() => { _zone.run(() => { microTask(() => { asyncRan = true; }); }); });

         macroTask(() => {
           expect(asyncRan).toBe(true);
           expect(_errors.length).toBe(1);
           expect(_errors[0]).toEqual(exception);
           async.done();
         }, 80);
       }));
  });
示例#7
0
 describe('injector', function() {
   it('should instantiate a class without dependencies', function() {
     var injector = new Injector([Engine]);
     var engine = injector.get(Engine);
     expect(engine).toBeAnInstanceOf(Engine);
   });
   it('should resolve dependencies based on type information', function() {
     var injector = new Injector([Engine, Car]);
     var car = injector.get(Car);
     expect(car).toBeAnInstanceOf(Car);
     expect(car.engine).toBeAnInstanceOf(Engine);
   });
   it('should resolve dependencies based on @Inject annotation', function() {
     var injector = new Injector([TurboEngine, Engine, CarWithInject]);
     var car = injector.get(CarWithInject);
     expect(car).toBeAnInstanceOf(CarWithInject);
     expect(car.engine).toBeAnInstanceOf(TurboEngine);
   });
   it('should throw when no type and not @Inject', function() {
     expect(() => new Injector([NoAnnotations])).toThrowError('Cannot resolve all parameters for NoAnnotations');
   });
   it('should cache instances', function() {
     var injector = new Injector([Engine]);
     var e1 = injector.get(Engine);
     var e2 = injector.get(Engine);
     expect(e1).toBe(e2);
   });
   it('should bind to a value', function() {
     var injector = new Injector([bind(Engine).toValue("fake engine")]);
     var engine = injector.get(Engine);
     expect(engine).toEqual("fake engine");
   });
   it('should bind to a factory', function() {
     function sportsCarFactory(e) {
       return new SportsCar(e);
     }
     Object.defineProperty(sportsCarFactory, "parameters", {get: function() {
         return [[Engine]];
       }});
     var injector = new Injector([Engine, bind(Car).toFactory(sportsCarFactory)]);
     var car = injector.get(Car);
     expect(car).toBeAnInstanceOf(SportsCar);
     expect(car.engine).toBeAnInstanceOf(Engine);
   });
   it('should bind to an alias', function() {
     var injector = new Injector([Engine, bind(SportsCar).toClass(SportsCar), bind(Car).toAlias(SportsCar)]);
     var car = injector.get(Car);
     var sportsCar = injector.get(SportsCar);
     expect(car).toBeAnInstanceOf(SportsCar);
     expect(car).toBe(sportsCar);
   });
   it('should throw when the aliased binding does not exist', function() {
     var injector = new Injector([bind('car').toAlias(SportsCar)]);
     expect(() => injector.get('car')).toThrowError('No provider for SportsCar! (car -> SportsCar)');
   });
   it('should support overriding factory dependencies', function() {
     var injector = new Injector([Engine, bind(Car).toFactory((e) => new SportsCar(e), [Engine])]);
     var car = injector.get(Car);
     expect(car).toBeAnInstanceOf(SportsCar);
     expect(car.engine).toBeAnInstanceOf(Engine);
   });
   it('should support optional dependencies', function() {
     var injector = new Injector([CarWithOptionalEngine]);
     var car = injector.get(CarWithOptionalEngine);
     expect(car.engine).toEqual(null);
   });
   it("should flatten passed-in bindings", function() {
     var injector = new Injector([[[Engine, Car]]]);
     var car = injector.get(Car);
     expect(car).toBeAnInstanceOf(Car);
   });
   it("should use the last binding " + "when there are mutliple bindings for same token", function() {
     var injector = new Injector([bind(Engine).toClass(Engine), bind(Engine).toClass(TurboEngine)]);
     expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
   });
   it('should use non-type tokens', function() {
     var injector = new Injector([bind('token').toValue('value')]);
     expect(injector.get('token')).toEqual('value');
   });
   it('should throw when given invalid bindings', function() {
     expect(() => new Injector(["blah"])).toThrowError('Invalid binding blah');
     expect(() => new Injector([bind("blah")])).toThrowError('Invalid binding blah');
   });
   it('should provide itself', function() {
     var parent = new Injector([]);
     var child = parent.createChild([]);
     expect(child.get(Injector)).toBe(child);
   });
   it('should throw when no provider defined', function() {
     var injector = new Injector([]);
     expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!');
   });
   it('should show the full path when no provider', function() {
     var injector = new Injector([CarWithDashboard, Engine, Dashboard]);
     expect(() => injector.get(CarWithDashboard)).toThrowError('No provider for DashboardSoftware! (CarWithDashboard -> Dashboard -> DashboardSoftware)');
   });
   it('should throw when trying to instantiate a cyclic dependency', function() {
     var injector = new Injector([Car, bind(Engine).toClass(CyclicEngine)]);
     expect(() => injector.get(Car)).toThrowError('Cannot instantiate cyclic dependency! (Car -> Engine -> Car)');
     expect(() => injector.asyncGet(Car)).toThrowError('Cannot instantiate cyclic dependency! (Car -> Engine -> Car)');
   });
   it('should show the full path when error happens in a constructor', function() {
     var injector = new Injector([Car, bind(Engine).toClass(BrokenEngine)]);
     try {
       injector.get(Car);
       throw "Must throw";
     } catch (e) {
       expect(e.message).toContain("Error during instantiation of Engine! (Car -> Engine)");
     }
   });
   it('should instantiate an object after a failed attempt', function() {
     var isBroken = true;
     var injector = new Injector([Car, bind(Engine).toFactory(() => isBroken ? new BrokenEngine() : new Engine())]);
     expect(() => injector.get(Car)).toThrowError(new RegExp("Error"));
     isBroken = false;
     expect(injector.get(Car)).toBeAnInstanceOf(Car);
   });
   it('should support null values', () => {
     var injector = new Injector([bind('null').toValue(null)]);
     expect(injector.get('null')).toBe(null);
   });
   describe("default bindings", function() {
     it("should be used when no matching binding found", function() {
       var injector = new Injector([], {defaultBindings: true});
       var car = injector.get(Car);
       expect(car).toBeAnInstanceOf(Car);
     });
     it("should use the matching binding when it is available", function() {
       var injector = new Injector([bind(Car).toClass(SportsCar)], {defaultBindings: true});
       var car = injector.get(Car);
       expect(car).toBeAnInstanceOf(SportsCar);
     });
   });
   describe("child", function() {
     it('should load instances from parent injector', function() {
       var parent = new Injector([Engine]);
       var child = parent.createChild([]);
       var engineFromParent = parent.get(Engine);
       var engineFromChild = child.get(Engine);
       expect(engineFromChild).toBe(engineFromParent);
     });
     it("should not use the child bindings when resolving the dependencies of a parent binding", function() {
       var parent = new Injector([Car, Engine]);
       var child = parent.createChild([bind(Engine).toClass(TurboEngine)]);
       var carFromChild = child.get(Car);
       expect(carFromChild.engine).toBeAnInstanceOf(Engine);
     });
     it('should create new instance in a child injector', function() {
       var parent = new Injector([Engine]);
       var child = parent.createChild([bind(Engine).toClass(TurboEngine)]);
       var engineFromParent = parent.get(Engine);
       var engineFromChild = child.get(Engine);
       expect(engineFromParent).not.toBe(engineFromChild);
       expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
     });
     it("should create child injectors without default bindings", function() {
       var parent = new Injector([], {defaultBindings: true});
       var child = parent.createChild([]);
       var childCar = child.get(Car);
       var parentCar = parent.get(Car);
       expect(childCar).toBe(parentCar);
     });
   });
   describe("lazy", function() {
     it("should create dependencies lazily", function() {
       var injector = new Injector([Engine, CarWithLazyEngine]);
       var car = injector.get(CarWithLazyEngine);
       expect(car.engineFactory()).toBeAnInstanceOf(Engine);
     });
     it("should cache instance created lazily", function() {
       var injector = new Injector([Engine, CarWithLazyEngine]);
       var car = injector.get(CarWithLazyEngine);
       var e1 = car.engineFactory();
       var e2 = car.engineFactory();
       expect(e1).toBe(e2);
     });
   });
 });
示例#8
0
      describe("optional components", () => {
        describe("contains", () => {
          var group;

          beforeEach(() => {
            group = new ControlGroup(
                {
                  "required": new Control("requiredValue"),
                  "optional": new Control("optionalValue")
                },
                {"optional": false});
          });

          // rename contains into has
          it("should return false when the component is not included",
             () => { expect(group.contains("optional")).toEqual(false); })

              it("should return false when there is no component with the given name",
                 () => { expect(group.contains("something else")).toEqual(false); });

          it("should return true when the component is included", () => {
            expect(group.contains("required")).toEqual(true);

            group.include("optional");

            expect(group.contains("optional")).toEqual(true);
          });
        });

        it("should not include an inactive component into the group value", () => {
          var group = new ControlGroup(
              {"required": new Control("requiredValue"), "optional": new Control("optionalValue")},
              {"optional": false});

          expect(group.value).toEqual({"required": "requiredValue"});

          group.include("optional");

          expect(group.value).toEqual({"required": "requiredValue", "optional": "optionalValue"});
        });

        it("should not run Validators on an inactive component", () => {
          var group = new ControlGroup(
              {
                "required": new Control("requiredValue", Validators.required),
                "optional": new Control("", Validators.required)
              },
              {"optional": false});

          expect(group.valid).toEqual(true);

          group.include("optional");

          expect(group.valid).toEqual(false);
        });

        describe("valueChanges", () => {
          var g, c1, c2;

          beforeEach(() => {
            c1 = new Control("old1");
            c2 = new Control("old2");
            g = new ControlGroup({"one": c1, "two": c2}, {"two": true});
          });

          it("should fire an event after the value has been updated",
             inject([AsyncTestCompleter], (async) => {
               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(g.value).toEqual({'one': 'new1', 'two': 'old2'});
                 expect(value).toEqual({'one': 'new1', 'two': 'old2'});
                 async.done();
               });
               c1.updateValue("new1");
             }));

          it("should fire an event after the control's observable fired an event",
             inject([AsyncTestCompleter], (async) => {
               var controlCallbackIsCalled = false;

               ObservableWrapper.subscribe(c1.valueChanges,
                                           (value) => { controlCallbackIsCalled = true; });

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(controlCallbackIsCalled).toBe(true);
                 async.done();
               });

               c1.updateValue("new1");
             }));

          it("should fire an event when a control is excluded",
             inject([AsyncTestCompleter], (async) => {
               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(value).toEqual({'one': 'old1'});
                 async.done();
               });

               g.exclude("two");
             }));

          it("should fire an event when a control is included",
             inject([AsyncTestCompleter], (async) => {
               g.exclude("two");

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(value).toEqual({'one': 'old1', 'two': 'old2'});
                 async.done();
               });

               g.include("two");
             }));

          it("should fire an event every time a control is updated",
             inject([AsyncTestCompleter], (async) => {
               var loggedValues = [];

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 ListWrapper.push(loggedValues, value);

                 if (loggedValues.length == 2) {
                   expect(loggedValues)
                       .toEqual([{"one": "new1", "two": "old2"}, {"one": "new1", "two": "new2"}])
                           async.done();
                 }
               });

               c1.updateValue("new1");
               c2.updateValue("new2");
             }));

          xit("should not fire an event when an excluded control is updated",
              inject([AsyncTestCompleter], (async) => {
                                               // hard to test without hacking zones
                                           }));
        });
      });
示例#9
0
        describe("valueChanges", () => {
          var g, c1, c2;

          beforeEach(() => {
            c1 = new Control("old1");
            c2 = new Control("old2");
            g = new ControlGroup({"one": c1, "two": c2}, {"two": true});
          });

          it("should fire an event after the value has been updated",
             inject([AsyncTestCompleter], (async) => {
               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(g.value).toEqual({'one': 'new1', 'two': 'old2'});
                 expect(value).toEqual({'one': 'new1', 'two': 'old2'});
                 async.done();
               });
               c1.updateValue("new1");
             }));

          it("should fire an event after the control's observable fired an event",
             inject([AsyncTestCompleter], (async) => {
               var controlCallbackIsCalled = false;

               ObservableWrapper.subscribe(c1.valueChanges,
                                           (value) => { controlCallbackIsCalled = true; });

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(controlCallbackIsCalled).toBe(true);
                 async.done();
               });

               c1.updateValue("new1");
             }));

          it("should fire an event when a control is excluded",
             inject([AsyncTestCompleter], (async) => {
               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(value).toEqual({'one': 'old1'});
                 async.done();
               });

               g.exclude("two");
             }));

          it("should fire an event when a control is included",
             inject([AsyncTestCompleter], (async) => {
               g.exclude("two");

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 expect(value).toEqual({'one': 'old1', 'two': 'old2'});
                 async.done();
               });

               g.include("two");
             }));

          it("should fire an event every time a control is updated",
             inject([AsyncTestCompleter], (async) => {
               var loggedValues = [];

               ObservableWrapper.subscribe(g.valueChanges, (value) => {
                 ListWrapper.push(loggedValues, value);

                 if (loggedValues.length == 2) {
                   expect(loggedValues)
                       .toEqual([{"one": "new1", "two": "old2"}, {"one": "new1", "two": "new2"}])
                           async.done();
                 }
               });

               c1.updateValue("new1");
               c2.updateValue("new2");
             }));

          xit("should not fire an event when an excluded control is updated",
              inject([AsyncTestCompleter], (async) => {
                                               // hard to test without hacking zones
                                           }));
        });
  describe('URLSearchParams', () => {
    it('should conform to spec', () => {
      var paramsString = "q=URLUtils.searchParams&topic=api";
      var searchParams = new URLSearchParams(paramsString);

      // Tests borrowed from example at
      // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
      // Compliant with spec described at https://url.spec.whatwg.org/#urlsearchparams
      expect(searchParams.has("topic")).toBe(true);
      expect(searchParams.has("foo")).toBe(false);
      expect(searchParams.get("topic")).toEqual("api");
      expect(searchParams.getAll("topic")).toEqual(["api"]);
      expect(searchParams.get("foo")).toBe(null);
      searchParams.append("topic", "webdev");
      expect(searchParams.getAll("topic")).toEqual(["api", "webdev"]);
      expect(searchParams.toString()).toEqual("q=URLUtils.searchParams&topic=api&topic=webdev");
      searchParams.delete("topic");
      expect(searchParams.toString()).toEqual("q=URLUtils.searchParams");

      // Test default constructor
      expect(new URLSearchParams().toString()).toBe("");
    });


    it('should support map-like merging operation via setAll()', () => {
      var mapA = new URLSearchParams('a=1&a=2&a=3&c=8');
      var mapB = new URLSearchParams('a=4&a=5&a=6&b=7');
      mapA.setAll(mapB);
      expect(mapA.has('a')).toBe(true);
      expect(mapA.has('b')).toBe(true);
      expect(mapA.has('c')).toBe(true);
      expect(mapA.getAll('a')).toEqual(['4']);
      expect(mapA.getAll('b')).toEqual(['7']);
      expect(mapA.getAll('c')).toEqual(['8']);
      expect(mapA.toString()).toEqual('a=4&c=8&b=7');
    });


    it('should support multimap-like merging operation via appendAll()', () => {
      var mapA = new URLSearchParams('a=1&a=2&a=3&c=8');
      var mapB = new URLSearchParams('a=4&a=5&a=6&b=7');
      mapA.appendAll(mapB);
      expect(mapA.has('a')).toBe(true);
      expect(mapA.has('b')).toBe(true);
      expect(mapA.has('c')).toBe(true);
      expect(mapA.getAll('a')).toEqual(['1', '2', '3', '4', '5', '6']);
      expect(mapA.getAll('b')).toEqual(['7']);
      expect(mapA.getAll('c')).toEqual(['8']);
      expect(mapA.toString()).toEqual('a=1&a=2&a=3&a=4&a=5&a=6&c=8&b=7');
    });


    it('should support multimap-like merging operation via replaceAll()', () => {
      var mapA = new URLSearchParams('a=1&a=2&a=3&c=8');
      var mapB = new URLSearchParams('a=4&a=5&a=6&b=7');
      mapA.replaceAll(mapB);
      expect(mapA.has('a')).toBe(true);
      expect(mapA.has('b')).toBe(true);
      expect(mapA.has('c')).toBe(true);
      expect(mapA.getAll('a')).toEqual(['4', '5', '6']);
      expect(mapA.getAll('b')).toEqual(['7']);
      expect(mapA.getAll('c')).toEqual(['8']);
      expect(mapA.toString()).toEqual('a=4&a=5&a=6&c=8&b=7');
    });
  });