Add unit tests for load-edit directive

Write unit tests for the directive to increase test coverage
Split file read into a separate service for easier testing.

Co-Authored-By: Matt Borland <matt.borland@hpe.com>
Co-Authored-By: Shaoquan Chen <sean.chen2@hp.com>
Co-Authored-By: Rajat Vig<rajatv@thoughtworks.com>

Change-Id: Ie886c374b19d24351766bb48023ddfb7426b7a06
Partial-Bug: #1506891
This commit is contained in:
cbeasley 2015-10-20 14:37:24 -07:00 committed by Rajat Vig
parent 71af780cf8
commit 0bd3863faf
11 changed files with 316 additions and 39 deletions

View File

@ -150,7 +150,7 @@ module.exports = function (config) {
statements: 91, // target 100
branches: 81, // target 100
functions: 90, // target 100
lines: 91 // target 100
lines: 92 // target 100
}
});
};

View File

@ -0,0 +1,62 @@
/*
* Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('horizon.framework.util.file')
.factory('horizon.framework.util.file.file-reader',
fileReaderService);
fileReaderService.$inject = ['$q'];
/**
* @ngdoc service
* @name horizon.framework.util.file.fileReaderService
* @description
* Service for reading file contents. Used for processing client-side
* files, such as loading a config file into launch instance.
*
* readTextFile - reads a text file and returns a promise of its contents.
*/
function fileReaderService($q) {
var service = {
readTextFile: readTextFile
};
return service;
////////////////
function readTextFile(file, fileReader) {
var reader = fileReader || new FileReader();
var deferred = $q.defer();
reader.onloadend = loadEnd;
reader.readAsArrayBuffer(file.slice(0, file.size));
return deferred.promise;
function loadEnd(e) {
var charArray = new Uint8Array(e.target.result);
var textContent = [].map.call(charArray, strFromCharCode).join('');
deferred.resolve(textContent);
function strFromCharCode(char) {
return String.fromCharCode(char);
}
}
}
}
})();

View File

@ -0,0 +1,54 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
describe('fileReader service', function() {
var $scope, fileReader;
beforeEach(module('horizon.framework.util.file'));
beforeEach(inject(function($injector) {
fileReader = $injector.get('horizon.framework.util.file.file-reader');
$scope = $injector.get('$rootScope');
}));
it('should return a promise that resolves to a string', function(done) {
var fileReaderStub = {};
var arrayBuffer = str2ab('file contents');
fileReaderStub.readAsArrayBuffer = function() {};
var filePromise = fileReader.readTextFile('file', fileReaderStub);
filePromise.then(function(contents) {
expect(contents).toEqual('file contents');
done();
});
fileReaderStub.onloadend({
target: {
result: arrayBuffer
}
});
$scope.$apply();
});
});
function str2ab(str) {
var buf = new ArrayBuffer(str.length); // 2 bytes for each char
var bufView = new Uint8Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
})();

View File

@ -0,0 +1,22 @@
/*
* Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('horizon.framework.util.file', []);
})();

View File

@ -4,6 +4,7 @@
angular
.module('horizon.framework.util', [
'horizon.framework.util.bind-scope',
'horizon.framework.util.file',
'horizon.framework.util.filters',
'horizon.framework.util.http',
'horizon.framework.util.i18n',

View File

@ -1,4 +1,6 @@
/*
* Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -14,9 +16,9 @@
(function () {
'use strict';
/*
/**
* @ngdoc directive
* @name horizon.dashboard.project.workflow.launch-instance:loadEdit
* @name horizon.framework.widgets:loadEdit
* @scope
* @element
* @description
@ -29,15 +31,16 @@
* See configuration.html for example usage.
*/
angular
.module('horizon.dashboard.project.workflow.launch-instance')
.module('horizon.framework.widgets.load-edit')
.directive('loadEdit', loadEdit);
loadEdit.$inject = [
'horizon.dashboard.project.workflow.launch-instance.basePath',
'$timeout'
'$timeout',
'horizon.framework.util.file.file-reader',
'horizon.framework.widgets.load-edit.basePath'
];
function loadEdit(basePath, $timeout) {
function loadEdit($timeout, fileReader, basePath) {
var directive = {
restrict: 'E',
scope: {
@ -46,7 +49,7 @@
key: '@'
},
link: link,
templateUrl: basePath + 'configuration/load-edit.html'
templateUrl: basePath + 'load-edit.html'
};
return directive;
@ -94,34 +97,25 @@
var file = event.originalEvent.target.files[0];
if (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
$scope.$applyAsync(function () {
var charArray = new Uint8Array(e.target.result);
$scope.textContent = [].map.call(charArray,
function (char) {
return String.fromCharCode(char);
}
).join('');
});
};
reader.readAsArrayBuffer(file.slice(0, file.size));
/* Once the DOM manipulation is done, update the scriptLength, so that
* user knows the length of the script loaded into the <textarea>.
*/
$timeout(function () {
onTextareaChange();
$scope.scriptModified = false;
}, 250, false);
// Focus the <textarea> element after injecting the code into it.
textarea.focus();
fileReader.readTextFile(file).then(updateTextArea);
}
}
function updateTextArea(fileContents) {
$scope.textContent = fileContents;
/* Once the DOM manipulation is done, update the scriptLength, so that
* user knows the length of the script loaded into the <textarea>.
*/
$timeout(function () {
onTextareaChange();
$scope.scriptModified = false;
}, 250, false);
// Focus the <textarea> element after injecting the code into it.
textarea.focus();
}
}
}
})();

View File

@ -0,0 +1,108 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
describe('load-edit directive', function () {
var $compile,
$scope,
key,
element,
$q,
readFileService;
beforeEach(module('templates'));
beforeEach(module('horizon.framework.widgets.load-edit'));
beforeEach(module(function($provide) {
readFileService = {};
$provide.provider('horizon.framework.util.file.file-reader',
function () {
this.$get = function () {
return readFileService;
};
});
}));
beforeEach(inject(function ($injector) {
$scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
$compile = $injector.get('$compile');
key = 'inputKey';
element = $compile(
'<load-edit config="{}" user-input="{}" key="' + key + '"></load-edit>'
)($scope);
$scope.$apply();
}));
describe('onTextAreaChange listener', function() {
var textarea;
beforeEach(function() {
textarea = element.find('textarea');
});
it('should set scriptModified to true when textarea has content', function () {
textarea.val('any value');
textarea.trigger('propertychange');
$scope.$apply();
expect(element.isolateScope().scriptModified).toBe(true);
});
it('should set scriptModified to false when textarea has no content', function () {
textarea.val('');
textarea.trigger('propertychange');
$scope.$apply();
expect(element.isolateScope().scriptModified).toBe(false);
});
it('should set userInput to the value of the textarea', function() {
textarea.val('user input');
textarea.trigger('input');
$scope.$apply();
expect(element.isolateScope().userInput[key]).toBe('user input');
});
});
describe('onFileLoadListener', function() {
it('should set the value of textContent to the file contents', function(done) {
var contentPromise = $q.defer();
readFileService.readTextFile = function() {
return contentPromise.promise;
};
var fileInput = element.find('input[type="file"]');
var e = jQuery.Event( "change", {originalEvent: {target: {files: [['hi']]}}});
fileInput.trigger(e);
contentPromise.promise.then(function() {
expect(element.isolateScope().textContent).toBe('the contents of a file');
done();
});
contentPromise.resolve('the contents of a file');
$scope.$apply();
});
it('should handle when no file is passed in', function() {
var fileInput = element.find('input[type="file"]');
var e = jQuery.Event( "change", {originalEvent: {target: {files: []}}});
fileInput.trigger(e);
expect(element.isolateScope().textContent).toBe('');
});
});
});
})();

View File

@ -0,0 +1,35 @@
/*
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
/**
* @ngdoc overview
* @name horizon.framework.widgets.load-edit
* @description
*
*/
angular
.module('horizon.framework.widgets.load-edit', [])
.config(config);
config.$inject = ['$provide', '$windowProvider'];
function config($provide, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'framework/widgets/load-edit/';
$provide.constant('horizon.framework.widgets.load-edit.basePath', path);
}
})();

View File

@ -14,7 +14,8 @@
'horizon.framework.widgets.action-list',
'horizon.framework.widgets.metadata',
'horizon.framework.widgets.toast',
'horizon.framework.widgets.magic-search'
'horizon.framework.widgets.magic-search',
'horizon.framework.widgets.load-edit'
])
.config(config);

View File

@ -192,10 +192,10 @@ module.exports = function (config) {
// Coverage threshold values.
thresholdReporter: {
statements: 93, // target 100
branches: 90, // target 100
functions: 92, // target 100
lines: 93 // target 100
statements: 95, // target 100
branches: 92, // target 100
functions: 94, // target 100
lines: 95 // target 100
}
});
};