How do i test my custom angular schema form field

745 Views Asked by At

I've just started developing with Angular schema form and I'm struggling to write any tests for my custom field directive.

I've tried compiling the schema form html tag which runs through my directives config testing it's display conditions against the data in the schema. However it never seems to run my controller and I can't get a reference to the directives HTML elements. Can someone give me some guidance on how to get a reference to the directive? Below is what I have so far:

angular.module('schemaForm').config(['schemaFormProvider',
    'schemaFormDecoratorsProvider', 'sfPathProvider',
    function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
        var date = function (name, schema, options) {
            if (schema.type === 'string' && schema.format == 'date') {
                var f = schemaFormProvider.stdFormObj(name, schema, options);
                f.key = options.path;
                f.type = 'date';
                options.lookup[sfPathProvider.stringify(options.path)] = f;
                return f;
            }
        };
        schemaFormProvider.defaults.string.unshift(date);
        schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'date',
            'app/modules/json_schema_form/schema_form_date_picker/schema_form_date_picker.html');
    }]);

  var dateControllerFunction =  function($scope) {
      $scope.isCalendarOpen = false;

      $scope.showCalendar = function () {
        $scope.isCalendarOpen = true;
      };

      $scope.calendarSave = function (date) {
        var leaf_model = $scope.ngModel[$scope.ngModel.length - 1];
        var formattedDate = $scope.filter('date')(date, 'yyyy-MM-dd');
        leaf_model.$setViewValue(formattedDate);

        $scope.isCalendarOpen = false;
      };
  };

  angular.module('schemaForm').directive('schemaFormDatePickerDirective', ['$filter', function($filter) {
    return {
      require: ['ngModel'],
      restrict: 'A',
      scope: false,
      controller : ['$scope', dateControllerFunction],
      link: function(scope, iElement, iAttrs, ngModelCtrl) {
          scope.ngModel = ngModelCtrl;
          scope.filter = $filter
      }
    };
  }]);
<div ng-class="{'has-error': hasError()}">
  <div ng-model="$$value$$" schema-form-date-picker-directive>
    <md-input-container>
        <!-- showTitle function is implemented by ASF -->
        <label ng-show="showTitle()">{{form.title}}</label>
        <input name="dateTimePicker" ng-model="$$value$$" ng-focus="showCalendar()" ng-disabled="isCalendarOpen">
    </md-input-container>
    <time-date-picker ng-model="catalogue.effectiveFrom" ng-if="isCalendarOpen" on-save="calendarSave($value)" display-mode="date"></time-date-picker>
  </div>
  <!-- hasError() defined by ASF -->
  <span class="help-block" sf-message="form.description"></span>
</div>

And the spec:

'use strict'

describe('SchemaFormDatePicker', function() {
  var $compile = undefined;
  var $rootScope = undefined;
  var $scope = undefined
  var scope = undefined
  var $httpBackend = undefined;
  var elem = undefined;
  var html = '<form sf-schema="schema" sf-form="form" sf-model="schemaModel"></form>';
  var $templateCache = undefined;
  var directive = undefined;

  beforeEach(function(){
    module('app');
  });

  beforeEach(inject(function(_$compile_, _$rootScope_, _$templateCache_, _$httpBackend_) {
    $compile = _$compile_
    $rootScope = _$rootScope_
    $httpBackend = _$httpBackend_
    $templateCache = _$templateCache_
  }));

  beforeEach(function(){
    //Absorb call for locale
    $httpBackend.expectGET('assets/locale/en_gb.json').respond(200, {});
    $templateCache.put('app/modules/json_schema_form/schema_form_date_picker/schema_form_date_picker.html', '');
    $scope = $rootScope.$new()
    $scope.schema = {
       type: 'object',
       properties: {
         party: {
           title: 'party',
           type: 'string',
           format: 'date'
     }}};
     $scope.form = [{key: 'party'}];
     $scope.schemaModel = {};
   });

  describe("showCalendar", function () {
    beforeEach(function(){
      elem = $compile(html)($scope);
      $scope.$digest();
      $httpBackend.flush();
      scope = elem.isolateScope();
    });
    it('should set isCalendarOpen to true', function(){
      var result = elem.find('time-date-picker');
      console.log("RESULT: "+result);

    ));
  });
});
});

1

There are 1 best solutions below

0
On

If you look at the below example taken from the project itself you can see that when it uses $compile it uses angular.element() first when setting tmpl.

Also, the supplied test module name is 'app' while the code sample has the module name 'schemaForm'. The examples in the 1.0.0 version of Angular Schema Form repo all use sinon and chai, I'm not sure what changes you would need to make if you do not use those.

Note: runSync(scope, tmpl); is a new addition for 1.0.0 given it is now run through async functions to process $ref includes.

/* eslint-disable quotes, no-var */
/* disabling quotes makes it easier to copy tests into the example app */
chai.should();

var runSync = function(scope, tmpl) {
  var directiveScope = tmpl.isolateScope();
  sinon.stub(directiveScope, 'resolveReferences', function(schema, form) {
    directiveScope.render(schema, form);
  });
  scope.$apply();
};

describe('sf-array.directive.js', function() {
  var exampleSchema;
  var tmpl;
  beforeEach(module('schemaForm'));
  beforeEach(
    module(function($sceProvider) {
      $sceProvider.enabled(false);

      exampleSchema = {
        "type": "object",
        "properties": {
          "names": {
            "type": "array",
            "description": "foobar",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "title": "Name",
                  "type": "string",
                  "default": 6,
                },
              },
            },
          },
        },
      };
    })
  );

  it('should not throw needless errors on validate [ノಠ益ಠ]ノ彡┻━┻', function(done) {
    tmpl = angular.element(
      '<form name="testform" sf-schema="schema" sf-form="form" sf-model="model" json="{{model | json}}"></form>'
    );

    inject(function($compile, $rootScope) {
      var scope = $rootScope.$new();
      scope.model = {};

      scope.schema = exampleSchema;

      scope.form = [ "*" ];

      $compile(tmpl)(scope);
      runSync(scope, tmpl);

      tmpl.find('div.help-block').text().should.equal('foobar');

      var add = tmpl.find('button').eq(1);
      add.click();

      $rootScope.$apply();

      setTimeout(function() {
        var errors = tmpl.find('.help-block');
        errors.text().should.equal('foobar');
        done();
      }, 0);
    });
  });
});