0

Note, related How to test if jQuery 3.0 beta is Promises/A+ compatible in browser?


For example, at promises-tests one of the tests is found at promises-tests/lib/tests/2.1.2.js

"use strict";

var assert = require("assert");
var testFulfilled = require("./helpers/testThreeCases").testFulfilled;

var adapter = global.adapter;
var deferred = adapter.deferred;

var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it

describe("2.1.2.1: When fulfilled, a promise: must not transition to any other state.", function () {
    testFulfilled(dummy, function (promise, done) {
        var onFulfilledCalled = false;

        promise.then(function onFulfilled() {
            onFulfilledCalled = true;
        }, function onRejected() {
            assert.strictEqual(onFulfilledCalled, false);
            done();
        });

        setTimeout(done, 100);
    });

    specify("trying to fulfill then immediately reject", function (done) {
        var d = deferred();
        var onFulfilledCalled = false;

        d.promise.then(function onFulfilled() {
            onFulfilledCalled = true;
        }, function onRejected() {
            assert.strictEqual(onFulfilledCalled, false);
            done();
        });

        d.resolve(dummy);
        d.reject(dummy);
        setTimeout(done, 100);
    });

    specify("trying to fulfill then reject, delayed", function (done) {
        var d = deferred();
        var onFulfilledCalled = false;

        d.promise.then(function onFulfilled() {
            onFulfilledCalled = true;
        }, function onRejected() {
            assert.strictEqual(onFulfilledCalled, false);
            done();
        });

        setTimeout(function () {
            d.resolve(dummy);
            d.reject(dummy);
        }, 50);
        setTimeout(done, 100);
    });

    specify("trying to fulfill immediately then reject delayed", function (done) {
        var d = deferred();
        var onFulfilledCalled = false;

        d.promise.then(function onFulfilled() {
            onFulfilledCalled = true;
        }, function onRejected() {
            assert.strictEqual(onFulfilledCalled, false);
            done();
        });

        d.resolve(dummy);
        setTimeout(function () {
            d.reject(dummy);
        }, 50);
        setTimeout(done, 100);
    });
});

Requirement:

The ability to run the test in the browser without reliance on node.js , a server, or installing libraries?

Question:

How can this test be converted to a version using native methods available at browsers, for example Console methods; that is, substitution of console.assert() or other native method available at window for describe() and specify()?

Community
  • 1
  • 1
guest271314
  • 1
  • 15
  • 104
  • 177
  • The completely unsatisfactory answer is: by hand :P – Jared Smith Apr 11 '16 at 18:26
  • @JaredSmith Yes. Ok with that approach. Do not have much experience with `node.js`. How to select the appropriate corresponding method available at `window`? For example, what is the difference between `describe()` and `specify()`? – guest271314 Apr 11 '16 at 18:27
  • You'll want to use a client side testing library like Jasmine or Qunit. Then you should almost be able to grep your code and replace the equivalent idioms. For instance, with Jasmine it would be describe instead of specify. IIRC qunit's syntax is nearly identical to the above. – Jared Smith Apr 11 '16 at 18:29
  • You wont need the console outputs at all, those libraries will graphically display the results in HTML. Only way to do it without libraries is to literally write your own. – Jared Smith Apr 11 '16 at 18:30
  • @JaredSmith Was able to run QUnit. How to convert the tests linked above to QUnit? Or even simply use `console.assert()`? The visual display is not a requirement, only the results. What are native `window` methods functional equivalents of `describe()` and `specify()`? – guest271314 Apr 11 '16 at 18:31
  • In that case you may want to use something like phantomjs. Here's a set up with phantom and jasmine https://github.com/qindio/headless-jasmine-sample. I use this approach for testing stuff fairly often. Window does not have native, that's why you need to write or use a library. – Jared Smith Apr 11 '16 at 18:32
  • @JaredSmith Would prefer not to install libraries to achieve requirement, but rather utilize native browser methods; for example `Console`. – guest271314 Apr 11 '16 at 18:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108850/discussion-between-jared-smith-and-guest271314). – Jared Smith Apr 11 '16 at 18:34

1 Answers1

1

I still think this is a terrible idea, but here's a (trivial) example:

var assert = {};
assert.equals = function(expected, value, msg) {
    var message = msg || "Test ";
    try {
        expected == value;
        console.log(message, "passed");
    catch (e) {
        console.log(message, "failed", e);
    }
};

Now repeat for >, <, ===, ranges, exceptions when they're expected, specific exceptions (e.g. TypeError, SyntaxError), typeof, instanceof, other types (built-ins, constructed), problematic values like NaN and null, etc.

NOTE: console.assert

There are some problems with console.assert. First, its non-standard and may not behave identically across platforms. Second, there is, AFAIK, no good way to abstract it: you'd end up doing just as much work as the above solution using console.log unless you use eval and string arguments:

function assert(str, msg) {
  try {
     console.assert(eval(str), msg);
  catch (e) {
     console.log(msg, " failed:", e);
  }
}

assert("3 === 4", "Three equals four"); // logs the assertion failure.

Needless to say, I do not recommend this, as manually constructing the strings is error-prone, eval (even though safe in this case) is a notorious perf killer, and not using eval means using a parser and bam we're right back to the library bit.

Seriously, as you go down this road you will think of more and more things you want to be in there (see my list above) and you will realize you are writing a library when you could have used one.

UPDATE

Per your question in the comments below, many testing libraries (e.g. mocha, jasmine) use a format like this:

wrapper('name of the thing being tested', function(done) {
   innerWrapper('description of the test', function(done) {
       assert(someAssertion);
   });

   innerWrapper('some other test for that function', function(done) {
       assert(somethingElse);
       someAsyncFunction().then(function(value) {
           assert(somethingAboutValue);
           done();
       });
   });
});
 

The 'wrapper', 'innerWrapper', and 'assert' are added by including the testing library in the code or running the command (for cli) i.e. 'mocha tests.js' instead of 'node tests.js'. The setup may or may not use the inner functions to specify subtests. 'Done' is an argument to the callback that can be used to signal the end of an async test.

QUnit is a little simpler in its API, but not too far off.

UPDATE 2

Those for the most part are names for the same things: functions that wrap a test condition to make sure that correct messages are logged, or exceptions caught, or async gets a chance to finish. The assert tests the actual condition to be evaluated. The adapter reference means wrapping the jQuery deferred constructor to match the API in the spec.

Community
  • 1
  • 1
Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • What is the difference between `describe()` and `specify()` at `js` at Question? – guest271314 Apr 11 '16 at 19:16
  • Neither are native, one is the way one library handles it, the other is the other library's syntax. Note that their tantalizingly close to identical, these libraries share a lot of commonalities. – Jared Smith Apr 11 '16 at 19:17
  • Would `assert()` at your Answer be equivalent to `specify()`? – guest271314 Apr 11 '16 at 19:18
  • Can you describe difference between `describe()`, `specify()`, `assert()` as used at `js` at Question? What an `adapter` is and the role that an `adpater` has in the process? – guest271314 Apr 11 '16 at 19:25