Skip to content
This repository has been archived by the owner on May 5, 2018. It is now read-only.

[CodeMirror] UI-Refresh, unit tests fix, and 3.02 update #412

Merged
merged 6 commits into from
Feb 11, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
node_js:
- "0.8"

before_script:
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install -g grunt@0.3.x testacular@0.2.x
- npm install -g grunt@0.3.x testacular@0.4.x

script: "grunt"
2 changes: 1 addition & 1 deletion grunt.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ module.exports = function (grunt) {
var done = this.async();
grunt.utils.spawn({
cmd: process.platform === 'win32' ? 'testacular.cmd' : 'testacular',
args: process.env.TRAVIS ? ['start', 'test/test-config.js', '--single-run', '--no-auto-watch', '--reporter=dots', '--browsers=Firefox'] : ['run']
args: process.env.TRAVIS ? ['start', 'test/test-config.js', '--single-run', '--no-auto-watch', '--reporters=dots', '--browsers=Firefox'] : ['run']
}, function (error, result, code) {
if (error) {
grunt.warn("Make sure the testacular server is online: run `grunt server`.\n" +
Expand Down
8 changes: 8 additions & 0 deletions modules/directives/codemirror/codemirror.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ angular.module('ui.directives').directive('uiCodemirror', ['ui.config', '$timeou
codeMirror.setValue(ngModel.$viewValue);
};

// Watch ui-refresh and refresh the directive
if (attrs.uiRefresh) {
scope.$watch(attrs.uiRefresh, function(newVal, oldVal){
// Skip the initial watch firing
if (newVal !== oldVal)
$timeout(codeMirror.refresh);
});
}
};

$timeout(deferCodeMirror);
Expand Down
250 changes: 136 additions & 114 deletions modules/directives/codemirror/test/codemirrorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,135 +2,157 @@
/**
* TODO Test all the CodeMirror events : cursorActivity viewportChange gutterClick focus blur scroll update.
* with <textarea ui-codemirror="{onChange: doChange ,onCursorActivity: doSomething}" ng-model="foo">
*
*
*/
describe('uiCodemirror', function () {
'use strict';
'use strict';

// declare these up here to be global to all tests
var $rootScope, $compile, $timeout, uiConfig = angular.module('ui.config');
var scope, $compile, $timeout, uiConfig = angular.module('ui.config');

beforeEach(module('ui.directives'));
beforeEach(function () {
uiConfig.value('ui.config', {codemirror: {bar: 'baz'}});
});

// inject in angular constructs. Injector knows about leading/trailing underscores and does the right thing
// otherwise, you would need to inject these into each test
beforeEach(inject(function (_$rootScope_, _$compile_, _$timeout_) {
$rootScope = _$rootScope_.$new();
scope = _$rootScope_.$new();
$compile = _$compile_;
$timeout = _$timeout_;
}));

afterEach(function () {
angular.module('ui.config').value('ui.config', {}); // cleanup
uiConfig.value('ui.config', {}); // cleanup
});

describe('compiling this directive', function () {
it('should throw an error if used against a non-textarea', function () {
function compile() {
$compile('<div ui-codemirror ng-model="foo"></div>')(scope);
}

expect(compile).toThrow();
});

it('should not throw an error when used against a textarea', function () {
function compile() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
}

expect(compile).not.toThrow();
});

it('should throw an error when no ngModel attribute defined', function () {
function compile() {
$compile('<textarea ui-codemirror></textarea>')(scope);
}

expect(compile).toThrow();
});

it('should watch the uiCodemirror attribute', function () {
spyOn(scope, '$watch');
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
$timeout.flush();
expect(scope.$watch).toHaveBeenCalled();
});

});

describe('while spying on the CodeMirror instance', function () {

var codemirror;

beforeEach(function () {
var fromTextArea = CodeMirror.fromTextArea;
spyOn(CodeMirror, 'fromTextArea').andCallFake(function () {
codemirror = fromTextArea.apply(this, arguments);
return codemirror;
});
});

describe('verify the directive options', function () {
it('should include the passed options', function () {
$compile('<textarea ui-codemirror="{oof: \'baar\'}" ng-model="foo"></textarea>')(scope);
$timeout.flush();
expect(CodeMirror.fromTextArea.mostRecentCall.args[1].oof).toEqual("baar");
});

it('should include the default options', function () {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
$timeout.flush();
expect(CodeMirror.fromTextArea.mostRecentCall.args[1].bar).toEqual('baz');
});
});

describe('when uiRefresh is added', function () {
it('should trigger the CodeMirror.refresh() method', function () {
$compile('<textarea ui-codemirror ng-model="foo" ui-refresh="bar"></textarea>')(scope);
$timeout.flush();
spyOn(codemirror, 'refresh');
scope.$apply('bar = true');
$timeout.flush();
expect(codemirror.refresh).toHaveBeenCalled();
});
});


describe('when the IDE changes', function () {
it('should update the model', function () {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
scope.$apply("foo = 'bar'");
$timeout.flush();
var value = 'baz';
codemirror.setValue(value);
expect(scope.foo).toBe(value);
});
});
});

describe('when the model changes', function () {
it('should update the IDE', function () {
var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
scope.foo = 'bar';
scope.$apply();
$timeout.flush();
expect($.trim(element.siblings().text())).toBe(scope.foo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I test locally this seems to be failing :(

});
});

describe('compiling this directive', function () {
it('should throw an error if used against a non-textarea', function () {
function compile() {
$compile('<div ui-codemirror ng-model="foo"></div>')($rootScope);
}

expect(compile).toThrow();
});

it('should not throw an error when used against a textarea', function () {
function compile() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
}

expect(compile).not.toThrow();
});

it('should throw an error when no ngModel attribute defined', function () {
function compile() {
$compile('<textarea ui-codemirror></textarea>')($rootScope);
}

expect(compile).toThrow();
});

it('should watch the uiCodemirror attribute', function () {
spyOn($rootScope, '$watch');
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$timeout.flush();
expect($rootScope.$watch).toHaveBeenCalled();
});

// Sorry I'm not enough familiar Jasmine to fix this...
/*
it('should include the passed options', function () {
spyOn(CodeMirror, 'fromTextArea');
$compile('<textarea ui-codemirror="{foo: \'bar\'}" ng-model="foo"></textarea>')($rootScope);
expect(CodeMirror.fromTextArea.mostRecentCall.args[1].foo).toEqual('bar');
});

it('should include the default options', function () {
spyOn(CodeMirror, 'fromTextArea');
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
expect(CodeMirror.fromTextArea.mostRecentCall.args[1].bar).toEqual('baz');
});
*/
});

describe('when the model changes', function () {
it('should update the IDE', function () {
var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$rootScope.foo = 'bar';
$rootScope.$apply();
$timeout.flush();
expect(element[0].nextSibling.CodeMirror.getValue()).toBe($rootScope.foo);
});
});

describe('when the IDE changes', function () {
it('should update the model', function () {
var codemirror,
fromTextArea = CodeMirror.fromTextArea;
spyOn(CodeMirror, 'fromTextArea').andCallFake(function () {
codemirror = fromTextArea.apply(this, arguments);
return codemirror;
});
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$rootScope.foo = 'bar';
$rootScope.$apply();
$timeout.flush();
var value = 'baz';
codemirror.setValue(value);
expect($rootScope.foo).toBe(value);
});
});

describe('when the model is undefined/null', function () {
it('should update the IDE with an empty string', function () {
var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$rootScope.$apply();
expect($rootScope.foo).toBe(undefined);
expect($.trim(element.siblings().text())).toBe('');
$rootScope.foo = null;
$rootScope.$apply();
expect($rootScope.foo).toBe(null);
expect($.trim(element.siblings().text())).toBe('');
});
});

describe('when the model is an object or an array', function () {
it('should throw an error', function () {
function compileWithObject() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$timeout.flush();
$rootScope.foo = {};
$rootScope.$apply();
}

function compileWithArray() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')($rootScope);
$timeout.flush();
$rootScope.foo = [];
$rootScope.$apply();
}

expect(compileWithObject).toThrow();
expect(compileWithArray).toThrow();
});
});

describe('when the model is undefined/null', function () {
it('should update the IDE with an empty string', function () {
var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
scope.$apply();
expect(scope.foo).toBe(undefined);
expect($.trim(element.siblings().text())).toBe('');
scope.foo = null;
scope.$apply();
expect(scope.foo).toBe(null);
expect($.trim(element.siblings().text())).toBe('');
});
});

describe('when the model is an object or an array', function () {
it('should throw an error', function () {
function compileWithObject() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
$timeout.flush();
scope.foo = {};
scope.$apply();
}

function compileWithArray() {
$compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
$timeout.flush();
scope.foo = [];
scope.$apply();
}

expect(compileWithObject).toThrow();
expect(compileWithArray).toThrow();
});
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"devDependencies": {
"grunt-recess": "~0.1.3",
"async": "0.1.x",
"testacular": "~0.4.0"
"testacular": "~0.4.x"
}
}
Loading