text: /*global defineSuite*/
  defineSuite([
          'DataSources/PropertyBag',
          'Core/JulianDate',
          'DataSources/ConstantProperty',
          'DataSources/SampledProperty'
      ], function(
          PropertyBag,
          JulianDate,
          ConstantProperty,
          SampledProperty) {
      'use strict';
  
      var time = JulianDate.now();
  
      it('sets correct values when constructed with no arguments', function() {
          var property = new PropertyBag();
          expect(property.isConstant).toBe(true);
          expect(property.getValue(time)).toEqual({});
      });
  
      it('sets correct values when constructed with arguments', function() {
          var property = new PropertyBag({
              a : new ConstantProperty(1),
              b : new ConstantProperty(2)
          });
  
          expect(property.propertyNames).toContain('a');
          expect(property.a).toBeDefined();
          expect(property.a).toBeInstanceOf(ConstantProperty);
          expect(property.hasProperty('a')).toEqual(true);
  
          expect(property.propertyNames).toContain('b');
          expect(property.b).toBeDefined();
          expect(property.b).toBeInstanceOf(ConstantProperty);
          expect(property.hasProperty('b')).toEqual(true);
  
          expect(property.getValue(time)).toEqual({
              a : 1,
              b : 2
          });
      });
  
      it('works with result parameter', function() {
          var property = new PropertyBag({
              a : new ConstantProperty(1),
              b : new ConstantProperty(2)
          });
  
          var expectedResult = {
              a : -1
          };
          var result = property.getValue(time, expectedResult);
          expect(result).toEqual({
              a : 1,
              b : 2
          });
          expect(result).toBe(expectedResult);
      });
  
      it('leaves extra properties in result object in place', function() {
          var property = new PropertyBag({
              a : new ConstantProperty(1)
          });
  
          var expectedResult = {
              q : -1
          };
          var result = property.getValue(time, expectedResult);
          expect(result).toEqual({
              a : 1,
              q : -1
          });
          expect(result).toBe(expectedResult);
      });
  
      it('converts raw values to properties when constructed', function() {
          var property = new PropertyBag({
              a : 1,
              b : 2
          });
  
          expect(property.propertyNames).toContain('a');
          expect(property.a).toBeInstanceOf(ConstantProperty);
  
          expect(property.propertyNames).toContain('b');
          expect(property.b).toBeInstanceOf(ConstantProperty);
  
          expect(property.getValue(time)).toEqual({
              a : 1,
              b : 2
          });
      });
  
      function FakeProperty(v) {
          this.v = v;
      }
      FakeProperty.prototype.getValue = function() {
          return this.v;
      };
      function createFakeProperty(v) {
          return new FakeProperty(v);
      }
  
      it('uses the provided function to convert raw values to properties when constructed', function() {
          var property = new PropertyBag({
              a : 1,
              b : 2
          }, createFakeProperty);
  
          expect(property.propertyNames).toContain('a');
          expect(property.a).toBeDefined();
          expect(property.a).toBeInstanceOf(FakeProperty);
  
          expect(property.propertyNames).toContain('b');
          expect(property.b).toBeDefined();
          expect(property.b).toBeInstanceOf(FakeProperty);
  
          expect(property.getValue(time)).toEqual({
              a : 1,
              b : 2
          });
      });
  
      it('returns correct results from hasProperty', function() {
          var property = new PropertyBag();
          expect(property.hasProperty('a')).toEqual(false);
          property.addProperty('a');
          expect(property.hasProperty('a')).toEqual(true);
      });
  
      it('allows adding a property without a value', function() {
          var property = new PropertyBag();
          property.addProperty('a');
  
          expect(property.propertyNames).toEqual(['a']);
          expect(property.a).toBeUndefined();
          expect(property.hasProperty('a')).toEqual(true);
  
          expect(property.getValue(time)).toEqual({
              a : undefined
          });
      });
  
      it('allows adding a property with a value', function() {
          var property = new PropertyBag();
          property.addProperty('a', new ConstantProperty(1));
  
          expect(property.propertyNames).toEqual(['a']);
          expect(property.a).toBeInstanceOf(ConstantProperty);
  
          expect(property.getValue(time)).toEqual({
              a : 1
          });
      });
  
      it('uses the provided function to convert raw values to properties when added with a value', function() {
          var property = new PropertyBag();
          property.addProperty('a', 1, createFakeProperty);
  
          expect(property.propertyNames).toEqual(['a']);
          expect(property.a).toBeInstanceOf(FakeProperty);
  
          expect(property.getValue(time)).toEqual({
              a : 1
          });
      });
  
      it('uses the provided function to convert raw values to properties when added without a value', function() {
          var property = new PropertyBag();
          property.addProperty('a', undefined, createFakeProperty);
  
          expect(property.propertyNames).toEqual(['a']);
          expect(property.a).toBeUndefined();
  
          property.a = 1;
          expect(property.a).toBeInstanceOf(FakeProperty);
  
          expect(property.getValue(time)).toEqual({
              a : 1
          });
      });
  
      it('allows removing a property that was previously added', function() {
          var property = new PropertyBag();
  
          property.addProperty('a', new ConstantProperty(1));
          expect(property.hasProperty('a')).toEqual(true);
  
          property.removeProperty('a');
  
          expect(property.propertyNames).toEqual([]);
          expect(property.a).toBeUndefined();
          expect(property.hasProperty('a')).toEqual(false);
  
          expect(property.getValue(time)).toEqual({});
      });
  
      it('throws when removing a property that was not added', function() {
          var property = new PropertyBag();
          expect(function() {
              property.removeProperty('a');
          }).toThrowDeveloperError();
      });
  
      it('raises definitionChanged event when addProperty is called', function() {
          var property = new PropertyBag();
          var listener = jasmine.createSpy('listener');
          property.definitionChanged.addEventListener(listener);
          property.addProperty('a');
          expect(listener).toHaveBeenCalledWith(property);
      });
  
      it('raises definitionChanged event when properties are changed', function() {
          var property = new PropertyBag();
          property.addProperty('a');
  
          var listener = jasmine.createSpy('listener');
          property.definitionChanged.addEventListener(listener);
  
          var a = new ConstantProperty(1);
          property.a = a;
  
          expect(listener).toHaveBeenCalledWith(property, 'a', a, undefined);
      });
  
      it('requires propertyName in addProperty', function() {
          var property = new PropertyBag();
          expect(function() {
              property.addProperty();
          }).toThrowDeveloperError();
      });
  
      it('requires propertyName in removeProperty', function() {
          var property = new PropertyBag();
          expect(function() {
              property.removeProperty();
          }).toThrowDeveloperError();
      });
  
      it('has working equals function', function() {
          var left = new PropertyBag({
              a : new ConstantProperty(1)
          });
          var right = new PropertyBag({
              a : new ConstantProperty(1)
          });
  
          expect(left.equals(right)).toEqual(true);
  
          right.addProperty('c');
          expect(left.equals(right)).toEqual(false);
  
          right = new PropertyBag({
              a : new ConstantProperty(2)
          });
          expect(left.equals(right)).toEqual(false);
  
          right = new PropertyBag({
              b : new ConstantProperty(1)
          });
          expect(left.equals(right)).toEqual(false);
  
          right = new PropertyBag();
          expect(left.equals(right)).toEqual(false);
  
          left = new PropertyBag();
          right = new PropertyBag();
          expect(left.equals(right)).toEqual(true);
      });
  
      it('returns true from isConstant only if all members are constant', function() {
          var property = new PropertyBag();
  
          property.addProperty('a', new ConstantProperty(2));
          expect(property.isConstant).toBe(true);
  
          var sampledProperty = new SampledProperty(Number);
          sampledProperty.addSample(time, 1);
          property.addProperty('b', sampledProperty);
  
          expect(property.isConstant).toBe(false);
      });
  });
  