diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..bdefdd5 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,74 @@ +{ + "excludeFiles": [ + "node_modules/**", + "bower_components/**" + ], + + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "maximumLineLength": { + "value": 200, + "allowComments": true, + "allowRegex": true + }, + "validateIndentation": 4, + "validateQuoteMarks": "'", + + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": null, + + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", "+=", + + "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", + "|", "^", "&&", "||", "===", "==", ">=", + "<=", "<", ">", "!=", "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireLineFeedAtFileEnd": true, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + + "validateJSDoc": { + "checkParamNames": true, + "requireParamTypes": true + }, + + "disallowMultipleLineBreaks": true, + + "disallowCommaBeforeLineBreak": null, + "disallowDanglingUnderscores": null, + "disallowEmptyBlocks": null, + "disallowTrailingComma": null, + "requireCommaBeforeLineBreak": null, + "requireDotNotation": null, + "requireMultipleVarDecl": null, + "requireParenthesesAroundIIFE": true +} diff --git a/gulp.config.js b/gulp.config.js new file mode 100644 index 0000000..2026fd5 --- /dev/null +++ b/gulp.config.js @@ -0,0 +1,29 @@ + +module.exports = function () { + var rootDir = __dirname; + + return { + rootDir: rootDir, + karma: { + default: { + configFile: rootDir + '/karma.config.js' + }, + coverage: { + coverageReporter: { + dir: rootDir + '/coverage', + reporters: [ + { type: 'html', subdir: 'coverage' }, + { type: 'text-summary' } + ] + }, + preprocessors: { + 'src/*.js': ['coverage'] + }, + reporters: ['mocha', 'coverage'] + }, + tdd: { + singleRun: false + } + } + }; +}; diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..16272cf --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,71 @@ +'use strict'; + +// Gulp configuration: +var config = require('./gulp.config')(); + +// Imports: +var gulp = require('gulp'); +var util = require('gulp-util'); +var karma = require('karma').server; +var _ = require('lodash'); + +// Tasks: +gulp.task('tdd', tddTask); +gulp.task('karma', karmaTask); +gulp.task('coverage', coverageTask); + +/** + * Test driven development task. + */ +function coverageTask(done) { + log('Starting a continuous "watch and test" cycle'); + + startKarma('coverage', done); +} + +/** + * Test driven development task. + */ +function tddTask(done) { + log('Starting a continuous "watch and test" cycle'); + + startKarma('tdd', done); +} + +/** + * Runs karma with default configuration. + */ +function karmaTask(done) { + startKarma('x', done); +} + +/** + * Runs karma with given configuration type + * + * @param {string} configType + * @param callback + */ +function startKarma(configType, callback) { + var options = _.merge( + config.karma.default, + config.karma[configType] || {} + ); + + karma.start(options, callback); +} + +/** + * Log a message or series of messages using chalk's blue color. + * Can pass in a string, object or array. + */ +function log(msg) { + if (typeof(msg) === 'object') { + for (var item in msg) { + if (msg.hasOwnProperty(item)) { + util.log($.util.colors.blue(msg[item])); + } + } + } else { + util.log(util.colors.blue(msg)); + } +} diff --git a/karma.config.js b/karma.config.js new file mode 100644 index 0000000..9137d47 --- /dev/null +++ b/karma.config.js @@ -0,0 +1,51 @@ +module.exports = function(config) { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: './', + + // frameworks to use + // some available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine-ajax', 'jasmine'], + + // list of files / patterns to load in the browser + files: [ + 'src/devbridge-autocomplete.js', + 'tests/spec/*.js' + ], + + // list of files to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: {}, + + // test results reporter to use + // possible values: 'dots', 'progress', 'coverage' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || + // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + // browsers: ['Chrome', 'ChromeCanary', 'FirefoxAurora', 'Safari', 'PhantomJS'], + browsers: ['PhantomJS'], + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }); +}; diff --git a/package.json b/package.json index c3980e9..24b1243 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,34 @@ { - "name": "devbridge-vanilla-autocomplete", - "version": "1.0.0", - "description": "Flexible JavaScript library for implementing Autocomplete features.", - "main": "dist/devbridge-vanilla-autocomplete.js", - "scripts": { - "test": "./node_modules/.bin/karma start karma-conf.js" - }, - "keywords": [ - "devbridge", - "autocomplete" - ], - "author": "Tomas Kirda", - "license": "MIT", - "repository": { - "type": "git", - "url": "git://github.com/devbridge/Vanilla-Autocomplete.git" - }, - "devDependencies": { - "grunt": "^0.4.5", - "grunt-contrib-uglify": "^0.8.0", - "karma": "^0.12.31", - "karma-coverage": "~0.1.0", - "karma-jasmine": "^0.3.3", - "karma-jasmine-ajax": "^0.1.12", - "karma-phantomjs-launcher": "^0.1.4" - } -} \ No newline at end of file + "name": "devbridge-vanilla-autocomplete", + "version": "1.0.0", + "description": "Flexible JavaScript library for implementing Autocomplete features.", + "main": "dist/devbridge-vanilla-autocomplete.js", + "scripts": { + "test": "./node_modules/.bin/karma start karma-conf.js" + }, + "keywords": [ + "devbridge", + "autocomplete" + ], + "author": "Tomas Kirda", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/devbridge/Vanilla-Autocomplete.git" + }, + "devDependencies": { + "grunt": "^0.4.5", + "grunt-contrib-uglify": "^0.8.0", + "gulp": "^3.8.11", + "gulp-uglify": "^1.1.0", + "karma": "^0.12.31", + "karma-coverage": "~0.1.0", + "karma-jasmine": "^0.3.3", + "karma-jasmine-ajax": "^0.1.12", + "karma-mocha": "^0.1.10", + "karma-mocha-reporter": "^1.0.2", + "karma-phantomjs-launcher": "^0.1.4", + "lodash": "^3.6.0", + "mocha": "^2.2.1" + } +} diff --git a/tests/spec/autocomplete-spec.js b/tests/spec/autocomplete-spec.js index a7247fe..41a5977 100644 --- a/tests/spec/autocomplete-spec.js +++ b/tests/spec/autocomplete-spec.js @@ -202,9 +202,13 @@ describe("Vanilla Autocomplete", function () { }); describe("By default", function () { - var instance, input, selectedSuggestion; + var instance; + var input; + var selectedSuggestion; beforeEach(function () { + jasmine.Ajax.install(); + selectedSuggestion = null; input = document.createElement('input'); @@ -225,6 +229,7 @@ describe("Vanilla Autocomplete", function () { } }; + instance = new VanillaAutocomplete(input, options); }); @@ -233,6 +238,47 @@ describe("Vanilla Autocomplete", function () { input.parentNode.removeChild(input); }); + it ("#isBadQuery() should always return false when preventBadQueries is set to false", function () { + instance.setOptions({ + preventBadQueries: false, + lookup: null, + serviceUrl: '/test' + }); + + var query = 'BadValue'; + + // Do it twice: + instance.changeValue(query); + + query = query + 'X'; + instance.changeValue(query); + + expect(instance.isBadQuery(query)).toEqual(false); + }); + + it ("#isBadQuery() should always true when preventBadQueries is set to true", function () { + instance.setOptions({ + preventBadQueries: true, + lookup: null, + serviceUrl: '/test' + }); + + var query = 'BadValue'; + + // Do it twice: + instance.changeValue(query); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: '{ "suggestions": [] }' + }); + + query = query + 'X'; + instance.changeValue(query); + + expect(instance.isBadQuery(query)).toEqual(true); + }); + it ("should set autocomplete attribute to 'off'", function () { expect(input.getAttribute('autocomplete')).toEqual('off'); }); @@ -773,7 +819,7 @@ describe("Vanilla Autocomplete", function () { document.body.appendChild(input); var options = { - lookup: ['AA1', 'AA2', 'BB1', 'BB2'], + lookup: ['AA1', 'AA2', 'BB1', 'BB2'] }; instance = new VanillaAutocomplete(input, options);