├── .gitignore ├── tests ├── .editorconfig ├── data │ ├── 1 │ │ ├── actual.js │ │ ├── expected-ast.js │ │ └── expected-regex.js │ ├── 2 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 3 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 4 │ │ ├── actual.js │ │ ├── expected-ast.js │ │ └── expected-regex.js │ ├── 5 │ │ ├── actual.js │ │ ├── expected-ast.js │ │ └── expected-regex.js │ ├── 6 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 7 │ │ ├── actual.js │ │ ├── expected-ast.js │ │ └── expected-regex.js │ ├── 8 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 9 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 10 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 11 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ ├── 12 │ │ ├── actual.js │ │ ├── expected-regex.js │ │ └── expected-ast.js │ └── 13 │ │ ├── actual.js │ │ └── expected-ast.js ├── main.js └── src │ ├── ast.js │ └── regex.js ├── .travis.yml ├── src ├── api.js ├── ast │ ├── checks │ │ ├── is-test.js │ │ ├── is-module.js │ │ ├── is-start.js │ │ ├── is-stop.js │ │ ├── is-async-test.js │ │ ├── is-reporter-callback-expression.js │ │ ├── is-anonymous.js │ │ ├── is-module-function-params-value.js │ │ ├── is-test-params.js │ │ ├── is-init.js │ │ ├── is-assert-push.js │ │ ├── is-qunit-test.js │ │ ├── is-qunit-start.js │ │ ├── is-qunit-stop.js │ │ ├── is-qunit-async-test.js │ │ ├── is-qunit-module.js │ │ ├── is-reporter.js │ │ ├── is-define.js │ │ ├── is-jsdump.js │ │ ├── is-assertion.js │ │ ├── is-qunit-reporter.js │ │ └── is-module-params.js │ ├── config │ │ ├── default-config.js │ │ └── generator.js │ ├── index.js │ ├── applicant.js │ ├── rules │ │ ├── init-function.js │ │ ├── assert-push-function.js │ │ ├── reporter-function.js │ │ ├── test-function-assert.js │ │ ├── start-function.js │ │ ├── jsdump-function.js │ │ ├── assertion-function.js │ │ ├── test-function.js │ │ ├── module-function.js │ │ ├── reporter-function-callback.js │ │ ├── module-function-params.js │ │ ├── module-function-params-value.js │ │ ├── anonymous-function.js │ │ ├── define-function.js │ │ └── async-test-function.js │ ├── option-names.js │ ├── utils.js │ └── constants.js ├── regex │ ├── helpers │ │ ├── indent.js │ │ └── queue.js │ ├── index.js │ ├── main.js │ └── modifiers │ │ ├── globals.js │ │ ├── tests.js │ │ ├── assertions.js │ │ ├── definitions.js │ │ └── async.js └── cli-api.js ├── .editorconfig ├── examples ├── default.config.json ├── sample.config.json └── rules.md ├── LICENSE ├── package.json ├── bin └── qunit-migrate └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | -------------------------------------------------------------------------------- /tests/data/7/actual.js: -------------------------------------------------------------------------------- 1 | ( function ( $ ) { 2 | 3 | })( jQuery ); 4 | -------------------------------------------------------------------------------- /tests/data/7/expected-ast.js: -------------------------------------------------------------------------------- 1 | (function(QUnit, $) { 2 | 3 | })(QUnit, jQuery); 4 | -------------------------------------------------------------------------------- /tests/data/7/expected-regex.js: -------------------------------------------------------------------------------- 1 | ( function( QUnit, $ ) { 2 | 3 | } )( QUnit, jQuery ); 4 | -------------------------------------------------------------------------------- /tests/data/5/actual.js: -------------------------------------------------------------------------------- 1 | define('myModule', [ 2 | 'jquery' 3 | ], function ( $ ) { 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /tests/data/5/expected-ast.js: -------------------------------------------------------------------------------- 1 | define('myModule', ["qunit", 'jquery'], function(QUnit, $) { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /tests/main.js: -------------------------------------------------------------------------------- 1 | var regex = require('./src/regex'); 2 | var ast = require('./src/ast'); 3 | 4 | regex(); 5 | ast(); 6 | -------------------------------------------------------------------------------- /tests/data/5/expected-regex.js: -------------------------------------------------------------------------------- 1 | define('myModule', [ 'qunit', 2 | 'jquery' 3 | ], function( QUnit, $ ) { 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /src/api.js: -------------------------------------------------------------------------------- 1 | var ast = require('./ast'); 2 | var regex = require('./regex'); 3 | 4 | module.exports = { 5 | ast: ast, 6 | regex: regex 7 | }; 8 | -------------------------------------------------------------------------------- /tests/data/6/actual.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery' 3 | ], function ( $ ) { 4 | 5 | }); 6 | 7 | define("module", function ($) { 8 | 9 | }); 10 | 11 | define(function ($) { 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /tests/data/6/expected-regex.js: -------------------------------------------------------------------------------- 1 | define( [ 'qunit', 2 | 'jquery' 3 | ], function( QUnit, $ ) { 4 | 5 | }); 6 | 7 | define("module", function ($) { 8 | 9 | }); 10 | 11 | define(function ($) { 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /tests/data/6/expected-ast.js: -------------------------------------------------------------------------------- 1 | define(["qunit", 'jquery'], function(QUnit, $) { 2 | 3 | }); 4 | 5 | define("module", ["qunit"], function(QUnit, $) { 6 | 7 | }); 8 | 9 | define(["qunit"], function(QUnit, $) { 10 | 11 | }); 12 | -------------------------------------------------------------------------------- /tests/data/3/actual.js: -------------------------------------------------------------------------------- 1 | // Async tests 2 | asyncTest("An async test", function () { 3 | start(); 4 | }); 5 | 6 | asyncTest("A test", function () { 7 | stop(); 8 | stop(); 9 | start(); 10 | start(); 11 | }); 12 | 13 | asyncTest("A test", function () { 14 | stop(); 15 | start(); 16 | }); 17 | -------------------------------------------------------------------------------- /src/ast/checks/is-test.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | return node.type === "CallExpression" && 6 | node.callee && 7 | node.callee.type === "Identifier" && 8 | node.callee.name === constants.test; 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/checks/is-module.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | return node.type === "CallExpression" && 6 | node.callee && 7 | node.callee.type === "Identifier" && 8 | node.callee.name === constants.module; 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/checks/is-start.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | return node.type === "CallExpression" && 6 | node.callee && 7 | node.callee.type === "Identifier" && 8 | node.callee.name === constants.start; 9 | }; 10 | -------------------------------------------------------------------------------- /src/ast/checks/is-stop.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | return node.type === "CallExpression" && 6 | node.callee && 7 | node.callee.type === "Identifier" && 8 | node.callee.name === constants.stop; 9 | }; 10 | -------------------------------------------------------------------------------- /src/ast/checks/is-async-test.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | return node.type === "CallExpression" && 6 | node.callee && 7 | node.callee.type === "Identifier" && 8 | node.callee.name === constants.asyncTest; 9 | } 10 | -------------------------------------------------------------------------------- /src/regex/helpers/indent.js: -------------------------------------------------------------------------------- 1 | var detectIndent = require('detect-indent'); 2 | 3 | // This function will return indent for next line 4 | module.exports = function (line) { 5 | var indent = detectIndent(line); 6 | var indentString = ''; 7 | var amount = indent.amount + 1; 8 | 9 | while(amount--) { 10 | indentString += indent.indent || '\t'; 11 | } 12 | return indentString; 13 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [package.json] 15 | indent_size = 2 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /tests/data/3/expected-regex.js: -------------------------------------------------------------------------------- 1 | // Async tests 2 | QUnit.test("An async test", function( assert ) { 3 | var done = assert.async(); 4 | done(); 5 | }); 6 | 7 | QUnit.test("A test", function( assert ) { 8 | var done = assert.async(); 9 | var done1 = assert.async(); 10 | done(); 11 | done1(); 12 | }); 13 | 14 | QUnit.test("A test", function( assert ) { 15 | var done = assert.async(); 16 | done(); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/data/3/expected-ast.js: -------------------------------------------------------------------------------- 1 | // Async tests 2 | QUnit.test("An async test", function(assert) { 3 | var ready = assert.async(); 4 | ready(); 5 | }); 6 | 7 | QUnit.test("A test", function(assert) { 8 | var ready = assert.async(); 9 | var ready1 = assert.async(); 10 | ready(); 11 | ready1(); 12 | }); 13 | 14 | QUnit.test("A test", function(assert) { 15 | var ready = assert.async(); 16 | ready(); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/data/4/actual.js: -------------------------------------------------------------------------------- 1 | begin(); 2 | begin(); 3 | done(); 4 | done(); 5 | log(); 6 | log(); 7 | testStart(); 8 | testStart(); 9 | testDone(); 10 | testDone(); 11 | moduleStart(); 12 | moduleStart(); 13 | moduleDone(); 14 | moduleDone(); 15 | module(); 16 | module(); 17 | start(); 18 | start(); 19 | // These won't be changed 20 | QUnit.begin(); 21 | QUnit.done(); 22 | QUnit.log(); 23 | QUnit.testStart(); 24 | QUnit.testDone(); 25 | QUnit.moduleStart(); 26 | QUnit.moduleDone(); 27 | -------------------------------------------------------------------------------- /src/ast/checks/is-reporter-callback-expression.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isQUnitReporter = require('./is-qunit-reporter'); 3 | 4 | module.exports = function (context) { 5 | var node = context.node; 6 | var parent = context.parent; 7 | 8 | return node.type === 'AssignmentExpression' && 9 | node.right && 10 | node.right.type === 'FunctionExpression' && 11 | node.left && 12 | isQUnitReporter({ node: node.left, parent: parent }); 13 | } 14 | -------------------------------------------------------------------------------- /src/regex/index.js: -------------------------------------------------------------------------------- 1 | var main = require('./main'); 2 | var extend = require('extend'); 3 | var defaultOptions = { 4 | definitions: false, 5 | quotes: '"' 6 | }; 7 | 8 | module.exports = function (data, options) { 9 | options = options || {}; 10 | options.parserConfig = options.parserConfig || {}; 11 | var regexOptions = options.parserConfig.regex || {}; 12 | 13 | var finalOptions = extend(options, regexOptions); 14 | var migrated = main(data.toString(), finalOptions); 15 | return migrated; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/ast/config/default-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | anonymousFunction: true, 3 | assertionFunction: true, 4 | assertPushFunction: true, 5 | asyncTestFunction: true, 6 | defineFunction: true, 7 | initFunction: true, 8 | jsDumpFunction: true, 9 | moduleFunction: true, 10 | moduleFunctionParams: true, 11 | moduleFunctionParamsValue: true, 12 | reporterFunction: true, 13 | reporterFunctionCallback: true, 14 | startFunction: true, 15 | testFunction: true, 16 | testFunctionAssert: true 17 | }; 18 | -------------------------------------------------------------------------------- /src/ast/checks/is-anonymous.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | var parent = context.parent; 6 | return node && 7 | node.type === 'ExpressionStatement' && 8 | node.expression && 9 | node.expression.type === 'CallExpression' && 10 | node.expression.callee && 11 | node.expression.callee.type === 'FunctionExpression' && 12 | parent && 13 | parent.parent && 14 | parent.parent.node.type === 'Program'; 15 | } 16 | -------------------------------------------------------------------------------- /src/ast/checks/is-module-function-params-value.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isModuleParams = require('./is-module-params'); 3 | var utils = require('../utils'); 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var parent = context.parent; 8 | 9 | return node.type === 'FunctionExpression' && 10 | !utils.checkIfNodeParamsContain(node, constants.assert) && 11 | context.key === 'value' && 12 | parent && 13 | isModuleParams({ node: parent.node.key, parent: parent }); 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /src/ast/checks/is-test-params.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isQUnitTest = require('./is-qunit-test'); 3 | var utils = require('../utils'); 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var parent = context.parent; 8 | 9 | return node.type === 'FunctionExpression' && 10 | !utils.checkIfNodeParamsContain(node, constants.assert) && 11 | parent && 12 | parent.parent && 13 | parent.parent.node.type === 'CallExpression' && 14 | isQUnitTest({ node: parent.parent.node }); 15 | }; 16 | -------------------------------------------------------------------------------- /src/ast/index.js: -------------------------------------------------------------------------------- 1 | var recast = require('recast'); 2 | var traverse = require('traverse'); 3 | var applicant = require('./applicant'); 4 | var builder = recast.types.builders; 5 | 6 | module.exports = function (code, options) { 7 | options = options || {}; 8 | options.parserConfig = options.parserConfig || {}; 9 | var ast = recast.parse(code); 10 | var Applicant = new applicant(options.parserConfig.ast); 11 | 12 | traverse(ast).forEach( function (node) { 13 | if (node) { 14 | Applicant.apply(this); 15 | } 16 | }); 17 | return recast.print(ast).code; 18 | } 19 | -------------------------------------------------------------------------------- /tests/data/4/expected-ast.js: -------------------------------------------------------------------------------- 1 | QUnit.begin(); 2 | QUnit.begin(); 3 | QUnit.done(); 4 | QUnit.done(); 5 | QUnit.log(); 6 | QUnit.log(); 7 | QUnit.testStart(); 8 | QUnit.testStart(); 9 | QUnit.testDone(); 10 | QUnit.testDone(); 11 | QUnit.moduleStart(); 12 | QUnit.moduleStart(); 13 | QUnit.moduleDone(); 14 | QUnit.moduleDone(); 15 | QUnit.module(); 16 | QUnit.module(); 17 | QUnit.start(); 18 | QUnit.start(); 19 | // These won't be changed 20 | QUnit.begin(); 21 | QUnit.done(); 22 | QUnit.log(); 23 | QUnit.testStart(); 24 | QUnit.testDone(); 25 | QUnit.moduleStart(); 26 | QUnit.moduleDone(); 27 | -------------------------------------------------------------------------------- /tests/data/4/expected-regex.js: -------------------------------------------------------------------------------- 1 | QUnit.begin(); 2 | QUnit.begin(); 3 | QUnit.done(); 4 | QUnit.done(); 5 | QUnit.log(); 6 | QUnit.log(); 7 | QUnit.testStart(); 8 | QUnit.testStart(); 9 | QUnit.testDone(); 10 | QUnit.testDone(); 11 | QUnit.moduleStart(); 12 | QUnit.moduleStart(); 13 | QUnit.moduleDone(); 14 | QUnit.moduleDone(); 15 | QUnit.module(); 16 | QUnit.module(); 17 | QUnit.start(); 18 | QUnit.start(); 19 | // These won't be changed 20 | QUnit.begin(); 21 | QUnit.done(); 22 | QUnit.log(); 23 | QUnit.testStart(); 24 | QUnit.testDone(); 25 | QUnit.moduleStart(); 26 | QUnit.moduleDone(); 27 | -------------------------------------------------------------------------------- /src/ast/checks/is-init.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | var parent = context.parent; 6 | var callee = node.callee; 7 | return (node.type === 'CallExpression' && 8 | callee.type === "MemberExpression" && 9 | callee.object && 10 | callee.object.type === "Identifier" && 11 | callee.object.name === constants.qunit && 12 | callee.property && 13 | callee.property.type === "Identifier" && 14 | callee.property.name === constants.init); 15 | } 16 | -------------------------------------------------------------------------------- /tests/data/1/actual.js: -------------------------------------------------------------------------------- 1 | ok(1, 1); 2 | ok(1, 1); 3 | equal(1, 1); 4 | notEqual(1, 1); 5 | propEqual(1, 1); 6 | notPropEqual(1, 2); 7 | notDeepEqual(1, 2); 8 | throws(new Error('This is supposed to throw an error')); 9 | strictEqual(1, 1); 10 | notStrictEqual(1, 2); 11 | expect(7); 12 | assert.ok(1, 1); 13 | assert.equal(1, 1); 14 | assert.notEqual(1, 1); 15 | assert.propEqual(1, 1); 16 | assert.notPropEqual(1, 2); 17 | assert.notDeepEqual(1, 2); 18 | assert.throws(new Error('This is supposed to throw an error')); 19 | assert.strictEqual(1, 1); 20 | assert.notStrictEqual(1, 2); 21 | assert.expect(7); 22 | -------------------------------------------------------------------------------- /src/ast/checks/is-assert-push.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | var parent = context.parent; 6 | 7 | return node.type === 'MemberExpression' && 8 | node.object && 9 | node.object.type === 'Identifier' && 10 | node.object.name === constants.qunit && 11 | node.property && 12 | node.property.type === 'Identifier' && 13 | node.property.name === constants.assertPush && 14 | parent && 15 | parent.node && 16 | parent.node.type === 'CallExpression'; 17 | }; 18 | -------------------------------------------------------------------------------- /src/regex/main.js: -------------------------------------------------------------------------------- 1 | var assertionsModifier = require('./modifiers/assertions'); 2 | var definitionsModifier = require('./modifiers/definitions'); 3 | var globalsModifier = require('./modifiers/globals'); 4 | var testsModifier = require('./modifiers/tests'); 5 | var asyncModifier = require('./modifiers/async'); 6 | 7 | module.exports = function (data, options) { 8 | data = assertionsModifier(data); 9 | data = globalsModifier(data); 10 | data = testsModifier(data); 11 | data = asyncModifier(data); 12 | 13 | if (options.definitions) { 14 | data = definitionsModifier(data, options); 15 | } 16 | 17 | return data; 18 | } 19 | -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-test.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isTest = require('./is-test'); 3 | 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var callee = node.callee; 8 | return isTest({node: node}) || 9 | (node.type === 'CallExpression' && 10 | callee.type === "MemberExpression" && 11 | callee.object && 12 | callee.object.type === "Identifier" && 13 | callee.object.name === constants.qunit && 14 | callee.property && 15 | callee.property.type === "Identifier" && 16 | callee.property.name === constants.test); 17 | } 18 | -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-start.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isStart = require('./is-start'); 3 | 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var callee = node.callee; 8 | return isStart({node: node}) || 9 | (node.type === 'CallExpression' && 10 | callee.type === "MemberExpression" && 11 | callee.object && 12 | callee.object.type === "Identifier" && 13 | callee.object.name === constants.qunit && 14 | callee.property && 15 | callee.property.type === "Identifier" && 16 | callee.property.name === constants.start); 17 | } 18 | -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-stop.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isStop = require('./is-stop'); 3 | 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var callee = node.callee; 8 | return isStop({node: node}) || 9 | (node.type === 'CallExpression' && 10 | callee.type === "MemberExpression" && 11 | callee.object && 12 | callee.object.type === "Identifier" && 13 | callee.object.name === constants.qunit && 14 | callee.property && 15 | callee.property.type === "Identifier" && 16 | callee.property.name === constants.stop); 17 | }; 18 | -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-async-test.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isAsyncTest = require('./is-async-test'); 3 | 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var callee = node.callee; 8 | return isAsyncTest({node: node}) || 9 | (node.type === 'CallExpression' && 10 | callee.type === "MemberExpression" && 11 | callee.object && 12 | callee.object.type === "Identifier" && 13 | callee.object.name === constants.qunit && 14 | callee.property && 15 | callee.property.type === "Identifier" && 16 | callee.property.name === constants.asyncTest); 17 | } 18 | -------------------------------------------------------------------------------- /tests/data/1/expected-ast.js: -------------------------------------------------------------------------------- 1 | assert.ok(1, 1); 2 | assert.ok(1, 1); 3 | assert.equal(1, 1); 4 | assert.notEqual(1, 1); 5 | assert.propEqual(1, 1); 6 | assert.notPropEqual(1, 2); 7 | assert.notDeepEqual(1, 2); 8 | assert.throws(new Error('This is supposed to throw an error')); 9 | assert.strictEqual(1, 1); 10 | assert.notStrictEqual(1, 2); 11 | assert.expect(7); 12 | assert.ok(1, 1); 13 | assert.equal(1, 1); 14 | assert.notEqual(1, 1); 15 | assert.propEqual(1, 1); 16 | assert.notPropEqual(1, 2); 17 | assert.notDeepEqual(1, 2); 18 | assert.throws(new Error('This is supposed to throw an error')); 19 | assert.strictEqual(1, 1); 20 | assert.notStrictEqual(1, 2); 21 | assert.expect(7); 22 | -------------------------------------------------------------------------------- /tests/data/1/expected-regex.js: -------------------------------------------------------------------------------- 1 | assert.ok(1, 1); 2 | assert.ok(1, 1); 3 | assert.equal(1, 1); 4 | assert.notEqual(1, 1); 5 | assert.propEqual(1, 1); 6 | assert.notPropEqual(1, 2); 7 | assert.notDeepEqual(1, 2); 8 | assert.throws(new Error('This is supposed to throw an error')); 9 | assert.strictEqual(1, 1); 10 | assert.notStrictEqual(1, 2); 11 | assert.expect(7); 12 | assert.ok(1, 1); 13 | assert.equal(1, 1); 14 | assert.notEqual(1, 1); 15 | assert.propEqual(1, 1); 16 | assert.notPropEqual(1, 2); 17 | assert.notDeepEqual(1, 2); 18 | assert.throws(new Error('This is supposed to throw an error')); 19 | assert.strictEqual(1, 1); 20 | assert.notStrictEqual(1, 2); 21 | assert.expect(7); 22 | -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-module.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isModule = require('./is-module'); 3 | 4 | 5 | module.exports = function (context) { 6 | var node = context.node; 7 | var parent = context.parent; 8 | var callee = node.callee; 9 | return isModule({node: node}) || 10 | (node.type === 'CallExpression' && 11 | callee.type === "MemberExpression" && 12 | callee.object && 13 | callee.object.type === "Identifier" && 14 | callee.object.name === constants.qunit && 15 | callee.property && 16 | callee.property.type === "Identifier" && 17 | callee.property.name === constants.module); 18 | } 19 | -------------------------------------------------------------------------------- /src/ast/checks/is-reporter.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | var reporters = [ 4 | constants.logReporter, 5 | constants.beginReporter, 6 | constants.doneReporter, 7 | constants.logReporter, 8 | constants.moduleDoneReporter, 9 | constants.moduleStartReporter, 10 | constants.testDoneReporter, 11 | constants.testStartReporter 12 | ]; 13 | 14 | module.exports = function (context) { 15 | var node = context.node; 16 | var parent = context.parent; 17 | 18 | return node.type === 'Identifier' && 19 | reporters.indexOf(node.name) > -1 && 20 | parent && 21 | parent.node && 22 | parent.node.type !== 'MemberExpression'; 23 | } 24 | -------------------------------------------------------------------------------- /src/ast/applicant.js: -------------------------------------------------------------------------------- 1 | var defaultConfig = require('./config/default-config'); 2 | var Generator = require('./config/generator'); 3 | var extend = require('extend'); 4 | 5 | module.exports = Applicant; 6 | 7 | function Applicant(config) { 8 | config = config || {}; 9 | config = extend(defaultConfig, config); 10 | this._generator = new Generator(config); 11 | this._rules = this._generator.getRules(); 12 | } 13 | 14 | 15 | Applicant.prototype.apply = function (context) { 16 | Object.keys(this._rules).forEach(function (rule) { 17 | var _ruleInstance = this._rules[rule]; 18 | if (_ruleInstance.check(context)) { 19 | node = _ruleInstance.update(context); 20 | } 21 | }, this); 22 | }; 23 | -------------------------------------------------------------------------------- /src/ast/checks/is-define.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | var parent = context.parent; 6 | return node && 7 | node.type === 'ExpressionStatement' && 8 | node.expression && 9 | node.expression.type === 'CallExpression' && 10 | node.expression.callee && 11 | node.expression.callee.type === 'Identifier' && 12 | node.expression.callee.name === constants.defineExpression && 13 | node.expression.arguments && 14 | node.expression.arguments.length > 0 && 15 | parent && 16 | parent.parent && 17 | parent.parent.node.type === 'Program'; 18 | } 19 | -------------------------------------------------------------------------------- /tests/data/10/actual.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | module( "Globalize.locale" ); 13 | 14 | test( "should allow String locale", function() { 15 | Globalize.locale( "en" ); 16 | ok( Globalize.cldr instanceof Cldr ); 17 | equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | test( "should allow Cldr instance to be passed as locale", function() { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | ok( Globalize.cldr instanceof Cldr ); 23 | equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/11/actual.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | module( "Globalize.locale" ); 13 | 14 | test( "should allow String locale", function() { 15 | Globalize.locale( "en" ); 16 | ok( Globalize.cldr instanceof Cldr ); 17 | equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | test( "should allow Cldr instance to be passed as locale", function() { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | ok( Globalize.cldr instanceof Cldr ); 23 | equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/12/actual.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | module( "Globalize.locale" ); 13 | 14 | test( "should allow String locale", function() { 15 | Globalize.locale( "en" ); 16 | ok( Globalize.cldr instanceof Cldr ); 17 | equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | test( "should allow Cldr instance to be passed as locale", function() { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | ok( Globalize.cldr instanceof Cldr ); 23 | equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /src/ast/rules/init-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isInit = require('../checks/is-init'); 7 | 8 | module.exports = InitFunction; 9 | 10 | function InitFunction() { 11 | this._optionName = optionNames.InitFunction; 12 | }; 13 | 14 | 15 | InitFunction.prototype = { 16 | check: function (context) { 17 | return isInit(context); 18 | }, 19 | 20 | update: function (context) { 21 | var _self = this; 22 | context.parent.remove(); 23 | }, 24 | 25 | getOptionName: function () { 26 | return this._optionName; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/ast/option-names.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'AnonymousFunction': 'anonymousFunction', 3 | 'AssertionFunction': 'assertionFunction', 4 | 'AssertPushFunction': 'assertPushFunction', 5 | 'AsyncTestFunction': 'asyncTestFunction', 6 | 'DefineFunction': 'defineFunction', 7 | 'InitFunction': 'initFunction', 8 | 'JsDumpFunction': 'jsDumpFunction', 9 | 'ModuleFunction': 'moduleFunction', 10 | 'ModuleFunctionParams': 'moduleFunctionParams', 11 | 'ModuleFunctionParamsValue': 'moduleFunctionParamsValue', 12 | 'ReporterFunction': 'reporterFunction', 13 | 'ReporterFunctionCallback': 'reporterFunctionCallback', 14 | 'StartFunction': 'startFunction', 15 | 'TestFunction': 'testFunction', 16 | 'TestFunctionAssert': 'testFunctionAssert' 17 | }; 18 | -------------------------------------------------------------------------------- /src/regex/modifiers/globals.js: -------------------------------------------------------------------------------- 1 | module.exports = function (data) { 2 | var globals = [ 3 | "begin", "done", "log", 4 | "testStart", "testDone", 5 | "moduleStart", "moduleDone", 6 | "module", "start", "stop" 7 | ]; 8 | var qunitPrefix = 'QUnit.'; 9 | var result = data; 10 | 11 | globals.map(function (global) { 12 | var regex = new RegExp('\^' + global + '\\('); 13 | var regexWithoutStart = new RegExp(global + '\\('); 14 | var replacement = qunitPrefix + global + '('; 15 | result = result.split('\n').map(function (x) { 16 | var stripped = x.trim(); 17 | if (regex.test(stripped)) { 18 | x = x.replace(regexWithoutStart, replacement); 19 | } 20 | return x; 21 | }).join('\n'); 22 | }); 23 | 24 | return result; 25 | } 26 | -------------------------------------------------------------------------------- /tests/data/10/expected-regex.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define( [ 'qunit', 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( QUnit, Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function( assert ) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function( assert ) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/11/expected-regex.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define( [ 'lib/qunit', 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( QUnit, Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function( assert ) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function( assert ) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/12/expected-regex.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define( [ "lib/qunit", 3 | "cldr", 4 | "src/core", 5 | "json!cldr-data/supplemental/likelySubtags.json", 6 | 7 | "cldr/event" 8 | ], function( QUnit, Cldr, Globalize, likelySubtags ) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function( assert ) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function( assert ) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/10/expected-ast.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "qunit", 4 | "cldr", 5 | "src/core", 6 | "json!cldr-data/supplemental/likelySubtags.json", 7 | "cldr/event" 8 | ], function(QUnit, Cldr, Globalize, likelySubtags) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function(assert) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function(assert) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/11/expected-ast.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "qunit", 4 | "cldr", 5 | "src/core", 6 | "json!cldr-data/supplemental/likelySubtags.json", 7 | "cldr/event" 8 | ], function(QUnit, Cldr, Globalize, likelySubtags) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function(assert) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function(assert) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/data/12/expected-ast.js: -------------------------------------------------------------------------------- 1 | // Taken directly from jquery-globalize 2 | define([ 3 | "qunit", 4 | "cldr", 5 | "src/core", 6 | "json!cldr-data/supplemental/likelySubtags.json", 7 | "cldr/event" 8 | ], function(QUnit, Cldr, Globalize, likelySubtags) { 9 | 10 | Cldr.load( likelySubtags ); 11 | 12 | QUnit.module( "Globalize.locale" ); 13 | 14 | QUnit.test( "should allow String locale", function(assert) { 15 | Globalize.locale( "en" ); 16 | assert.ok( Globalize.cldr instanceof Cldr ); 17 | assert.equal( Globalize.cldr.locale, "en" ); 18 | }); 19 | 20 | QUnit.test( "should allow Cldr instance to be passed as locale", function(assert) { 21 | Globalize.locale( new Cldr( "pt" ) ); 22 | assert.ok( Globalize.cldr instanceof Cldr ); 23 | assert.equal( Globalize.cldr.locale, "pt" ); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /src/ast/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | getHyphenedNameFromCamelCase: function (rule) { 5 | return rule.replace(/([A-Z])/g, 6 | function (str) { return "-" + str.toLowerCase() }) + '.js'; 7 | }, 8 | 9 | getCamelCaseFromHyphenedName: function (filename) { 10 | var tokens = filename.split('-'); 11 | var camelCasedName = tokens.shift(); 12 | tokens.map(function (x) { 13 | camelCasedName += x.charAt(0).toUpperCase() + x.slice(1); 14 | }); 15 | 16 | return camelCasedName; 17 | }, 18 | 19 | checkIfNodeParamsContain: function (node, param) { 20 | var len = node.params.length; 21 | for (var i = 0; i < len; i++) { 22 | if (node.params[i].name === param) { 23 | return true; 24 | } 25 | } 26 | return false; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/regex/modifiers/tests.js: -------------------------------------------------------------------------------- 1 | module.exports = function (data) { 2 | var tests = [ 'test', 'asyncTest' ]; 3 | var qunitPrefix = 'QUnit.'; 4 | var result = data; 5 | var functionRegex = new RegExp('function' +'\\s*' + '\\(\\)'); 6 | var functionReplacement = 'function( assert )'; 7 | 8 | tests.map(function (test) { 9 | var regex = new RegExp('\^' + test + '\\('); 10 | var regexWithoutStart = new RegExp(test + '\\('); 11 | var replacement = qunitPrefix + test + '('; 12 | result = result.split('\n').map(function (x) { 13 | var stripped = x.trim(); 14 | if (regex.test(stripped)) { 15 | x = x.replace(functionRegex, functionReplacement); 16 | x = x.replace(regexWithoutStart, replacement); 17 | } 18 | return x; 19 | }).join('\n'); 20 | }); 21 | 22 | return result; 23 | } 24 | -------------------------------------------------------------------------------- /src/regex/modifiers/assertions.js: -------------------------------------------------------------------------------- 1 | module.exports = function (data) { 2 | var assertions = [ 3 | 'ok', 'equal', 'notEqual', 4 | 'propEqual', 'notPropEqual', 5 | 'deepEqual', 'notDeepEqual', 6 | 'strictEqual', 'notStrictEqual', 7 | 'throws', 'expect' 8 | ]; 9 | var assertPrefix = 'assert.'; 10 | var result = data; 11 | 12 | assertions.map(function (assertion) { 13 | var regex = new RegExp('\^' + assertion + '\\('); 14 | var regexWithoutStart = new RegExp(assertion + '\\('); 15 | var replacement = assertPrefix + assertion + '('; 16 | result = result.split('\n').map(function (x) { 17 | var stripped = x.trim(); 18 | if (regex.test(stripped)) { 19 | x = x.replace(regexWithoutStart, replacement); 20 | } 21 | return x; 22 | }).join('\n'); 23 | }); 24 | 25 | return result; 26 | } 27 | -------------------------------------------------------------------------------- /examples/default.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserConfig": { 3 | "ast": { 4 | "moduleFunction": true, 5 | "reporterFunction": true, 6 | "moduleFunctionParams": true, 7 | "moduleFunctionAssert": true, 8 | "moduleFunctionParamsValue": true, 9 | "reporterFunctionCallback": true, 10 | "testFunction": true, 11 | "testFunctionAssert": true, 12 | "assertPushFunction": true, 13 | "assertionFunction": true, 14 | "asyncTestFunction": true, 15 | "startFunction": true, 16 | "initFunction": true, 17 | "jsDumpFunction": true 18 | }, 19 | "regex": { 20 | "definitions": false, 21 | "quotes": "\"" 22 | } 23 | }, 24 | 25 | "jscsConfig": { 26 | "fix": true, 27 | "preset": "jquery" 28 | }, 29 | 30 | "parser": "ast", 31 | "write": false, 32 | "jscs": true 33 | } 34 | -------------------------------------------------------------------------------- /src/ast/checks/is-jsdump.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | module.exports = function (context) { 4 | var node = context.node; 5 | var parent = context.parent; 6 | 7 | return (node.type === 'MemberExpression' && 8 | node.object.type === 'Identifier' && 9 | node.object.name === constants.qunit && 10 | node.property && 11 | node.property.type === 'Identifier' && 12 | node.property.name === constants.jsdumpExpression && 13 | parent && 14 | parent.node && 15 | parent.node.type === 'MemberExpression' && 16 | parent.parent && 17 | parent.parent.parent.node && 18 | parent.parent.parent.node.type === 'ExpressionStatement' && 19 | parent.parent.parent.node.expression && 20 | parent.parent.parent.node.expression.type === 'CallExpression'); 21 | } 22 | -------------------------------------------------------------------------------- /src/ast/rules/assert-push-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isAssertPush = require('../checks/is-assert-push'); 7 | 8 | module.exports = AssertPushFunction; 9 | 10 | function AssertPushFunction() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.AssertPushFunction; 13 | }; 14 | 15 | 16 | AssertPushFunction.prototype = { 17 | check: function (context) { 18 | return isAssertPush(context); 19 | }, 20 | 21 | update: function (context) { 22 | var _self = this; 23 | var node = context.node; 24 | node.object.name = constants.thisObject; 25 | }, 26 | 27 | getOptionName: function () { 28 | return this._optionName; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/ast/checks/is-assertion.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | 3 | var assertions = [ 4 | constants.okAssertion, 5 | constants.notOkAssertion, 6 | constants.equalAssertion, 7 | constants.notEqualAssertion, 8 | constants.strictEqualAssertion, 9 | constants.notStrictEqualAssertion, 10 | constants.deepEqualAssertion, 11 | constants.notDeepEqualAssertion, 12 | constants.propEqualAssertion, 13 | constants.notPropEqualAssertion, 14 | constants.throwsAssertion, 15 | constants.raisesAssertion, 16 | constants.expectAssertion 17 | ]; 18 | 19 | module.exports = function (context) { 20 | var node = context.node; 21 | var parent = context.parent; 22 | 23 | return node.type === 'Identifier' && 24 | assertions.indexOf(node.name) > -1 && 25 | parent && 26 | parent.node && 27 | parent.node.type === 'CallExpression'; 28 | }; 29 | -------------------------------------------------------------------------------- /examples/sample.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserConfig": { 3 | "ast": { 4 | "moduleFunction": true, 5 | "reporterFunction": false, 6 | "moduleFunctionParams": true, 7 | "moduleFunctionAssert": true, 8 | "moduleFunctionParamsValue": true, 9 | "reporterFunctionCallback": true, 10 | "testFunction": true, 11 | "testFunctionAssert": true, 12 | "assertPushFunction": true, 13 | "assertionFunction": true, 14 | "asyncTestFunction": false, 15 | "startFunction": false, 16 | "initFunction": true, 17 | "jsDumpFunction": false 18 | } 19 | }, 20 | 21 | "jscsConfig": { 22 | "fix": true, 23 | "preset": "jquery", 24 | "requireCurlyBraces": false, 25 | "disallowMultipleLineBreaks": false, 26 | "validateIndentation": "\t" 27 | }, 28 | 29 | "parser": "regex", 30 | "write": false, 31 | "jscs": true 32 | } 33 | -------------------------------------------------------------------------------- /src/regex/helpers/queue.js: -------------------------------------------------------------------------------- 1 | module.exports = Queue; 2 | 3 | function Node(data) { 4 | this.data = data; 5 | this.next = null; 6 | } 7 | 8 | function Queue() { 9 | this.head = null; 10 | this.tail = null; 11 | } 12 | 13 | Queue.prototype.enqueue = function(data) { 14 | var newNode = new Node(data); 15 | 16 | if (this.head === null) { 17 | this.head = newNode; 18 | this.tail = newNode; 19 | } else { 20 | this.tail.next = newNode; 21 | this.tail = newNode; 22 | } 23 | } 24 | 25 | Queue.prototype.dequeue = function() { 26 | var newNode; 27 | if (this.head !== null) { 28 | newNode = this.head.data; 29 | this.head = this.head.next; 30 | } 31 | return newNode; 32 | } 33 | 34 | Queue.prototype.top = function() { 35 | var value; 36 | if (this.head !== null) { 37 | value = this.head.data; 38 | } else { 39 | value = null; 40 | } 41 | return value; 42 | } -------------------------------------------------------------------------------- /src/ast/checks/is-qunit-reporter.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isReporter = require('./is-reporter'); 3 | 4 | var reporters = [ 5 | constants.logReporting, 6 | constants.beginReporting, 7 | constants.doneReporting, 8 | constants.logReporting, 9 | constants.moduleDoneReporting, 10 | constants.moduleStartReporting, 11 | constants.testDoneReporting, 12 | constants.testStartReporting 13 | ]; 14 | 15 | module.exports = function (context) { 16 | var node = context.node 17 | var parent = context.parent; 18 | 19 | return isReporter({node: node, parent: parent}) || 20 | (node.type === "MemberExpression" && 21 | node.object && 22 | node.object.type === "Identifier" && 23 | node.object.name === constants.qunit && 24 | node.property && 25 | node.property.type === "Identifier" && 26 | reporters.indexOf(node.property.name) > 1); 27 | } 28 | -------------------------------------------------------------------------------- /src/ast/rules/reporter-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isReporter = require('../checks/is-reporter'); 7 | 8 | module.exports = ReporterFunction; 9 | 10 | function ReporterFunction() { 11 | this._optionName = optionNames.ReporterFunction; 12 | }; 13 | 14 | 15 | ReporterFunction.prototype = { 16 | check: function (context) { 17 | return isReporter(context); 18 | }, 19 | 20 | update: function (context) { 21 | var node = context.node; 22 | 23 | node = builder.memberExpression( 24 | builder.identifier(constants.qunit), 25 | builder.identifier(node.name), 26 | false 27 | ); 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/ast/rules/test-function-assert.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isTestFunctionParams = require('../checks/is-test-params'); 7 | 8 | module.exports = TestFunctionAssert; 9 | 10 | function TestFunctionAssert() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.TestFunctionAssert; 13 | }; 14 | 15 | 16 | TestFunctionAssert.prototype = { 17 | check: function (context) { 18 | return isTestFunctionParams(context); 19 | }, 20 | 21 | update: function (context) { 22 | var _self = this; 23 | var node = context.node; 24 | node.params.unshift(builder.identifier(constants.assert)); 25 | context.update(node); 26 | }, 27 | 28 | getOptionName: function () { 29 | return this._optionName; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/ast/rules/start-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isStart = require('../checks/is-start'); 7 | 8 | module.exports = StartFunction; 9 | 10 | function StartFunction() { 11 | this._optionName = optionNames.StartFunction; 12 | }; 13 | 14 | 15 | StartFunction.prototype = { 16 | check: function (context) { 17 | return isStart(context); 18 | }, 19 | 20 | update: function (context) { 21 | var _self = this; 22 | var node = context.node; 23 | node.callee = builder.memberExpression( 24 | builder.identifier(constants.qunit), 25 | builder.identifier(node.callee.name), 26 | false 27 | ); 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/ast/rules/jsdump-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isJSDump = require('../checks/is-jsdump'); 7 | 8 | module.exports = JsDumpFunction; 9 | 10 | function JsDumpFunction() { 11 | this._optionName = optionNames.JsDumpFunction; 12 | }; 13 | 14 | 15 | JsDumpFunction.prototype = { 16 | check: function (context) { 17 | return isJSDump(context); 18 | }, 19 | 20 | update: function (context) { 21 | var _self = this; 22 | var node = context.node; 23 | node = builder.memberExpression( 24 | builder.identifier(constants.qunit), 25 | builder.identifier(constants.dumpExpression), 26 | false); 27 | 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/ast/rules/assertion-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isAssertion = require('../checks/is-assertion'); 7 | 8 | module.exports = AssertionFunction; 9 | 10 | function AssertionFunction() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.AssertionFunction; 13 | }; 14 | 15 | 16 | AssertionFunction.prototype = { 17 | check: function (context) { 18 | return isAssertion(context); 19 | }, 20 | 21 | update: function (context) { 22 | var node = context.node; 23 | node = builder.memberExpression( 24 | builder.identifier(constants.assert), 25 | builder.identifier(node.name) 26 | ); 27 | 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /tests/src/ast.js: -------------------------------------------------------------------------------- 1 | module.exports = function () { 2 | var fs = require('fs'); 3 | var assert = require('assert'); 4 | var glob = require('glob'); 5 | var astApi = require('../../src/ast'); 6 | var actual = []; 7 | var expected = []; 8 | 9 | glob('tests/data/**/*.js', function (error, files) { 10 | for (var i = 0; i < files.length; i++) { 11 | if (files[i].indexOf('actual') > -1) { 12 | actual.push(files[i]); 13 | } else if (files[i].indexOf('expected-ast') > -1) { 14 | expected.push(files[i]); 15 | } 16 | }; 17 | 18 | describe('AST tests', function () { 19 | it('should convert properly', function () { 20 | var length = actual.length; 21 | 22 | for(var i = 0; i < length; i++) { 23 | assert.equal( 24 | astApi(fs.readFileSync(actual[i]).toString()), 25 | fs.readFileSync(expected[i]).toString()); 26 | } 27 | }) 28 | }); 29 | }); 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/ast/rules/test-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isTest = require('../checks/is-test'); 7 | 8 | module.exports = TestFunction; 9 | 10 | function TestFunction() { 11 | this._property = constants.test; 12 | this._optionName = optionNames.TestFunction; 13 | }; 14 | 15 | 16 | TestFunction.prototype = { 17 | check: function (context) { 18 | return isTest(context); 19 | }, 20 | 21 | update: function (context) { 22 | var _self = this; 23 | var node = context.node; 24 | node.callee = builder.memberExpression( 25 | builder.identifier(constants.qunit), 26 | builder.identifier(_self._property), 27 | false 28 | ); 29 | context.update(node); 30 | }, 31 | 32 | getOptionName: function () { 33 | return this._optionName; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/ast/rules/module-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isModule = require('../checks/is-module'); 7 | 8 | module.exports = ModuleFunction; 9 | 10 | function ModuleFunction() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.ModuleFunction; 13 | }; 14 | 15 | 16 | ModuleFunction.prototype = { 17 | check: function (context) { 18 | return isModule(context); 19 | }, 20 | 21 | update: function (context) { 22 | var _self = this; 23 | var node = context.node; 24 | node.callee = builder.memberExpression( 25 | builder.identifier(constants.qunit), 26 | builder.identifier(_self._property), 27 | false 28 | ); 29 | context.update(node); 30 | }, 31 | 32 | getOptionName: function () { 33 | return this._optionName; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/ast/rules/reporter-function-callback.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isReporterCallbackExpression = require('../checks/is-reporter-callback-expression'); 7 | 8 | module.exports = ReporterFunctionCallback; 9 | 10 | function ReporterFunctionCallback() { 11 | this._property = constants.log; 12 | this._optionName = optionNames.ReporterFunctionCallback; 13 | }; 14 | 15 | 16 | ReporterFunctionCallback.prototype = { 17 | check: function (context) { 18 | return isReporterCallbackExpression(context); 19 | }, 20 | 21 | update: function (context) { 22 | var node = context.node; 23 | var _self = this; 24 | node = builder.callExpression( 25 | node.left, 26 | [node.right]); 27 | 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /tests/data/2/actual.js: -------------------------------------------------------------------------------- 1 | test('Def tests'); 2 | test('Def tests'); 3 | // Same tests are here to check if regex is wokring properly second time 4 | asyncTest('Def tests'); 5 | asyncTest('Def tests'); 6 | QUnit.test('Def tests 2'); 7 | QUnit.asyncTest('Def tests 3'); 8 | test('Def tests', function () { 9 | 10 | }); 11 | 12 | test('Def tests', function() { 13 | 14 | }); 15 | 16 | test('Def tests', function(){ 17 | 18 | }); 19 | 20 | asyncTest('Def tests', function () { 21 | 22 | }); 23 | 24 | asyncTest('Def tests', function() { 25 | 26 | }); 27 | 28 | asyncTest('Def tests', function(){ 29 | 30 | }); 31 | 32 | // Won't match all these so these would remain as they are 33 | QUnit.test('Def tests', function () { 34 | 35 | }); 36 | 37 | QUnit.test('Def tests', function() { 38 | 39 | }); 40 | 41 | QUnit.test('Def tests', function(){ 42 | 43 | }); 44 | 45 | QUnit.asyncTest('Def tests', function () { 46 | 47 | }); 48 | 49 | QUnit.asyncTest('Def tests', function() { 50 | 51 | }); 52 | 53 | QUnit.asyncTest('Def tests', function(){ 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /src/ast/rules/module-function-params.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isModuleParams = require('../checks/is-module-params'); 7 | 8 | module.exports = ModuleFunctionParams; 9 | 10 | function ModuleFunctionParams() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.ModuleFunctionParams; 13 | this._nameMap = {}; 14 | this._nameMap[constants['moduleSetup']] = constants.moduleBeforeEach; 15 | this._nameMap[constants['moduleTeardown']] = constants.moduleAfterEach; 16 | }; 17 | 18 | 19 | ModuleFunctionParams.prototype = { 20 | check: function (context) { 21 | return isModuleParams(context); 22 | }, 23 | 24 | update: function (context) { 25 | var _self = this; 26 | var node = context.node; 27 | node.name = this._nameMap[node.name]; 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /tests/data/2/expected-regex.js: -------------------------------------------------------------------------------- 1 | QUnit.test('Def tests'); 2 | QUnit.test('Def tests'); 3 | // Same tests are here to check if regex is wokring properly second time 4 | QUnit.test('Def tests'); 5 | QUnit.test('Def tests'); 6 | QUnit.test('Def tests 2'); 7 | QUnit.test('Def tests 3'); 8 | QUnit.test('Def tests', function( assert ) { 9 | 10 | }); 11 | 12 | QUnit.test('Def tests', function( assert ) { 13 | 14 | }); 15 | 16 | QUnit.test('Def tests', function( assert ){ 17 | 18 | }); 19 | 20 | QUnit.test('Def tests', function( assert ) { 21 | 22 | }); 23 | 24 | QUnit.test('Def tests', function( assert ) { 25 | 26 | }); 27 | 28 | QUnit.test('Def tests', function( assert ){ 29 | 30 | }); 31 | 32 | // Won't match all these so these would remain as they are 33 | QUnit.test('Def tests', function () { 34 | 35 | }); 36 | 37 | QUnit.test('Def tests', function() { 38 | 39 | }); 40 | 41 | QUnit.test('Def tests', function(){ 42 | 43 | }); 44 | 45 | QUnit.test('Def tests', function () { 46 | 47 | }); 48 | 49 | QUnit.test('Def tests', function() { 50 | 51 | }); 52 | 53 | QUnit.test('Def tests', function(){ 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /tests/data/2/expected-ast.js: -------------------------------------------------------------------------------- 1 | QUnit.test('Def tests'); 2 | QUnit.test('Def tests'); 3 | // Same tests are here to check if regex is wokring properly second time 4 | QUnit.test('Def tests'); 5 | QUnit.test('Def tests'); 6 | QUnit.test('Def tests 2'); 7 | QUnit.test('Def tests 3'); 8 | QUnit.test('Def tests', function(assert) { 9 | 10 | }); 11 | 12 | QUnit.test('Def tests', function(assert) { 13 | 14 | }); 15 | 16 | QUnit.test('Def tests', function(assert) { 17 | 18 | }); 19 | 20 | QUnit.test('Def tests', function(assert) { 21 | 22 | }); 23 | 24 | QUnit.test('Def tests', function(assert) { 25 | 26 | }); 27 | 28 | QUnit.test('Def tests', function(assert) { 29 | 30 | }); 31 | 32 | // Won't match all these so these would remain as they are 33 | QUnit.test('Def tests', function(assert) { 34 | 35 | }); 36 | 37 | QUnit.test('Def tests', function(assert) { 38 | 39 | }); 40 | 41 | QUnit.test('Def tests', function(assert) { 42 | 43 | }); 44 | 45 | QUnit.test('Def tests', function(assert) { 46 | 47 | }); 48 | 49 | QUnit.test('Def tests', function(assert) { 50 | 51 | }); 52 | 53 | QUnit.test('Def tests', function(assert) { 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Amanpreet Singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/ast/checks/is-module-params.js: -------------------------------------------------------------------------------- 1 | var constants = require('../constants'); 2 | var isQUnitModule = require('./is-qunit-module'); 3 | 4 | var nameMap = {}; 5 | nameMap[constants['moduleSetup']] = constants.moduleBeforeEach; 6 | nameMap[constants['moduleTeardown']] = constants.moduleAfterEach; 7 | 8 | // For assert change 9 | nameMap[constants['moduleAfterEach']] = constants.moduleAfterEach; 10 | nameMap[constants['moduleBeforeEach']] = constants.moduleBeforeEach; 11 | 12 | module.exports = function (context) { 13 | var node = context.node; 14 | var parent = context.parent; 15 | 16 | return node.type === 'Identifier' && 17 | nameMap.hasOwnProperty(node.name) && 18 | parent && 19 | parent.node && 20 | parent.node.type === 'Property' && 21 | parent.parent && 22 | parent.parent.parent && 23 | parent.parent.parent.node && 24 | parent.parent.parent.node.type === 'ObjectExpression' && 25 | parent.parent.parent.parent && 26 | parent.parent.parent.parent.parent && 27 | parent.parent.parent.parent.parent.node && 28 | isQUnitModule({ node: parent.parent.parent.parent.parent.node }); 29 | }; 30 | -------------------------------------------------------------------------------- /src/ast/rules/module-function-params-value.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isModuleFunctionParamsValue = require('../checks/is-module-function-params-value'); 7 | 8 | module.exports = ModuleFunctionParamsValue; 9 | 10 | function ModuleFunctionParamsValue() { 11 | this._property = constants.module; 12 | this._optionName = optionNames.ModuleFunctionParamsValue; 13 | this._nameMap = {}; 14 | this._nameMap[constants['moduleSetup']] = constants.moduleBeforeEach; 15 | this._nameMap[constants['moduleTeardown']] = constants.moduleAfterEach; 16 | }; 17 | 18 | 19 | ModuleFunctionParamsValue.prototype = { 20 | check: function (context) { 21 | return isModuleFunctionParamsValue(context); 22 | }, 23 | 24 | update: function (context) { 25 | var _self = this; 26 | var node = context.node; 27 | node.params.unshift(builder.identifier(constants.assert)); 28 | context.update(node); 29 | }, 30 | 31 | getOptionName: function () { 32 | return this._optionName; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/ast/rules/anonymous-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isAnonymous = require('../checks/is-anonymous'); 7 | 8 | module.exports = AnonymousFunction; 9 | 10 | function AnonymousFunction() { 11 | this._optionName = optionNames.AnonymousFunction; 12 | }; 13 | 14 | 15 | AnonymousFunction.prototype = { 16 | check: function (context) { 17 | return isAnonymous(context); 18 | }, 19 | 20 | update: function (context) { 21 | var _self = this; 22 | var node = context.node; 23 | 24 | var params = node.expression.callee.params; 25 | var paramLength = params.length; 26 | 27 | for(var i = 0; i < paramLength; i++) { 28 | var param = params[i]; 29 | if (param.type === 'Identifier' && param.name === constants.qunit) { 30 | return; 31 | } 32 | } 33 | 34 | params.unshift(builder.identifier(constants.qunit)); 35 | node.expression.arguments.unshift(builder.identifier(constants.qunit)); 36 | context.update(node); 37 | }, 38 | 39 | getOptionName: function () { 40 | return this._optionName; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qunit-migrate", 3 | "version": "2.0.2", 4 | "bin": "bin/qunit-migrate", 5 | "description": "Migrate old QUnit code to 2.x", 6 | "main": "src/api.js", 7 | "scripts": { 8 | "test": "./node_modules/mocha/bin/mocha -u bdd tests/main.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/apsdehal/qunit-migrate.git" 13 | }, 14 | "keywords": [ 15 | "qunit", 16 | "migrate", 17 | "old" 18 | ], 19 | "author": "Amanpreet Singh", 20 | "licenses": [ 21 | { 22 | "type": "MIT", 23 | "url": "https://github.com/apsdehal/awesome-ctf/LICENSE.txt" 24 | } 25 | ], 26 | "devDependencies": { 27 | "chai": "^2.2.0", 28 | "mocha": "~2.2.1" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/apsdehal/qunit-migrate/issues" 32 | }, 33 | "homepage": "https://github.com/apsdehal/qunit-migrate", 34 | "dependencies": { 35 | "chalk": "^1.1.1", 36 | "commander": "^2.9.0", 37 | "detect-indent": "^4.0.0", 38 | "estraverse": "^4.1.0", 39 | "exit": "^0.1.2", 40 | "extend": "^3.0.0", 41 | "glob": "^7.0.3", 42 | "jscs": "^2.11.0", 43 | "log-symbols": "^1.0.2", 44 | "recast": "^0.11.3", 45 | "traverse": "^0.6.6" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ast/config/generator.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var utils = require('../utils'); 4 | var assert = require('assert'); 5 | 6 | module.exports = ConfigGenerator; 7 | 8 | 9 | function ConfigGenerator(config) { 10 | this._rules = {}; 11 | 12 | this.registerDefaultRules(); 13 | 14 | var rulesLen = this._rules.length; 15 | 16 | Object.keys(this._rules).forEach(function (prop) { 17 | 18 | if (this._rules.hasOwnProperty(prop) && !config[prop]) { 19 | delete this._rules[prop]; 20 | } 21 | }, this); 22 | }; 23 | 24 | 25 | ConfigGenerator.prototype.getRules = function () { 26 | return this._rules; 27 | }; 28 | 29 | ConfigGenerator.prototype.registerDefaultRules = function () { 30 | var dir = path.join(__dirname, '../rules'); 31 | 32 | fs.readdirSync(dir).forEach(function(rule) { 33 | this.registerRule( 34 | require(path.join(dir, rule)) 35 | ); 36 | }, this); 37 | }; 38 | 39 | ConfigGenerator.prototype.registerRule = function (rule) { 40 | if (typeof rule === 'function') { 41 | var RuleClass = rule; 42 | rule = new RuleClass(); 43 | } 44 | 45 | var optionName = rule.getOptionName(); 46 | assert(!this._rules.hasOwnProperty(optionName), 'Rule "' + optionName + '" is already registered'); 47 | this._rules[optionName] = rule; 48 | }; 49 | -------------------------------------------------------------------------------- /src/ast/constants.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'assert': 'assert', 3 | 'assertPush': 'push', 4 | 'asyncExpression': 'async', 5 | 'asyncTest': 'asyncTest', 6 | 'beginReporter': 'begin', 7 | 'deepEqualAssertion': 'deepEqual', 8 | 'defineExpression': 'define', 9 | 'doneReporter': 'done', 10 | 'dumpExpression': 'dump', 11 | 'equalAssertion': 'equal', 12 | 'expectAssertion': 'expect', 13 | 'init': 'init', 14 | 'jsdumpExpression': 'jsDump', 15 | 'logReporter': 'log', 16 | 'module': 'module', 17 | 'moduleAfterEach': 'afterEach', 18 | 'moduleBeforeEach': 'beforeEach', 19 | 'moduleDoneReporter': 'moduleDone', 20 | 'moduleSetup': 'setup', 21 | 'moduleStartReporter': 'moduleStart', 22 | 'moduleTeardown': 'teardown', 23 | 'notDeepEqualAssertion': 'notDeepEqual', 24 | 'notEqualAssertion': 'notEqual', 25 | 'notOkAssertion': 'notOk', 26 | 'notPropEqualAssertion': 'notPropEqual', 27 | 'notStrictEqualAssertion': 'notStrictEqual', 28 | 'okAssertion': 'ok', 29 | 'propEqualAssertion': 'propEqual', 30 | 'qunit': 'QUnit', 31 | 'qunitSmallExpression': 'qunit', 32 | 'raisesAssertion': 'raises', 33 | 'readyExpression': 'ready', 34 | 'start': 'start', 35 | 'stop': 'stop', 36 | 'strictEqualAssertion': 'strictEqual', 37 | 'test': 'test', 38 | 'testDoneReporter': 'testDone', 39 | 'testStartReporter': 'testStart', 40 | 'thisObject': 'this', 41 | 'throwsAssertion': 'throws', 42 | 'varDeclarator': 'var' 43 | }; 44 | -------------------------------------------------------------------------------- /src/ast/rules/define-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isDefine = require('../checks/is-define'); 7 | 8 | module.exports = DefineFunction; 9 | 10 | function DefineFunction() { 11 | this._optionName = optionNames.DefineFunction; 12 | }; 13 | 14 | 15 | DefineFunction.prototype = { 16 | check: function (context) { 17 | return isDefine(context); 18 | }, 19 | 20 | update: function (context) { 21 | var _self = this; 22 | var node = context.node; 23 | var argLen = node.expression.arguments.length; 24 | var args = node.expression.arguments; 25 | var hasArray = 0, hasFunction = 0, hasLiteral = 0; 26 | 27 | for(var i = 0; i < argLen; i++) { 28 | var arg = args[i]; 29 | if (arg.type === 'ArrayExpression') { 30 | arg.elements.unshift(builder.literal(constants.qunitSmallExpression)); 31 | hasArray = 1; 32 | } else if (arg.type === 'FunctionExpression') { 33 | arg.params.unshift(builder.identifier(constants.qunit)); 34 | hasFunction = 1; 35 | } else if (arg.type === 'Literal') { 36 | hasLiteral = 1; 37 | } 38 | } 39 | 40 | if (hasFunction && !hasArray) { 41 | var arrayExpression = builder.arrayExpression([builder.literal(constants.qunitSmallExpression)]) 42 | if (hasLiteral) { 43 | args.splice(1, 0, arrayExpression); 44 | } else { 45 | args.unshift(arrayExpression); 46 | } 47 | } 48 | 49 | context.update(node); 50 | }, 51 | 52 | getOptionName: function () { 53 | return this._optionName; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /examples/rules.md: -------------------------------------------------------------------------------- 1 | # Config options for AST parser 2 | 3 | All these options are set true by default 4 | 5 | ### anonymousFunction 6 | 7 | If anonymous function definitions should be prepended with QUnit 8 | 9 | ### assertionFunction 10 | 11 | If assertions should be prepended with `assert.`. For e.g. `equal` with `assert.equal`. 12 | 13 | ### assertPushFunction 14 | 15 | If `QUnit.push` in QUnit.assert additions should be replaced `this.push` 16 | 17 | ### asyncTestFunction 18 | 19 | If `asyncTest` definitions should be fixed. 20 | 21 | ### defineFunction 22 | 23 | If requirejs definitions should be fixed and require proper qunit. You might want to disable if you already require qunit 24 | 25 | ### initFunction 26 | 27 | If you want migrator to remove `QUnit.init` from code 28 | 29 | ### jsDumpFunction 30 | 31 | If you want `QUnit.jsDump.parse` to be replaced by `QUnit.dump.parse` 32 | 33 | ### moduleFunction 34 | 35 | If you want `module` to be replaced by `QUnit.module` 36 | 37 | ### moduleFunctionParams 38 | 39 | If you want `setup` and `teardown` should be replaced by `beforeEach` and `afterEach` 40 | 41 | ### moduleFunctionParamsValue 42 | 43 | If you want `assert` to function parameters of `beforeEach` and `afterEach`. You might want to disable this if you don't use `assert` in these functions. 44 | 45 | ### reporterFunction 46 | 47 | If `begin`, `done`, `log`, `moduleDone`, `moduleStart`, `testDone`, `testStart` should be appended with `QUnit.`. 48 | 49 | ### reporterFunctionCallback 50 | 51 | If reporter functions' callback which is in `StatementExpression` should be replaced with callback type expression. 52 | 53 | ### startFunction 54 | 55 | If `start` function should be replaced with `QUnit.start`, given it was already not replaced by `asyncTestFunction` 56 | 57 | ### testFunction 58 | 59 | If `test` should be replaced with `QUnit.test` 60 | 61 | ### testFunctionAssert 62 | 63 | If `assert` should be added as a parameter to `test` function's callback 64 | -------------------------------------------------------------------------------- /bin/qunit-migrate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var program = require('commander'); 3 | var fs = require('fs'); 4 | var chalk = require('chalk'); 5 | var extend = require('extend'); 6 | var api = require('../src/cli-api'); 7 | var exit = require('exit'); 8 | var logSymbols = require('log-symbols'); 9 | 10 | program 11 | .version('2.0.0') 12 | .usage( 13 | '[options] \n\n QUnit Migrate: A tool to migrate your files to QUnit 2.0 API') 14 | .option('-c, --config ', 'Config file for qunit-migrate') 15 | .option('-P, --parser ', 'Parser to be used for parsing, Default: ast') 16 | .option('-w, --write', 'Pass if parsed files should be overwritten. Default: false') 17 | .option('-p, --preset ', 'Preset rule for jscs config. Default: jquery') 18 | .option('-j, --no-jscs', 'Pass if jscs fix should not be applied. Default: true') 19 | 20 | program.on('--help', function(){ 21 | console.log(' Globbing is supported in files') 22 | console.log(''); 23 | console.log(' Examples:'); 24 | console.log(''); 25 | console.log(' $ qunit-migrate "./**/*.js" -w --preset "google" -c "config.json"'); 26 | console.log(''); 27 | console.log(' By Amanpreet Singh <@apsdehal>'); 28 | console.log(''); 29 | }); 30 | 31 | program.parse(process.argv); 32 | 33 | var config; 34 | 35 | if (program.config) { 36 | try { 37 | config = fs.readFileSync(program.config); 38 | } catch (e) { 39 | console.log(logSymbols.error + ' ' + 40 | chalk.bold.red('Failed to read config file passed: %s'), 41 | program.config); 42 | console.log(e.toString()); 43 | exit(); 44 | } 45 | 46 | try { 47 | config = JSON.parse(config); 48 | } catch (e) { 49 | console.log(logSymbols.error + ' ' + 50 | chalk.bold.red('Failed to parse JSON in file: %s'), 51 | program.config); 52 | console.log(e.toString()); 53 | exit(); 54 | 55 | } 56 | } 57 | 58 | config = config || {}; 59 | 60 | extend(config, { 61 | files: program.args, 62 | write: program.write, 63 | jscs: program.jscs, 64 | parser: program.parser, 65 | preset: program.preset 66 | }); 67 | 68 | api(config); 69 | -------------------------------------------------------------------------------- /tests/src/regex.js: -------------------------------------------------------------------------------- 1 | module.exports = function () { 2 | var assertionsModifier = require('../../src/regex/modifiers/assertions'); 3 | var testsModifier = require('../../src/regex/modifiers/tests'); 4 | var globalsModifier = require('../../src/regex/modifiers/globals'); 5 | var definitionsModifier = require('../../src/regex/modifiers/definitions'); 6 | var asyncModifier = require('../../src/regex/modifiers/async'); 7 | var mainModifier = require('../../src/regex/main'); 8 | var assert = require('assert'); 9 | var fs = require('fs'); 10 | var noOfData = 12; 11 | 12 | var oneToTwelveArray = []; 13 | for(var i = 1; i <= noOfData; i++) { 14 | oneToTwelveArray.push(i); 15 | } 16 | 17 | var testData = oneToTwelveArray.map(function (i) { 18 | return fs.readFileSync('tests/data/' + i + '/actual.js').toString(); 19 | }) 20 | 21 | var expectedData = oneToTwelveArray.map(function (i) { 22 | return fs.readFileSync('tests/data/' + i + '/expected-regex.js').toString(); 23 | }) 24 | 25 | describe('Assertions modules', function () { 26 | it('should have a working assertion modifier', function () { 27 | for (var i = 0; i < 1; i++) { 28 | var result = assertionsModifier(testData[i]); 29 | assert.equal(result, expectedData[i]); 30 | } 31 | }); 32 | }); 33 | 34 | describe('Tests modules', function () { 35 | it('should have a working tests modifier', function () { 36 | for (var i = 1; i < 2; i++) { 37 | var result = testsModifier(testData[i]); 38 | result = asyncModifier(result); 39 | assert.equal(result, expectedData[i]); 40 | } 41 | }); 42 | }); 43 | 44 | describe('Async modules', function () { 45 | it('should have a working async modifier', function () { 46 | for (var i = 2; i < 3; i++) { 47 | var result = globalsModifier(testData[i]); 48 | result = testsModifier(result); 49 | result = asyncModifier(result); 50 | assert.equal(result, expectedData[i]); 51 | } 52 | }); 53 | }); 54 | 55 | describe('Globals modules', function () { 56 | it('should have a working globals modifier', function () { 57 | for (var i = 3; i < 4; i++) { 58 | var result = globalsModifier(testData[i]); 59 | assert.equal(result, expectedData[i]); 60 | } 61 | }); 62 | }); 63 | 64 | describe('Definitions modules', function () { 65 | it('should have a working definitions modifier', function () { 66 | for (var i = 4; i < 7; i++) { 67 | var result = definitionsModifier(testData[i]); 68 | assert.equal(result, expectedData[i]); 69 | } 70 | }); 71 | }); 72 | 73 | describe('Main worker', function () { 74 | it('should have a working main worker', function () { 75 | var options = { definitions: false }; 76 | for (var i = 7; i < 12; i++) { 77 | var result = mainModifier(testData[i], options); 78 | assert.equal(result, expectedData[i]) 79 | if (i == 7) { 80 | options.definitions = true; 81 | } 82 | if (i == 9) { 83 | options.definitions = 'lib/qunit'; 84 | } 85 | if (i == 10) { 86 | options.quotes = '"'; 87 | } 88 | } 89 | }); 90 | }); 91 | }; 92 | -------------------------------------------------------------------------------- /src/regex/modifiers/definitions.js: -------------------------------------------------------------------------------- 1 | module.exports = function (data, options) { 2 | options = options || {}; 3 | 4 | if (options.definitions === true || !options.definitions) { 5 | options.definitions = 'qunit'; 6 | } 7 | 8 | if (!options.quotes) { 9 | // Default single quote support 10 | options.quotes = '\''; 11 | } 12 | 13 | var qunitString = 'QUnit'; 14 | var result = data; 15 | result = result.split('\n'); 16 | var defineResults = testDefine(result, options); 17 | if (defineResults.found) { 18 | return defineResults.result; 19 | } 20 | var anonResults = testAnon(result); 21 | if (anonResults.found) { 22 | return anonResults.result; 23 | } 24 | } 25 | 26 | var replacementAnonStart = '( function( QUnit,'; 27 | var replacementAnonEnd = '} )( QUnit, '; 28 | 29 | 30 | function testDefine(data, options) { 31 | 32 | var replacementDefine = 'define( [ ' + options.quotes 33 | + options.definitions 34 | + options.quotes + '\,'; 35 | 36 | var regex = new RegExp('\^' + 'define\\('); 37 | var regexWithoutStart = new RegExp('define\\('); 38 | var depsRegex = new RegExp('\\[\n*'); 39 | var functionRegex = new RegExp('function\\s*\\('); 40 | var noDefinition = new RegExp('\^' + 'define\\(\\s*\\['); 41 | var noDefinitionWithoutStart = new RegExp('define\\(\\s*\\['); 42 | var depsToBeFound = false; 43 | var qunitDepToBeInserted = false; 44 | var foundDefine = false; 45 | 46 | var result = data.map(function (x) { 47 | var stripped = x.trim(); 48 | if (!foundDefine) { 49 | if (regex.test(stripped)) { 50 | foundDefine = true; 51 | if (noDefinition.test(x)) { 52 | x = x.replace(noDefinitionWithoutStart, replacementDefine); 53 | qunitDepToBeInserted = true; 54 | } else { 55 | depsToBeFound = true; 56 | } 57 | } 58 | } 59 | 60 | if (depsToBeFound) { 61 | if (depsRegex.test(x)) { 62 | x = x.replace(depsRegex, '[ ' + options.quotes 63 | + options.definitions + options.quotes + '\,'); 64 | qunitDepToBeInserted = true; 65 | depsToBeFound = false; 66 | } 67 | } 68 | 69 | if (qunitDepToBeInserted) { 70 | if (functionRegex.test(x)) { 71 | x = x.replace(functionRegex, 'function( QUnit,'); 72 | qunitDepToBeInserted = false; 73 | } 74 | } 75 | return x; 76 | }).join('\n'); 77 | 78 | return { result: result, found: foundDefine }; 79 | } 80 | 81 | function testAnon(data) { 82 | var regex = new RegExp('\^' + '\\(\\s*function\\s*\\('); 83 | var matchAnonRegex = new RegExp('\\}\\s*\\)\\s*\\(\\s*'); 84 | var matchAnonToBeFound = false; 85 | var foundAnon = false; 86 | var result = data.map(function (x) { 87 | if (!foundAnon) { 88 | if (regex.test(x)) { 89 | x = x.replace(regex, replacementAnonStart); 90 | matchAnonToBeFound = true; 91 | foundAnon = true; 92 | } 93 | 94 | } 95 | if (matchAnonToBeFound) { 96 | if (matchAnonRegex.test(x)) { 97 | x = x.replace(matchAnonRegex, replacementAnonEnd); 98 | matchAnonToBeFound = false; 99 | } 100 | } 101 | return x; 102 | }).join('\n'); 103 | 104 | return { result: result, found: foundAnon }; 105 | } 106 | -------------------------------------------------------------------------------- /src/ast/rules/async-test-function.js: -------------------------------------------------------------------------------- 1 | var builder = require('recast').types.builders; 2 | var constants = require('../constants'); 3 | var path = require('path'); 4 | var utils = require('../utils'); 5 | var optionNames = require('../option-names'); 6 | var isQUnitAsyncTest = require('../checks/is-qunit-async-test'); 7 | var isQUnitStart = require('../checks/is-qunit-start'); 8 | var isQUnitStop = require('../checks/is-qunit-stop'); 9 | var traverse = require('traverse'); 10 | 11 | module.exports = AsyncTestFunction; 12 | 13 | // We don't need to take care of parameter assert in function 14 | // Since it will be automatically added when this converts to 15 | // QUnit.test by test-function-assert 16 | function AsyncTestFunction() { 17 | this._property = constants.test; 18 | this._optionName = optionNames.AsyncTestFunction; 19 | }; 20 | 21 | 22 | AsyncTestFunction.prototype = { 23 | check: function (context) { 24 | return isQUnitAsyncTest(context); 25 | }, 26 | 27 | update: function (context) { 28 | var _self = this; 29 | var node = context.node; 30 | 31 | node.callee = builder.memberExpression( 32 | builder.identifier(constants.qunit), 33 | builder.identifier(_self._property), 34 | false 35 | ); 36 | 37 | if (node.arguments && 38 | node.arguments[1] && 39 | node.arguments[1].body && 40 | node.arguments[1].body.body) { 41 | 42 | var statements = node.arguments[1].body.body; 43 | var len = statements.length; 44 | var stops = 0; 45 | var starts = 0; 46 | var expressionStatement; 47 | 48 | // Traverse again because there might be QUnit.start() 49 | // hidden in depths of this function 50 | traverse(node).forEach(function (blockNode) { 51 | if (blockNode) { 52 | if (blockNode.type === 'ExpressionStatement') { 53 | 54 | if (isQUnitStop({node: blockNode.expression})) { 55 | blockNode = _self.getAssertAsyncDeclaration(stops); 56 | stops++; 57 | } else if (isQUnitStart({node: blockNode.expression})) { 58 | blockNode = _self.getDoneCallExpression(starts); 59 | starts++; 60 | } 61 | } 62 | this.update(blockNode); 63 | } 64 | }); 65 | 66 | while (stops < starts) { 67 | statements.unshift(this.getAssertAsyncDeclaration(stops)); 68 | stops++; 69 | } 70 | } 71 | 72 | context.update(node); 73 | }, 74 | 75 | getOptionName: function () { 76 | return this._optionName; 77 | }, 78 | 79 | getAssertAsyncDeclaration: function (stops) { 80 | return builder.variableDeclaration(constants.varDeclarator, [ 81 | builder.variableDeclarator( 82 | builder.identifier( 83 | constants.readyExpression + (stops ? stops : '')), 84 | builder.callExpression( 85 | builder.memberExpression( 86 | builder.identifier(constants.assert), 87 | builder.identifier(constants.asyncExpression), 88 | false), 89 | []))]); 90 | }, 91 | 92 | getDoneCallExpression: function (starts) { 93 | return builder.expressionStatement( 94 | builder.callExpression( 95 | builder.identifier( 96 | constants.readyExpression + (starts ? starts : '')), 97 | [])); 98 | } 99 | }; 100 | -------------------------------------------------------------------------------- /src/regex/modifiers/async.js: -------------------------------------------------------------------------------- 1 | var Queue = require('../helpers/queue'); 2 | var Indent = require('../helpers/indent'); 3 | 4 | module.exports = function (data) { 5 | var test = 'QUnit.asyncTest'; 6 | var testReplacement = 'QUnit.test'; 7 | var doneString = 'done'; 8 | var result = data; 9 | result = result.split('\n'); 10 | 11 | var regex = new RegExp('\^' + test); 12 | var regexWithoutStart = new RegExp(test); 13 | var openingBracketsRegex = new RegExp('\\{'); 14 | var closingBracketsRegex = new RegExp('\\}'); 15 | var functionRegex = new RegExp('function\\( assert \\)'); 16 | 17 | // We have generalized all kind of stops, starts by 18 | // passing them through global modifier 19 | var asyncStopRegex = new RegExp('QUnit\\.stop\\(\\);'); 20 | var asyncStartRegex = new RegExp('QUnit\\.start\\(\\)'); 21 | 22 | var bracketsQueue = new Queue(); 23 | 24 | for(var i = 0; i < result.length; i++) { 25 | var x = result[i]; 26 | var stripped = x.trim(); 27 | if (regex.test(stripped)) { 28 | x = x.replace(regexWithoutStart, testReplacement); 29 | 30 | result[i] = x; 31 | 32 | if (!functionRegex.test(stripped)) { 33 | continue; 34 | } 35 | // Get indent for line next to the starting line 36 | var indent = Indent(x); 37 | 38 | 39 | foundFirstBracket = false; 40 | var top = null; 41 | var numberOfStarts = 0; 42 | var donePrefix = 'done'; 43 | var originalI = i; 44 | 45 | // Finding number of calls to start() 46 | while(top !== null || foundFirstBracket === false) { 47 | var hasOpeningBrackets = openingBracketsRegex.test(stripped); 48 | 49 | if (hasOpeningBrackets) { 50 | bracketsQueue.enqueue('{'); 51 | if (top === null) { 52 | foundFirstBracket = true; 53 | } 54 | } 55 | 56 | var hasClosingBrackets = closingBracketsRegex.test(stripped); 57 | 58 | if (hasClosingBrackets) { 59 | bracketsQueue.dequeue(); 60 | } 61 | 62 | 63 | if (asyncStartRegex.test(stripped)) { 64 | x = x.replace(asyncStartRegex, 65 | donePrefix + (numberOfStarts ? numberOfStarts : '') + '()'); 66 | numberOfStarts++; 67 | } 68 | 69 | // Remove any stop call found 70 | if (asyncStopRegex.test(stripped)) { 71 | result.splice(i, 1); 72 | x = result[i]; 73 | stripped = x.trim(); 74 | continue; 75 | } 76 | 77 | // Set new top 78 | var top = bracketsQueue.top(); 79 | 80 | // Set result back 81 | result[i] = x; 82 | i++; 83 | x = result[i]; 84 | stripped = x.trim(); 85 | } 86 | 87 | var doneStringToBeAppended = []; 88 | var counter = 0; 89 | 90 | while(counter < numberOfStarts) { 91 | doneStringToBeAppended.push( 92 | indent + 'var done' + 93 | (counter ? counter : '') + ' = assert.async();'); 94 | counter++; 95 | } 96 | 97 | doneStringToBeAppended = doneStringToBeAppended.join('\n'); 98 | if (doneStringToBeAppended.length > 0) { 99 | result.splice(originalI+1, 0, doneStringToBeAppended); 100 | // Since we added an element to array, current i needs to be 101 | // updated 102 | i++; 103 | } 104 | 105 | } 106 | } 107 | 108 | return result.join('\n'); 109 | } -------------------------------------------------------------------------------- /src/cli-api.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk'); 2 | var glob = require('glob'); 3 | var Checker = require('jscs'); 4 | var exit = require('exit'); 5 | var fs = require('fs'); 6 | var glob = require('glob'); 7 | var extend = require('extend'); 8 | var logSymbols = require('log-symbols'); 9 | 10 | var data, parsedCode, checker, parser; 11 | 12 | module.exports = function (config) { 13 | extend(config, { 14 | files: config.files || [], 15 | write: config.write || false, 16 | jscs: config.jscs, 17 | parser: config.parser || 'ast', 18 | preset: config.preset || 'jquery', 19 | parserConfig: config.parserConfig || {} 20 | }); 21 | 22 | if (typeof config.jscs === 'undefined') { 23 | config.jscs = true; 24 | } 25 | 26 | try { 27 | parser = require('./' + config.parser); 28 | } catch (e) { 29 | console.log(logSymbols.error + ' ' + 30 | chalk.bold.red('Failed to load parser: %s'), config.parser); 31 | console.log(logSymbols.info, 32 | chalk.bold.yellow('Info: Parser should be either ast/regex')); 33 | console.log(e.toString()); 34 | exit(); 35 | } 36 | 37 | if (config.files.length === 0) { 38 | console.log(logSymbols.error, chalk.bold.red('No files passed!')); 39 | console.log(logSymbols.info, chalk.bold.yellow('Use -h for help')); 40 | exit(); 41 | } 42 | 43 | if (config.jscs) { 44 | checker = new Checker(); 45 | var jscsConfig = config.jscsConfig || {}; 46 | extend(jscsConfig, { 47 | preset: config.preset, 48 | fix: true 49 | }); 50 | 51 | checker.registerDefaultRules(); 52 | checker.configure(jscsConfig); 53 | } 54 | 55 | if (!Array.isArray(config.files)) { 56 | config.files = [config.files]; 57 | } 58 | console.log(config.files[0]); 59 | if (config.files.length != 1) { 60 | parseFiles(null, config.files); 61 | } else { 62 | glob(config.files[0], parseFiles); 63 | } 64 | 65 | 66 | function parseFiles(error, files) { 67 | console.log(files); 68 | if (error) { 69 | console.log(logSymbols.error, chalk.bold.red('Error in Globbing pattern!')); 70 | console.log(error.toString()); 71 | exit(); 72 | } 73 | 74 | var errors = [], passed = []; 75 | 76 | files.forEach(function (file) { 77 | try { 78 | data = fs.readFileSync(file); 79 | parsedCode = parser(data, config); 80 | 81 | if (config.jscs) { 82 | parsedCode = checker.fixString(parsedCode); 83 | parsedCode = parsedCode.output; 84 | } 85 | 86 | if (config.write) { 87 | fs.writeFileSync(file, parsedCode); 88 | } else { 89 | console.log(logSymbols.success + 90 | ' ' + chalk.bold.green('Output for %s:\n'), file); 91 | console.log(parsedCode); 92 | } 93 | 94 | passed.push(file); 95 | } catch (e) { 96 | console.log(logSymbols.error + ' ' + 97 | chalk.bold.red('Error occured while fixing file: %s'), file); 98 | 99 | console.log(e.toString()); 100 | errors.push(file); 101 | } 102 | }); 103 | 104 | if (errors.length) { 105 | console.log(chalk.bold.red('Following files were not converted:')); 106 | errors.forEach(function (error) { 107 | console.log(logSymbols.error, chalk.red(error)); 108 | }); 109 | } 110 | 111 | if (passed.length) { 112 | console.log(chalk.bold.green('Following files were successfully converted:')); 113 | passed.forEach(function (pass) { 114 | console.log(logSymbols.success, chalk.green(pass)); 115 | }); 116 | } 117 | } 118 | }; 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QUnit Migrate 2 | [![NPM Version](https://img.shields.io/npm/v/qunit-migrate.svg?style=flat)](https://www.npmjs.com/package/qunit-migrate) 3 | [![Build Status](https://travis-ci.org/apsdehal/qunit-migrate.svg?branch=master)](https://travis-ci.org/apsdehal/qunit-migrate) 4 | 5 | Migrate old QUnit code to 2.x. 6 | 7 | ## Features 8 | 9 | - JSCS support 10 | - Custom config support for defining rules 11 | - Supports conversion of Async tests 12 | - Support for globbing patterns 13 | - Both regex and ast parser supported 14 | 15 | ## Install 16 | 17 | > npm install --global qunit-migrate 18 | 19 | ## Usage 20 | 21 | ``` 22 | qunit-migrate -h 23 | 24 | Usage: qunit-migrate [options] 25 | 26 | QUnit Migrate: A tool to migrate your files to QUnit 2.0 API 27 | 28 | Options: 29 | 30 | -h, --help output usage information 31 | -V, --version output the version number 32 | -c, --config Config file for qunit-migrate 33 | -P, --parser Parser to be used for parsing, Default: ast 34 | -w, --write Pass if parsed files should be overwritten. Default: false 35 | -p, --preset Preset rule for jscs config. Default: jquery 36 | -j, --no-jscs Pass if jscs fix should not be applied. Default: true 37 | 38 | Globbing is supported in files 39 | 40 | Examples: 41 | 42 | $ qunit-migrate "./**/*.js" -w --preset "google" -c "config.json" 43 | $ # This will migrate all js files in subdirectories using google 44 | $ # preset and config as config.json 45 | ``` 46 | 47 | *Information: AST parser is more robust than regex parser* 48 | 49 | 50 | ## Configuration 51 | 52 | Various rules can be toggled through use of custom config which can be passed via `-c` option. 53 | 54 | [Default config file](examples/default.config.json) 55 | 56 | [Sample config file](examples/sample.config.json) 57 | 58 | [Config Rules](examples/rules.md) 59 | 60 | ## Example: 61 | 62 | qunit-migrate tries to change old QUnit code to new QUnit specifications. 63 | 64 | For e.g. following code will be converted as follows: 65 | 66 | ```js 67 | // Taken directly from jquery-globalize 68 | // file1.js 69 | define([ 70 | "cldr", 71 | "src/core", 72 | "json!cldr-data/supplemental/likelySubtags.json", 73 | "cldr/event" 74 | ], function( Cldr, Globalize, likelySubtags ) { 75 | Cldr.load( likelySubtags ); 76 | module( "Globalize.locale" ); 77 | ssyncTest( "should allow String locale", function() { 78 | stop(); 79 | Globalize.locale( "en" ); 80 | ok( Globalize.cldr instanceof Cldr ); 81 | equal( Globalize.cldr.locale, "en" ); 82 | start(); 83 | }); 84 | }); 85 | ``` 86 | > $ qunit-migrate "file1.js" -w 87 | 88 | to 89 | 90 | ```js 91 | // Taken directly from jquery-globalize 92 | // file1.js 93 | define( [ 94 | "qunit", 95 | "cldr", 96 | "src/core", 97 | "json!cldr-data/supplemental/likelySubtags.json", 98 | "cldr/event" 99 | ], function( QUnit, Cldr, Globalize, likelySubtags ) { 100 | Cldr.load( likelySubtags ); 101 | QUnit.module( "Globalize.locale" ); 102 | QUnit.test( "should allow String locale", function( assert ) { 103 | var ready = assert.async(); 104 | Globalize.locale( "en" ); 105 | assert.ok( Globalize.cldr instanceof Cldr ); 106 | assert.equal( Globalize.cldr.locale, "en" ); 107 | ready(); 108 | }); 109 | }); 110 | ``` 111 | 112 | ## API 113 | > $ npm install --save qunit-migrate 114 | 115 | ```js 116 | var qunitMigrate = require('qunit-migrate'); 117 | var qmAst = qunitMigrate.ast; 118 | var qmRegex = qunitMigrate.regex; 119 | var data = 'Some old qunit code'; 120 | 121 | var modifiedDataAST = qmAst(data); // Fixed code through AST 122 | var modifiedDataRegex = qmRegex(data); // Fixed code through AST 123 | ``` 124 | 125 | *Information: `qunit-migrate` api doesn't fix source with jscs* 126 | 127 | ## Accuracy & Limitations 128 | 129 | QUnit migrate tries its best to upgrade your API, but there are still some limitations. 130 | 131 | For e.g. 132 | - If you are encapsulating some of your logic in a function and using assertions in that, it is 133 | your responsibility to pass assert into function parameters. API of qunit-migrate can also be upgraded to do this, but it doesn't support it at the moment 134 | - There might be issues with require definitions some time if they are not in the start and encapsulated somewhere. 135 | - QUnit.reset is not supported as of now 136 | 137 | *All these are fixable through AST. _Pull requests_ are welcome* 138 | 139 | ## License 140 | 141 | MIT © [Amanpreet Singh](https://apsdehal.in) 142 | -------------------------------------------------------------------------------- /tests/data/8/actual.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | ( function( $ ) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | module( libName, { 16 | setup: function() { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | teardown: function() { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | asyncTest( "grade A browser either supports media queries or is IE 7+", function() { 32 | setGradeA( false, 6 ); 33 | $.testHelper.deferredSequence( [ 34 | function() { 35 | return $.testHelper.reloadModule( libName ); 36 | }, 37 | 38 | function() { 39 | ok( !$.mobile.gradeA() ); 40 | }, 41 | 42 | function() { 43 | setGradeA( true, 8 ); 44 | return $.testHelper.reloadModule( libName ); 45 | }, 46 | 47 | function() { 48 | ok( $.mobile.gradeA() ); 49 | start(); 50 | } 51 | ] ); 52 | } ); 53 | } ); 54 | 55 | function clearNSNormalizeDictionary() { 56 | var dict = $.mobile.nsNormalizeDict; 57 | for ( var prop in dict ) { 58 | delete dict[ prop ]; 59 | } 60 | } 61 | 62 | test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function() { 63 | // Start with a fresh namespace property cache, just in case 64 | // the previous test mucked with namespaces. 65 | clearNSNormalizeDictionary(); 66 | 67 | equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 68 | equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 69 | equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 70 | equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 71 | 72 | // Reset the namespace property cache for the next test. 73 | clearNSNormalizeDictionary(); 74 | } ); 75 | 76 | test( "$.mobile.nsNormalize works properly with an empty namespace", function() { 77 | var realNs = $.mobile.ns; 78 | 79 | $.mobile.ns = ""; 80 | 81 | // Start with a fresh namespace property cache, just in case 82 | // the previous test mucked with namespaces. 83 | clearNSNormalizeDictionary(); 84 | 85 | equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 86 | equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 87 | equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 88 | equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 89 | 90 | $.mobile.ns = realNs; 91 | 92 | // Reset the namespace property cache for the next test. 93 | clearNSNormalizeDictionary(); 94 | } ); 95 | 96 | //data tests 97 | test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function() { 98 | var data; 99 | 100 | deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 101 | 102 | deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 103 | 104 | deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 105 | 106 | deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 107 | 108 | data = $.extend( {}, $( "body" ).data() ); 109 | delete data[ $.expando ]; //discard the expando for that test 110 | deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 111 | 112 | deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 113 | 114 | deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 115 | 116 | deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 117 | 118 | deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 119 | 120 | deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 121 | 122 | } ); 123 | 124 | 125 | test( "$.jqmData and $.jqmRemoveData methods are working properly", function() { 126 | deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 127 | 128 | deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 129 | 130 | deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 131 | 132 | deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 133 | 134 | deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 135 | 136 | deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 137 | 138 | deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 139 | 140 | deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 141 | 142 | deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 143 | 144 | } ); 145 | 146 | test( "addDependents works properly", function() { 147 | deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 148 | $( "#parent" ).addDependents( $( "#dependent" ) ); 149 | deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 150 | } ); 151 | 152 | test( "removeWithDependents removes the parent element and ", function() { 153 | $( "#parent" ).addDependents( $( "#dependent" ) ); 154 | deepEqual( $( "#parent, #dependent" ).length, 2 ); 155 | $( "#parent" ).removeWithDependents(); 156 | deepEqual( $( "#parent, #dependent" ).length, 0 ); 157 | } ); 158 | 159 | test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function() { 160 | deepEqual( $( "#encoded" ).text(), "foo>" ); 161 | deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 162 | deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 163 | } ); 164 | 165 | test( "closestPageData returns the parent's page data", function() { 166 | var pageChild = $( "#page-child" ); 167 | 168 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 169 | deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 170 | } ); 171 | 172 | test( "closestPageData returns the parent dialog's page data", function() { 173 | var dialogChild = $( "#dialog-child" ); 174 | 175 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 176 | deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 177 | } ); 178 | 179 | test( "test that $.fn.jqmHijackable works", function() { 180 | $.mobile.ignoreContentEnabled = true; 181 | 182 | deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 183 | "a link without any association to data-ajax=false should be included" ); 184 | 185 | deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 186 | "a link with a data-ajax=false parent should be excluded" ); 187 | 188 | deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 189 | "a link with data-ajax=false should be excluded" ); 190 | 191 | $.mobile.ignoreContentEnabled = false; 192 | } ); 193 | } )( jQuery ); 194 | -------------------------------------------------------------------------------- /tests/data/9/actual.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | ( function( $ ) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | module( libName, { 16 | setup: function() { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | teardown: function() { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | asyncTest( "grade A browser either supports media queries or is IE 7+", function() { 32 | setGradeA( false, 6 ); 33 | $.testHelper.deferredSequence( [ 34 | function() { 35 | return $.testHelper.reloadModule( libName ); 36 | }, 37 | 38 | function() { 39 | ok( !$.mobile.gradeA() ); 40 | }, 41 | 42 | function() { 43 | setGradeA( true, 8 ); 44 | return $.testHelper.reloadModule( libName ); 45 | }, 46 | 47 | function() { 48 | ok( $.mobile.gradeA() ); 49 | start(); 50 | } 51 | ] ); 52 | } ); 53 | } ); 54 | 55 | function clearNSNormalizeDictionary() { 56 | var dict = $.mobile.nsNormalizeDict; 57 | for ( var prop in dict ) { 58 | delete dict[ prop ]; 59 | } 60 | } 61 | 62 | test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function() { 63 | // Start with a fresh namespace property cache, just in case 64 | // the previous test mucked with namespaces. 65 | clearNSNormalizeDictionary(); 66 | 67 | equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 68 | equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 69 | equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 70 | equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 71 | 72 | // Reset the namespace property cache for the next test. 73 | clearNSNormalizeDictionary(); 74 | } ); 75 | 76 | test( "$.mobile.nsNormalize works properly with an empty namespace", function() { 77 | var realNs = $.mobile.ns; 78 | 79 | $.mobile.ns = ""; 80 | 81 | // Start with a fresh namespace property cache, just in case 82 | // the previous test mucked with namespaces. 83 | clearNSNormalizeDictionary(); 84 | 85 | equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 86 | equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 87 | equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 88 | equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 89 | 90 | $.mobile.ns = realNs; 91 | 92 | // Reset the namespace property cache for the next test. 93 | clearNSNormalizeDictionary(); 94 | } ); 95 | 96 | //data tests 97 | test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function() { 98 | var data; 99 | 100 | deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 101 | 102 | deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 103 | 104 | deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 105 | 106 | deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 107 | 108 | data = $.extend( {}, $( "body" ).data() ); 109 | delete data[ $.expando ]; //discard the expando for that test 110 | deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 111 | 112 | deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 113 | 114 | deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 115 | 116 | deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 117 | 118 | deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 119 | 120 | deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 121 | 122 | } ); 123 | 124 | 125 | test( "$.jqmData and $.jqmRemoveData methods are working properly", function() { 126 | deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 127 | 128 | deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 129 | 130 | deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 131 | 132 | deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 133 | 134 | deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 135 | 136 | deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 137 | 138 | deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 139 | 140 | deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 141 | 142 | deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 143 | 144 | } ); 145 | 146 | test( "addDependents works properly", function() { 147 | deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 148 | $( "#parent" ).addDependents( $( "#dependent" ) ); 149 | deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 150 | } ); 151 | 152 | test( "removeWithDependents removes the parent element and ", function() { 153 | $( "#parent" ).addDependents( $( "#dependent" ) ); 154 | deepEqual( $( "#parent, #dependent" ).length, 2 ); 155 | $( "#parent" ).removeWithDependents(); 156 | deepEqual( $( "#parent, #dependent" ).length, 0 ); 157 | } ); 158 | 159 | test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function() { 160 | deepEqual( $( "#encoded" ).text(), "foo>" ); 161 | deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 162 | deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 163 | } ); 164 | 165 | test( "closestPageData returns the parent's page data", function() { 166 | var pageChild = $( "#page-child" ); 167 | 168 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 169 | deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 170 | } ); 171 | 172 | test( "closestPageData returns the parent dialog's page data", function() { 173 | var dialogChild = $( "#dialog-child" ); 174 | 175 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 176 | deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 177 | } ); 178 | 179 | test( "test that $.fn.jqmHijackable works", function() { 180 | $.mobile.ignoreContentEnabled = true; 181 | 182 | deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 183 | "a link without any association to data-ajax=false should be included" ); 184 | 185 | deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 186 | "a link with a data-ajax=false parent should be excluded" ); 187 | 188 | deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 189 | "a link with data-ajax=false should be excluded" ); 190 | 191 | $.mobile.ignoreContentEnabled = false; 192 | } ); 193 | } )( jQuery ); 194 | -------------------------------------------------------------------------------- /tests/data/8/expected-regex.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | ( function( $ ) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | QUnit.module( libName, { 16 | setup: function() { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | teardown: function() { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | QUnit.test( "grade A browser either supports media queries or is IE 7+", function( assert ) { 32 | var done = assert.async(); 33 | setGradeA( false, 6 ); 34 | $.testHelper.deferredSequence( [ 35 | function() { 36 | return $.testHelper.reloadModule( libName ); 37 | }, 38 | 39 | function() { 40 | assert.ok( !$.mobile.gradeA() ); 41 | }, 42 | 43 | function() { 44 | setGradeA( true, 8 ); 45 | return $.testHelper.reloadModule( libName ); 46 | }, 47 | 48 | function() { 49 | assert.ok( $.mobile.gradeA() ); 50 | done(); 51 | } 52 | ] ); 53 | } ); 54 | } ); 55 | 56 | function clearNSNormalizeDictionary() { 57 | var dict = $.mobile.nsNormalizeDict; 58 | for ( var prop in dict ) { 59 | delete dict[ prop ]; 60 | } 61 | } 62 | 63 | QUnit.test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function( assert ) { 64 | // Start with a fresh namespace property cache, just in case 65 | // the previous test mucked with namespaces. 66 | clearNSNormalizeDictionary(); 67 | 68 | assert.equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 69 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 70 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 71 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 72 | 73 | // Reset the namespace property cache for the next test. 74 | clearNSNormalizeDictionary(); 75 | } ); 76 | 77 | QUnit.test( "$.mobile.nsNormalize works properly with an empty namespace", function( assert ) { 78 | var realNs = $.mobile.ns; 79 | 80 | $.mobile.ns = ""; 81 | 82 | // Start with a fresh namespace property cache, just in case 83 | // the previous test mucked with namespaces. 84 | clearNSNormalizeDictionary(); 85 | 86 | assert.equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 87 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 88 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 89 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 90 | 91 | $.mobile.ns = realNs; 92 | 93 | // Reset the namespace property cache for the next test. 94 | clearNSNormalizeDictionary(); 95 | } ); 96 | 97 | //data tests 98 | QUnit.test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function( assert ) { 99 | var data; 100 | 101 | assert.deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 102 | 103 | assert.deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 104 | 105 | assert.deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 106 | 107 | assert.deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 108 | 109 | data = $.extend( {}, $( "body" ).data() ); 110 | delete data[ $.expando ]; //discard the expando for that test 111 | assert.deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 112 | 113 | assert.deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 114 | 115 | assert.deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 116 | 117 | assert.deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 118 | 119 | assert.deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 120 | 121 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 122 | 123 | } ); 124 | 125 | 126 | QUnit.test( "$.jqmData and $.jqmRemoveData methods are working properly", function( assert ) { 127 | assert.deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 128 | 129 | assert.deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 130 | 131 | assert.deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 132 | 133 | assert.deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 134 | 135 | assert.deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 136 | 137 | assert.deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 138 | 139 | assert.deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 140 | 141 | assert.deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 142 | 143 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 144 | 145 | } ); 146 | 147 | QUnit.test( "addDependents works properly", function( assert ) { 148 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 149 | $( "#parent" ).addDependents( $( "#dependent" ) ); 150 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 151 | } ); 152 | 153 | QUnit.test( "removeWithDependents removes the parent element and ", function( assert ) { 154 | $( "#parent" ).addDependents( $( "#dependent" ) ); 155 | assert.deepEqual( $( "#parent, #dependent" ).length, 2 ); 156 | $( "#parent" ).removeWithDependents(); 157 | assert.deepEqual( $( "#parent, #dependent" ).length, 0 ); 158 | } ); 159 | 160 | QUnit.test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function( assert ) { 161 | assert.deepEqual( $( "#encoded" ).text(), "foo>" ); 162 | assert.deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 163 | assert.deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 164 | } ); 165 | 166 | QUnit.test( "closestPageData returns the parent's page data", function( assert ) { 167 | var pageChild = $( "#page-child" ); 168 | 169 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 170 | assert.deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 171 | } ); 172 | 173 | QUnit.test( "closestPageData returns the parent dialog's page data", function( assert ) { 174 | var dialogChild = $( "#dialog-child" ); 175 | 176 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 177 | assert.deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 178 | } ); 179 | 180 | QUnit.test( "test that $.fn.jqmHijackable works", function( assert ) { 181 | $.mobile.ignoreContentEnabled = true; 182 | 183 | assert.deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 184 | "a link without any association to data-ajax=false should be included" ); 185 | 186 | assert.deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 187 | "a link with a data-ajax=false parent should be excluded" ); 188 | 189 | assert.deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 190 | "a link with data-ajax=false should be excluded" ); 191 | 192 | $.mobile.ignoreContentEnabled = false; 193 | } ); 194 | } )( jQuery ); 195 | -------------------------------------------------------------------------------- /tests/data/9/expected-regex.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | ( function( QUnit, $ ) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | QUnit.module( libName, { 16 | setup: function() { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | teardown: function() { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | QUnit.test( "grade A browser either supports media queries or is IE 7+", function( assert ) { 32 | var done = assert.async(); 33 | setGradeA( false, 6 ); 34 | $.testHelper.deferredSequence( [ 35 | function() { 36 | return $.testHelper.reloadModule( libName ); 37 | }, 38 | 39 | function() { 40 | assert.ok( !$.mobile.gradeA() ); 41 | }, 42 | 43 | function() { 44 | setGradeA( true, 8 ); 45 | return $.testHelper.reloadModule( libName ); 46 | }, 47 | 48 | function() { 49 | assert.ok( $.mobile.gradeA() ); 50 | done(); 51 | } 52 | ] ); 53 | } ); 54 | } ); 55 | 56 | function clearNSNormalizeDictionary() { 57 | var dict = $.mobile.nsNormalizeDict; 58 | for ( var prop in dict ) { 59 | delete dict[ prop ]; 60 | } 61 | } 62 | 63 | QUnit.test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function( assert ) { 64 | // Start with a fresh namespace property cache, just in case 65 | // the previous test mucked with namespaces. 66 | clearNSNormalizeDictionary(); 67 | 68 | assert.equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 69 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 70 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 71 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 72 | 73 | // Reset the namespace property cache for the next test. 74 | clearNSNormalizeDictionary(); 75 | } ); 76 | 77 | QUnit.test( "$.mobile.nsNormalize works properly with an empty namespace", function( assert ) { 78 | var realNs = $.mobile.ns; 79 | 80 | $.mobile.ns = ""; 81 | 82 | // Start with a fresh namespace property cache, just in case 83 | // the previous test mucked with namespaces. 84 | clearNSNormalizeDictionary(); 85 | 86 | assert.equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 87 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 88 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 89 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 90 | 91 | $.mobile.ns = realNs; 92 | 93 | // Reset the namespace property cache for the next test. 94 | clearNSNormalizeDictionary(); 95 | } ); 96 | 97 | //data tests 98 | QUnit.test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function( assert ) { 99 | var data; 100 | 101 | assert.deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 102 | 103 | assert.deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 104 | 105 | assert.deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 106 | 107 | assert.deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 108 | 109 | data = $.extend( {}, $( "body" ).data() ); 110 | delete data[ $.expando ]; //discard the expando for that test 111 | assert.deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 112 | 113 | assert.deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 114 | 115 | assert.deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 116 | 117 | assert.deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 118 | 119 | assert.deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 120 | 121 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 122 | 123 | } ); 124 | 125 | 126 | QUnit.test( "$.jqmData and $.jqmRemoveData methods are working properly", function( assert ) { 127 | assert.deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 128 | 129 | assert.deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 130 | 131 | assert.deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 132 | 133 | assert.deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 134 | 135 | assert.deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 136 | 137 | assert.deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 138 | 139 | assert.deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 140 | 141 | assert.deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 142 | 143 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 144 | 145 | } ); 146 | 147 | QUnit.test( "addDependents works properly", function( assert ) { 148 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 149 | $( "#parent" ).addDependents( $( "#dependent" ) ); 150 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 151 | } ); 152 | 153 | QUnit.test( "removeWithDependents removes the parent element and ", function( assert ) { 154 | $( "#parent" ).addDependents( $( "#dependent" ) ); 155 | assert.deepEqual( $( "#parent, #dependent" ).length, 2 ); 156 | $( "#parent" ).removeWithDependents(); 157 | assert.deepEqual( $( "#parent, #dependent" ).length, 0 ); 158 | } ); 159 | 160 | QUnit.test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function( assert ) { 161 | assert.deepEqual( $( "#encoded" ).text(), "foo>" ); 162 | assert.deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 163 | assert.deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 164 | } ); 165 | 166 | QUnit.test( "closestPageData returns the parent's page data", function( assert ) { 167 | var pageChild = $( "#page-child" ); 168 | 169 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 170 | assert.deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 171 | } ); 172 | 173 | QUnit.test( "closestPageData returns the parent dialog's page data", function( assert ) { 174 | var dialogChild = $( "#dialog-child" ); 175 | 176 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 177 | assert.deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 178 | } ); 179 | 180 | QUnit.test( "test that $.fn.jqmHijackable works", function( assert ) { 181 | $.mobile.ignoreContentEnabled = true; 182 | 183 | assert.deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 184 | "a link without any association to data-ajax=false should be included" ); 185 | 186 | assert.deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 187 | "a link with a data-ajax=false parent should be excluded" ); 188 | 189 | assert.deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 190 | "a link with data-ajax=false should be excluded" ); 191 | 192 | $.mobile.ignoreContentEnabled = false; 193 | } ); 194 | } )( QUnit, jQuery ); 195 | -------------------------------------------------------------------------------- /tests/data/8/expected-ast.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | (function(QUnit, $) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | QUnit.module( libName, { 16 | beforeEach: function(assert) { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | afterEach: function(assert) { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | QUnit.test( "grade A browser either supports media queries or is IE 7+", function(assert) { 32 | var ready = assert.async(); 33 | setGradeA( false, 6 ); 34 | $.testHelper.deferredSequence( [ 35 | function() { 36 | return $.testHelper.reloadModule( libName ); 37 | }, 38 | 39 | function() { 40 | assert.ok( !$.mobile.gradeA() ); 41 | }, 42 | 43 | function() { 44 | setGradeA( true, 8 ); 45 | return $.testHelper.reloadModule( libName ); 46 | }, 47 | 48 | function() { 49 | assert.ok( $.mobile.gradeA() ); 50 | ready(); 51 | } 52 | ] ); 53 | } ); 54 | } ); 55 | 56 | function clearNSNormalizeDictionary() { 57 | var dict = $.mobile.nsNormalizeDict; 58 | for ( var prop in dict ) { 59 | delete dict[ prop ]; 60 | } 61 | } 62 | 63 | QUnit.test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function(assert) { 64 | // Start with a fresh namespace property cache, just in case 65 | // the previous test mucked with namespaces. 66 | clearNSNormalizeDictionary(); 67 | 68 | assert.equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 69 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 70 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 71 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 72 | 73 | // Reset the namespace property cache for the next test. 74 | clearNSNormalizeDictionary(); 75 | } ); 76 | 77 | QUnit.test( "$.mobile.nsNormalize works properly with an empty namespace", function(assert) { 78 | var realNs = $.mobile.ns; 79 | 80 | $.mobile.ns = ""; 81 | 82 | // Start with a fresh namespace property cache, just in case 83 | // the previous test mucked with namespaces. 84 | clearNSNormalizeDictionary(); 85 | 86 | assert.equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 87 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 88 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 89 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 90 | 91 | $.mobile.ns = realNs; 92 | 93 | // Reset the namespace property cache for the next test. 94 | clearNSNormalizeDictionary(); 95 | } ); 96 | 97 | //data tests 98 | QUnit.test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function(assert) { 99 | var data; 100 | 101 | assert.deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 102 | 103 | assert.deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 104 | 105 | assert.deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 106 | 107 | assert.deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 108 | 109 | data = $.extend( {}, $( "body" ).data() ); 110 | delete data[ $.expando ]; //discard the expando for that test 111 | assert.deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 112 | 113 | assert.deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 114 | 115 | assert.deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 116 | 117 | assert.deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 118 | 119 | assert.deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 120 | 121 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 122 | 123 | } ); 124 | 125 | 126 | QUnit.test( "$.jqmData and $.jqmRemoveData methods are working properly", function(assert) { 127 | assert.deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 128 | 129 | assert.deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 130 | 131 | assert.deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 132 | 133 | assert.deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 134 | 135 | assert.deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 136 | 137 | assert.deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 138 | 139 | assert.deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 140 | 141 | assert.deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 142 | 143 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 144 | 145 | } ); 146 | 147 | QUnit.test( "addDependents works properly", function(assert) { 148 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 149 | $( "#parent" ).addDependents( $( "#dependent" ) ); 150 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 151 | } ); 152 | 153 | QUnit.test( "removeWithDependents removes the parent element and ", function(assert) { 154 | $( "#parent" ).addDependents( $( "#dependent" ) ); 155 | assert.deepEqual( $( "#parent, #dependent" ).length, 2 ); 156 | $( "#parent" ).removeWithDependents(); 157 | assert.deepEqual( $( "#parent, #dependent" ).length, 0 ); 158 | } ); 159 | 160 | QUnit.test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function(assert) { 161 | assert.deepEqual( $( "#encoded" ).text(), "foo>" ); 162 | assert.deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 163 | assert.deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 164 | } ); 165 | 166 | QUnit.test( "closestPageData returns the parent's page data", function(assert) { 167 | var pageChild = $( "#page-child" ); 168 | 169 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 170 | assert.deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 171 | } ); 172 | 173 | QUnit.test( "closestPageData returns the parent dialog's page data", function(assert) { 174 | var dialogChild = $( "#dialog-child" ); 175 | 176 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 177 | assert.deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 178 | } ); 179 | 180 | QUnit.test( "test that $.fn.jqmHijackable works", function(assert) { 181 | $.mobile.ignoreContentEnabled = true; 182 | 183 | assert.deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 184 | "a link without any association to data-ajax=false should be included" ); 185 | 186 | assert.deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 187 | "a link with a data-ajax=false parent should be excluded" ); 188 | 189 | assert.deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 190 | "a link with data-ajax=false should be excluded" ); 191 | 192 | $.mobile.ignoreContentEnabled = false; 193 | } ); 194 | })(QUnit, jQuery); 195 | -------------------------------------------------------------------------------- /tests/data/9/expected-ast.js: -------------------------------------------------------------------------------- 1 | /* 2 | * mobile core unit tests 3 | * Taken directly from jquery-mobile 4 | */ 5 | 6 | (function(QUnit, $) { 7 | var libName = "core", 8 | setGradeA = function( value, version ) { 9 | $.support.mediaquery = value; 10 | $.mobile.browser.ie = version; 11 | }, 12 | extendFn = $.extend, 13 | ns = $.mobile.ns; 14 | 15 | QUnit.module( libName, { 16 | beforeEach: function(assert) { 17 | $.mobile.ns = ns; 18 | 19 | // NOTE reset for gradeA tests 20 | $( 'html' ).removeClass( 'ui-mobile' ); 21 | 22 | // NOTE reset for pageLoading tests 23 | $( '.ui-loader' ).remove(); 24 | }, 25 | afterEach: function(assert) { 26 | $.extend = extendFn; 27 | } 28 | } ); 29 | 30 | $.testHelper.excludeFileProtocol( function() { 31 | QUnit.test( "grade A browser either supports media queries or is IE 7+", function(assert) { 32 | var ready = assert.async(); 33 | setGradeA( false, 6 ); 34 | $.testHelper.deferredSequence( [ 35 | function() { 36 | return $.testHelper.reloadModule( libName ); 37 | }, 38 | 39 | function() { 40 | assert.ok( !$.mobile.gradeA() ); 41 | }, 42 | 43 | function() { 44 | setGradeA( true, 8 ); 45 | return $.testHelper.reloadModule( libName ); 46 | }, 47 | 48 | function() { 49 | assert.ok( $.mobile.gradeA() ); 50 | ready(); 51 | } 52 | ] ); 53 | } ); 54 | } ); 55 | 56 | function clearNSNormalizeDictionary() { 57 | var dict = $.mobile.nsNormalizeDict; 58 | for ( var prop in dict ) { 59 | delete dict[ prop ]; 60 | } 61 | } 62 | 63 | QUnit.test( "$.mobile.nsNormalize works properly with namespace defined (test default)", function(assert) { 64 | // Start with a fresh namespace property cache, just in case 65 | // the previous test mucked with namespaces. 66 | clearNSNormalizeDictionary(); 67 | 68 | assert.equal( $.mobile.nsNormalize( "foo" ), "nstestFoo", "appends ns and initcaps" ); 69 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "nstestFooBar", "leaves capped strings intact" ); 70 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "nstestFooBar", "changes dashed strings" ); 71 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "nstestFooBarBak", "changes multiple dashed strings" ); 72 | 73 | // Reset the namespace property cache for the next test. 74 | clearNSNormalizeDictionary(); 75 | } ); 76 | 77 | QUnit.test( "$.mobile.nsNormalize works properly with an empty namespace", function(assert) { 78 | var realNs = $.mobile.ns; 79 | 80 | $.mobile.ns = ""; 81 | 82 | // Start with a fresh namespace property cache, just in case 83 | // the previous test mucked with namespaces. 84 | clearNSNormalizeDictionary(); 85 | 86 | assert.equal( $.mobile.nsNormalize( "foo" ), "foo", "leaves uncapped and undashed" ); 87 | assert.equal( $.mobile.nsNormalize( "fooBar" ), "fooBar", "leaves capped strings intact" ); 88 | assert.equal( $.mobile.nsNormalize( "foo-bar" ), "fooBar", "changes dashed strings" ); 89 | assert.equal( $.mobile.nsNormalize( "foo-bar-bak" ), "fooBarBak", "changes multiple dashed strings" ); 90 | 91 | $.mobile.ns = realNs; 92 | 93 | // Reset the namespace property cache for the next test. 94 | clearNSNormalizeDictionary(); 95 | } ); 96 | 97 | //data tests 98 | QUnit.test( "$.fn.jqmData and $.fn.jqmRemoveData methods are working properly", function(assert) { 99 | var data; 100 | 101 | assert.deepEqual( $( "body" ).jqmData( "foo", true ), $( "body" ), "setting data returns the element" ); 102 | 103 | assert.deepEqual( $( "body" ).jqmData( "foo" ), true, "getting data returns the right value" ); 104 | 105 | assert.deepEqual( $( "body" ).data( $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 106 | 107 | assert.deepEqual( $( "body" ).jqmData( "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 108 | 109 | data = $.extend( {}, $( "body" ).data() ); 110 | delete data[ $.expando ]; //discard the expando for that test 111 | assert.deepEqual( data.nstestFoo, true, "passing .data() no arguments returns a hash with all set properties" ); 112 | 113 | assert.deepEqual( $( "body" ).jqmData(), undefined, "passing no arguments returns undefined" ); 114 | 115 | assert.deepEqual( $( "body" ).jqmData( undefined ), undefined, "passing a single undefined argument returns undefined" ); 116 | 117 | assert.deepEqual( $( "body" ).jqmData( undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 118 | 119 | assert.deepEqual( $( "body" ).jqmRemoveData( "foo" ), $( "body" ), "jqmRemoveData returns the element" ); 120 | 121 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 122 | 123 | } ); 124 | 125 | 126 | QUnit.test( "$.jqmData and $.jqmRemoveData methods are working properly", function(assert) { 127 | assert.deepEqual( $.jqmData( document.body, "foo", true ), true, "setting data returns the value" ); 128 | 129 | assert.deepEqual( $.jqmData( document.body, "foo" ), true, "getting data returns the right value" ); 130 | 131 | assert.deepEqual( $.data( document.body, $.mobile.nsNormalize( "foo" ) ), true, "data was set using namespace" ); 132 | 133 | assert.deepEqual( $.jqmData( document.body, "foo", undefined ), true, "getting data still returns the value if there's an undefined second arg" ); 134 | 135 | assert.deepEqual( $.jqmData( document.body ), undefined, "passing no arguments returns undefined" ); 136 | 137 | assert.deepEqual( $.jqmData( document.body, undefined ), undefined, "passing a single undefined argument returns undefined" ); 138 | 139 | assert.deepEqual( $.jqmData( document.body, undefined, undefined ), undefined, "passing 2 undefined arguments returns undefined" ); 140 | 141 | assert.deepEqual( $.jqmRemoveData( document.body, "foo" ), undefined, "jqmRemoveData returns the undefined value" ); 142 | 143 | assert.deepEqual( $( "body" ).jqmData( "foo" ), undefined, "jqmRemoveData properly removes namespaced data" ); 144 | 145 | } ); 146 | 147 | QUnit.test( "addDependents works properly", function(assert) { 148 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ), undefined ); 149 | $( "#parent" ).addDependents( $( "#dependent" ) ); 150 | assert.deepEqual( $( "#parent" ).jqmData( 'dependents' ).length, 1 ); 151 | } ); 152 | 153 | QUnit.test( "removeWithDependents removes the parent element and ", function(assert) { 154 | $( "#parent" ).addDependents( $( "#dependent" ) ); 155 | assert.deepEqual( $( "#parent, #dependent" ).length, 2 ); 156 | $( "#parent" ).removeWithDependents(); 157 | assert.deepEqual( $( "#parent, #dependent" ).length, 0 ); 158 | } ); 159 | 160 | QUnit.test( "$.fn.getEncodedText should return the encoded value where $.fn.text doesn't", function(assert) { 161 | assert.deepEqual( $( "#encoded" ).text(), "foo>" ); 162 | assert.deepEqual( $( "#encoded" ).getEncodedText(), "foo>" ); 163 | assert.deepEqual( $( "#unencoded" ).getEncodedText(), "var foo;" ); 164 | } ); 165 | 166 | QUnit.test( "closestPageData returns the parent's page data", function(assert) { 167 | var pageChild = $( "#page-child" ); 168 | 169 | $( "#parent-page" ).data( "mobile-page", { foo: "bar" } ); 170 | assert.deepEqual( $.mobile.closestPageData( pageChild ).foo, "bar" ); 171 | } ); 172 | 173 | QUnit.test( "closestPageData returns the parent dialog's page data", function(assert) { 174 | var dialogChild = $( "#dialog-child" ); 175 | 176 | $( "#parent-dialog" ).data( "mobile-page", { foo: "bar" } ); 177 | assert.deepEqual( $.mobile.closestPageData( dialogChild ).foo, "bar" ); 178 | } ); 179 | 180 | QUnit.test( "test that $.fn.jqmHijackable works", function(assert) { 181 | $.mobile.ignoreContentEnabled = true; 182 | 183 | assert.deepEqual( $( "#hijacked-link" ).jqmHijackable().length, 1, 184 | "a link without any association to data-ajax=false should be included" ); 185 | 186 | assert.deepEqual( $( "#unhijacked-link-by-parent" ).jqmHijackable().length, 0, 187 | "a link with a data-ajax=false parent should be excluded" ); 188 | 189 | assert.deepEqual( $( "#unhijacked-link-by-attr" ).jqmHijackable().length, 0, 190 | "a link with data-ajax=false should be excluded" ); 191 | 192 | $.mobile.ignoreContentEnabled = false; 193 | } ); 194 | })(QUnit, jQuery); 195 | -------------------------------------------------------------------------------- /tests/data/13/actual.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Taken from jquery-ui 3 | */ 4 | 5 | define( [ 6 | "jquery", 7 | "./helper", 8 | "ui/widgets/accordion" 9 | ], function( $, testHelper ) { 10 | 11 | var setupTeardown = testHelper.setupTeardown, 12 | state = testHelper.state; 13 | 14 | module( "accordion: core", setupTeardown() ); 15 | 16 | $.each( { div: "#list1", ul: "#navigation", dl: "#accordion-dl" }, function( type, selector ) { 17 | test( "markup structure: " + type, function( assert ) { 18 | expect( 10 ); 19 | var element = $( selector ).accordion(), 20 | headers = element.find( ".ui-accordion-header" ), 21 | content = headers.next(); 22 | 23 | assert.hasClasses( element, "ui-accordion ui-widget" ); 24 | equal( headers.length, 3, ".ui-accordion-header elements exist, correct number" ); 25 | assert.hasClasses( headers[ 0 ], 26 | "ui-accordion-header ui-accordion-header-active ui-accordion-icons" ); 27 | assert.hasClasses( headers[ 1 ], 28 | "ui-accordion-header ui-accordion-header-collapsed ui-accordion-icons" ); 29 | assert.hasClasses( headers[ 2 ], 30 | "ui-accordion-header ui-accordion-header-collapsed ui-accordion-icons" ); 31 | equal( content.length, 3, ".ui-accordion-content elements exist, correct number" ); 32 | assert.hasClasses( content[ 0 ], 33 | "ui-accordion-content ui-widget-content ui-accordion-content-active" ); 34 | assert.hasClasses( content[ 1 ], "ui-accordion-content ui-widget-content" ); 35 | assert.hasClasses( content[ 2 ], "ui-accordion-content ui-widget-content" ); 36 | deepEqual( element.find( ".ui-accordion-header" ).next().get(), 37 | element.find( ".ui-accordion-content" ).get(), 38 | "content panels come immediately after headers" ); 39 | } ); 40 | } ); 41 | 42 | test( "handle click on header-descendant", function() { 43 | expect( 1 ); 44 | var element = $( "#navigation" ).accordion(); 45 | $( "#navigation h2:eq(1) a" ).trigger( "click" ); 46 | state( element, 0, 1, 0 ); 47 | } ); 48 | 49 | test( "accessibility", function() { 50 | expect( 61 ); 51 | var element = $( "#list1" ).accordion( { 52 | active: 1, 53 | collapsible: true 54 | } ), 55 | headers = element.find( ".ui-accordion-header" ); 56 | 57 | equal( element.attr( "role" ), "tablist", "element role" ); 58 | headers.each( function( i ) { 59 | var header = headers.eq( i ), 60 | panel = header.next(); 61 | equal( header.attr( "role" ), "tab", "header " + i + " role" ); 62 | equal( header.attr( "aria-controls" ), panel.attr( "id" ), "header " + i + " aria-controls" ); 63 | equal( panel.attr( "role" ), "tabpanel", "panel " + i + " role" ); 64 | equal( panel.attr( "aria-labelledby" ), header.attr( "id" ), "panel " + i + " aria-labelledby" ); 65 | } ); 66 | 67 | equal( headers.eq( 1 ).attr( "tabindex" ), 0, "active header has tabindex=0" ); 68 | equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab (1) has aria-selected=true" ); 69 | equal( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab (1) has aria-expanded=true" ); 70 | equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "false", "active tabpanel (1) has aria-hidden=false" ); 71 | equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header (0) has tabindex=-1" ); 72 | equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 73 | equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 74 | equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 75 | equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 76 | equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 77 | equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 78 | equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 79 | 80 | element.accordion( "option", "active", 0 ); 81 | equal( headers.eq( 0 ).attr( "tabindex" ), 0, "active header (0) has tabindex=0" ); 82 | equal( headers.eq( 0 ).attr( "aria-selected" ), "true", "active tab (0) has aria-selected=true" ); 83 | equal( headers.eq( 0 ).attr( "aria-expanded" ), "true", "active tab (0) has aria-expanded=true" ); 84 | equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "false", "active tabpanel (0) has aria-hidden=false" ); 85 | equal( headers.eq( 1 ).attr( "tabindex" ), -1, "inactive header (1) has tabindex=-1" ); 86 | equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab (1) has aria-selected=false" ); 87 | equal( headers.eq( 1 ).attr( "aria-expanded" ), "false", "inactive tab (1) has aria-expanded=false" ); 88 | equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (1) has aria-hidden=true" ); 89 | equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 90 | equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 91 | equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 92 | equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 93 | 94 | element.accordion( "option", "active", false ); 95 | equal( headers.eq( 0 ).attr( "tabindex" ), 0, "previously active header (0) has tabindex=0" ); 96 | equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 97 | equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 98 | equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 99 | equal( headers.eq( 1 ).attr( "tabindex" ), -1, "inactive header (1) has tabindex=-1" ); 100 | equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab (1) has aria-selected=false" ); 101 | equal( headers.eq( 1 ).attr( "aria-expanded" ), "false", "inactive tab (1) has aria-expanded=false" ); 102 | equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (1) has aria-hidden=true" ); 103 | equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 104 | equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 105 | equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 106 | equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 107 | 108 | element.accordion( "option", "active", 1 ); 109 | equal( headers.eq( 1 ).attr( "tabindex" ), 0, "active header has tabindex=0" ); 110 | equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab (1) has aria-selected=true" ); 111 | equal( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab (1) has aria-expanded=true" ); 112 | equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "false", "active tabpanel (1) has aria-hidden=false" ); 113 | equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header (0) has tabindex=-1" ); 114 | equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 115 | equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 116 | equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 117 | equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 118 | equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 119 | equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 120 | equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 121 | 122 | } ); 123 | 124 | asyncTest( "keyboard support", function( assert ) { 125 | expect( 13 ); 126 | var element = $( "#list1" ).accordion(), 127 | headers = element.find( ".ui-accordion-header" ), 128 | anchor = headers.eq( 1 ).next().find( "a" ).eq( 0 ), 129 | keyCode = $.ui.keyCode; 130 | equal( headers.filter( ".ui-state-focus" ).length, 0, "no headers focused on init" ); 131 | headers.eq( 0 ).simulate( "focus" ); 132 | setTimeout( step1 ); 133 | 134 | function step1() { 135 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "first header has focus" ); 136 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); 137 | setTimeout( step2 ); 138 | } 139 | 140 | // Support: IE 11 with jQuery 1.7 - 1.8 only 141 | // All of the setTimeouts() from keydowns aren't necessary with newer jQuery. 142 | // Only the explicit focus simulations require them. 143 | function step2() { 144 | assert.hasClasses( headers.eq( 1 ), "ui-state-focus", "DOWN moves focus to next header" ); 145 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT } ); 146 | setTimeout( step3 ); 147 | } 148 | 149 | function step3() { 150 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "RIGHT moves focus to next header" ); 151 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); 152 | setTimeout( step4 ); 153 | } 154 | 155 | function step4() { 156 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "DOWN wraps focus to first header" ); 157 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP } ); 158 | setTimeout( step5 ); 159 | } 160 | 161 | function step5() { 162 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "UP wraps focus to last header" ); 163 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT } ); 164 | setTimeout( step6 ); 165 | } 166 | 167 | function step6() { 168 | assert.hasClasses( headers.eq( 1 ), 169 | "ui-state-focus", "LEFT moves focus to previous header" ); 170 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME } ); 171 | setTimeout( step7 ); 172 | } 173 | 174 | function step7() { 175 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "HOME moves focus to first header" ); 176 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END } ); 177 | setTimeout( step8 ); 178 | } 179 | 180 | function step8() { 181 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "END moves focus to last header" ); 182 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); 183 | setTimeout( step9 ); 184 | } 185 | 186 | function step9() { 187 | equal( element.accordion( "option", "active" ), 2, "ENTER activates panel" ); 188 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); 189 | setTimeout( step10 ); 190 | } 191 | 192 | function step10() { 193 | equal( element.accordion( "option", "active" ), 1, "SPACE activates panel" ); 194 | anchor.simulate( "focus" ); 195 | setTimeout( step11 ); 196 | } 197 | 198 | function step11() { 199 | assert.lacksClasses( headers.eq( 1 ), "ui-state-focus", 200 | "header loses focus when focusing inside the panel" ); 201 | anchor.simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); 202 | setTimeout( step12 ); 203 | } 204 | 205 | function step12() { 206 | assert.hasClasses( headers.eq( 1 ), "ui-state-focus", "CTRL+UP moves focus to header" ); 207 | start(); 208 | } 209 | } ); 210 | 211 | } ); 212 | -------------------------------------------------------------------------------- /tests/data/13/expected-ast.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Taken from jquery-ui 3 | */ 4 | 5 | define( ["qunit", "jquery", "./helper", "ui/widgets/accordion"], function(QUnit, $, testHelper) { 6 | 7 | var setupTeardown = testHelper.setupTeardown, 8 | state = testHelper.state; 9 | 10 | QUnit.module( "accordion: core", setupTeardown() ); 11 | 12 | $.each( { div: "#list1", ul: "#navigation", dl: "#accordion-dl" }, function( type, selector ) { 13 | QUnit.test( "markup structure: " + type, function( assert ) { 14 | assert.expect( 10 ); 15 | var element = $( selector ).accordion(), 16 | headers = element.find( ".ui-accordion-header" ), 17 | content = headers.next(); 18 | 19 | assert.hasClasses( element, "ui-accordion ui-widget" ); 20 | assert.equal( headers.length, 3, ".ui-accordion-header elements exist, correct number" ); 21 | assert.hasClasses( headers[ 0 ], 22 | "ui-accordion-header ui-accordion-header-active ui-accordion-icons" ); 23 | assert.hasClasses( headers[ 1 ], 24 | "ui-accordion-header ui-accordion-header-collapsed ui-accordion-icons" ); 25 | assert.hasClasses( headers[ 2 ], 26 | "ui-accordion-header ui-accordion-header-collapsed ui-accordion-icons" ); 27 | assert.equal( content.length, 3, ".ui-accordion-content elements exist, correct number" ); 28 | assert.hasClasses( content[ 0 ], 29 | "ui-accordion-content ui-widget-content ui-accordion-content-active" ); 30 | assert.hasClasses( content[ 1 ], "ui-accordion-content ui-widget-content" ); 31 | assert.hasClasses( content[ 2 ], "ui-accordion-content ui-widget-content" ); 32 | assert.deepEqual( element.find( ".ui-accordion-header" ).next().get(), 33 | element.find( ".ui-accordion-content" ).get(), 34 | "content panels come immediately after headers" ); 35 | } ); 36 | } ); 37 | 38 | QUnit.test( "handle click on header-descendant", function(assert) { 39 | assert.expect( 1 ); 40 | var element = $( "#navigation" ).accordion(); 41 | $( "#navigation h2:eq(1) a" ).trigger( "click" ); 42 | state( element, 0, 1, 0 ); 43 | } ); 44 | 45 | QUnit.test( "accessibility", function(assert) { 46 | assert.expect( 61 ); 47 | var element = $( "#list1" ).accordion( { 48 | active: 1, 49 | collapsible: true 50 | } ), 51 | headers = element.find( ".ui-accordion-header" ); 52 | 53 | assert.equal( element.attr( "role" ), "tablist", "element role" ); 54 | headers.each( function( i ) { 55 | var header = headers.eq( i ), 56 | panel = header.next(); 57 | assert.equal( header.attr( "role" ), "tab", "header " + i + " role" ); 58 | assert.equal( header.attr( "aria-controls" ), panel.attr( "id" ), "header " + i + " aria-controls" ); 59 | assert.equal( panel.attr( "role" ), "tabpanel", "panel " + i + " role" ); 60 | assert.equal( panel.attr( "aria-labelledby" ), header.attr( "id" ), "panel " + i + " aria-labelledby" ); 61 | } ); 62 | 63 | assert.equal( headers.eq( 1 ).attr( "tabindex" ), 0, "active header has tabindex=0" ); 64 | assert.equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab (1) has aria-selected=true" ); 65 | assert.equal( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab (1) has aria-expanded=true" ); 66 | assert.equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "false", "active tabpanel (1) has aria-hidden=false" ); 67 | assert.equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header (0) has tabindex=-1" ); 68 | assert.equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 69 | assert.equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 70 | assert.equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 71 | assert.equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 72 | assert.equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 73 | assert.equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 74 | assert.equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 75 | 76 | element.accordion( "option", "active", 0 ); 77 | assert.equal( headers.eq( 0 ).attr( "tabindex" ), 0, "active header (0) has tabindex=0" ); 78 | assert.equal( headers.eq( 0 ).attr( "aria-selected" ), "true", "active tab (0) has aria-selected=true" ); 79 | assert.equal( headers.eq( 0 ).attr( "aria-expanded" ), "true", "active tab (0) has aria-expanded=true" ); 80 | assert.equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "false", "active tabpanel (0) has aria-hidden=false" ); 81 | assert.equal( headers.eq( 1 ).attr( "tabindex" ), -1, "inactive header (1) has tabindex=-1" ); 82 | assert.equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab (1) has aria-selected=false" ); 83 | assert.equal( headers.eq( 1 ).attr( "aria-expanded" ), "false", "inactive tab (1) has aria-expanded=false" ); 84 | assert.equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (1) has aria-hidden=true" ); 85 | assert.equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 86 | assert.equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 87 | assert.equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 88 | assert.equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 89 | 90 | element.accordion( "option", "active", false ); 91 | assert.equal( headers.eq( 0 ).attr( "tabindex" ), 0, "previously active header (0) has tabindex=0" ); 92 | assert.equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 93 | assert.equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 94 | assert.equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 95 | assert.equal( headers.eq( 1 ).attr( "tabindex" ), -1, "inactive header (1) has tabindex=-1" ); 96 | assert.equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab (1) has aria-selected=false" ); 97 | assert.equal( headers.eq( 1 ).attr( "aria-expanded" ), "false", "inactive tab (1) has aria-expanded=false" ); 98 | assert.equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (1) has aria-hidden=true" ); 99 | assert.equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 100 | assert.equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 101 | assert.equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 102 | assert.equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 103 | 104 | element.accordion( "option", "active", 1 ); 105 | assert.equal( headers.eq( 1 ).attr( "tabindex" ), 0, "active header has tabindex=0" ); 106 | assert.equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab (1) has aria-selected=true" ); 107 | assert.equal( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab (1) has aria-expanded=true" ); 108 | assert.equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "false", "active tabpanel (1) has aria-hidden=false" ); 109 | assert.equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header (0) has tabindex=-1" ); 110 | assert.equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab (0) has aria-selected=false" ); 111 | assert.equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab (0) has aria-expanded=false" ); 112 | assert.equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (0) has aria-hidden=true" ); 113 | assert.equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header (2) has tabindex=-1" ); 114 | assert.equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab (2) has aria-selected=false" ); 115 | assert.equal( headers.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab (2) has aria-expanded=false" ); 116 | assert.equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel (2) has aria-hidden=true" ); 117 | 118 | } ); 119 | 120 | QUnit.test( "keyboard support", function( assert ) { 121 | var ready = assert.async(); 122 | assert.expect( 13 ); 123 | var element = $( "#list1" ).accordion(), 124 | headers = element.find( ".ui-accordion-header" ), 125 | anchor = headers.eq( 1 ).next().find( "a" ).eq( 0 ), 126 | keyCode = $.ui.keyCode; 127 | assert.equal( headers.filter( ".ui-state-focus" ).length, 0, "no headers focused on init" ); 128 | headers.eq( 0 ).simulate( "focus" ); 129 | setTimeout( step1 ); 130 | 131 | function step1() { 132 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "first header has focus" ); 133 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); 134 | setTimeout( step2 ); 135 | } 136 | 137 | // Support: IE 11 with jQuery 1.7 - 1.8 only 138 | // All of the setTimeouts() from keydowns aren't necessary with newer jQuery. 139 | // Only the explicit focus simulations require them. 140 | function step2() { 141 | assert.hasClasses( headers.eq( 1 ), "ui-state-focus", "DOWN moves focus to next header" ); 142 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT } ); 143 | setTimeout( step3 ); 144 | } 145 | 146 | function step3() { 147 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "RIGHT moves focus to next header" ); 148 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); 149 | setTimeout( step4 ); 150 | } 151 | 152 | function step4() { 153 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "DOWN wraps focus to first header" ); 154 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP } ); 155 | setTimeout( step5 ); 156 | } 157 | 158 | function step5() { 159 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "UP wraps focus to last header" ); 160 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT } ); 161 | setTimeout( step6 ); 162 | } 163 | 164 | function step6() { 165 | assert.hasClasses( headers.eq( 1 ), 166 | "ui-state-focus", "LEFT moves focus to previous header" ); 167 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME } ); 168 | setTimeout( step7 ); 169 | } 170 | 171 | function step7() { 172 | assert.hasClasses( headers.eq( 0 ), "ui-state-focus", "HOME moves focus to first header" ); 173 | headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END } ); 174 | setTimeout( step8 ); 175 | } 176 | 177 | function step8() { 178 | assert.hasClasses( headers.eq( 2 ), "ui-state-focus", "END moves focus to last header" ); 179 | headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); 180 | setTimeout( step9 ); 181 | } 182 | 183 | function step9() { 184 | assert.equal( element.accordion( "option", "active" ), 2, "ENTER activates panel" ); 185 | headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); 186 | setTimeout( step10 ); 187 | } 188 | 189 | function step10() { 190 | assert.equal( element.accordion( "option", "active" ), 1, "SPACE activates panel" ); 191 | anchor.simulate( "focus" ); 192 | setTimeout( step11 ); 193 | } 194 | 195 | function step11() { 196 | assert.lacksClasses( headers.eq( 1 ), "ui-state-focus", 197 | "header loses focus when focusing inside the panel" ); 198 | anchor.simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); 199 | setTimeout( step12 ); 200 | } 201 | 202 | function step12() { 203 | assert.hasClasses( headers.eq( 1 ), "ui-state-focus", "CTRL+UP moves focus to header" ); 204 | ready(); 205 | } 206 | } ); 207 | 208 | } ); 209 | --------------------------------------------------------------------------------