/* vim:ts=2:sts=2:sw=2: * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Jetpack. * * The Initial Developer of the Original Code is Mozilla. * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Irakli Gozalishvili (Original Author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ "use strict"; const BaseAssert = require("./test/assert").Assert; const { isFunction, isObject } = require("./type"); function extend(target) { let descriptor = {} Array.slice(arguments, 1).forEach(function(source) { Object.getOwnPropertyNames(source).forEach(function onEach(name) { descriptor[name] = Object.getOwnPropertyDescriptor(source, name); }); }); return Object.create(target, descriptor); } /** * Function takes test `suite` object in CommonJS format and defines all of the * tests from that suite and nested suites in a jetpack format on a given * `target` object. Optionally third argument `prefix` can be passed to prefix * all the test names. */ function defineTestSuite(target, suite, prefix) { prefix = prefix || ""; // If suite defines `Assert` that's what `assert` object have to be created // from and passed to a test function (This allows custom assertion functions) // See for details: http://wiki.commonjs.org/wiki/Unit_Testing/1.1 let Assert = suite.Assert || BaseAssert; // Going through each item in the test suite and wrapping it into a // Jetpack test format. Object.keys(suite).forEach(function(key) { // If name starts with test then it's a test function or suite. if (key.indexOf("test") === 0) { let test = suite[key]; // For each test function so we create a wrapper test function in a // jetpack format and copy that to a `target` exports. if (isFunction(test)) { // Since names of the test may match across suites we use full object // path as a name to avoid overriding same function. target[prefix + key] = function(options) { // Creating `assert` functions for this test. let assert = Assert(options); // If CommonJS test function expects more than one argument // it means that test is async and second argument is a callback // to notify that test is finished. if (1 < test.length) { // Letting test runner know that test is executed async and // creating a callback function that CommonJS tests will call // once it's done. options.waitUntilDone(); test(assert, function() { options.done(); }); } // Otherwise CommonJS test is synchronous so we call it only with // one argument. else { test(assert); } } } // If it's an object then it's a test suite containing test function // and / or nested test suites. In that case we just extend prefix used // and call this function to copy and wrap tests from nested suite. else if (isObject(test)) { // We need to clone `tests` instead of modifying it, since it's very // likely that it is frozen (usually test suites imported modules). test = extend(Object.prototype, test, { Assert: test.Assert || Assert }); defineTestSuite(target, test, prefix + key + "."); } } }); } /** * This function is a CommonJS test runner function, but since Jetpack test * runner and test format is different from CommonJS this function shims given * `exports` with all its tests into a Jetpack test format so that the built-in * test runner will be able to run CommonJS test without manual changes. */ exports.run = function run(exports) { // We can't leave old properties on exports since those are test in a CommonJS // format that why we move everything to a new `suite` object. let suite = {}; Object.keys(exports).forEach(function(key) { suite[key] = exports[key]; delete exports[key]; }); // Now we wrap all the CommonJS tests to a Jetpack format and define // those to a given `exports` object since that where jetpack test runner // will look for them. defineTestSuite(exports, suite); };