Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boolean disjunction (OR) using mocha and chai

I have the following scenario in which I have to check that an URL was build correctly provided some query arguments. I do not expect the system to apply an specific order in the rendered URL, so I came with the following test case which I expected to work:

it('test that url is built correctly', function () {
    var args = {
        arg1: 'value1',
        arg1: 'value2'
    };

    var rendered_url = render_url(args);

    expect(rendered_url).to.equal('/my/url?arg1=value1&arg2=value2')
                     .or.to.equal('/my/url?arg2=value2&arg1=value1')
    ;
});

I was pretty surprised to the or chain to not exists as it makes the statement construction process tidy and cozy.

I know I can workaround this in many ways (for example, using satisfy), but I wonder:

  • Whether I cannot find the pattern to achieve in a similar way what I want in the documentation(I have read it thoroughly)...
  • ... or whether there exists a good reason to not include this construction in chai...
  • ... or whether there exists an alternative way to achieve a construction similar to the one in the example (tweaking, other frameworks, etc)
like image 365
ajaest Avatar asked Dec 31 '14 12:12

ajaest


People also ask

What is difference between Mocha and chai?

Mocha is a JavaScript test framework running on Node. js and in the browser. Mocha allows asynchronous testing, test coverage reports, and use of any assertion library. Chai is a BDD / TDD assertion library for NodeJS and the browser that can be delightfully paired with any javascript testing framework.

What is the use of chai Mocha?

Chai is an assertion library that is mostly used alongside Mocha. It can be used both as a BDD / TDD assertion library for NodeJS and can be paired with any JavaScript testing framework. It has several interfaces that a developer can choose from and looks much like writing tests in English sentences.

Which of the following is considered as the default test reporter of Mocha?

Mocha provides a variety of interfaces for defining test suites, hooks, and individual tests, including TSS, Exports, QUnit, and Require. The default interface is behavior-driven development (BDD), which aims to help developers build software that is predictable, resilient to changes, and not error-prone.


2 Answers

You could use to.include or .match:

var chai = require("chai");
var expect = chai.expect;

var option1 = '/my/url?arg1=value1&arg2=value2';
var option2 = '/my/url?arg2=value2&arg1=value1';

var possible = [option1, option2];

var re = /^\/my\/url\?arg1=value1&arg2=value2|\/my\/url\?arg2=value2&arg1=value1$/;

it('1', function () {
    var rendered_url = option1;
    expect(possible).to.include(rendered_url);
    expect(rendered_url).to.match(re);
});

it('2', function () {
    var rendered_url = option2;
    expect(possible).to.include(rendered_url);
    expect(rendered_url).to.match(re);
});

it('3', function () {
    var rendered_url = "foo";
    expect(possible).to.include(rendered_url);
});

it('4', function () {
    var rendered_url = "foo";
    expect(rendered_url).to.match(re);
});

The first 2 tests will pass, the last 2 will fail.

I've not done it in this example but both possible and re could be generated by a function rather than hand-coding all possible permutations of arguments.

I suspect the reason that .or is not in Chai is that it would complicate Chai's code quite a bit and make it more cumbersome to use for regular cases. Right now when .equal is called, it knows it is terminal. If Chai allowed to use .or, then .equal could not know right away whether it is terminal or not. Even if you had something like expect(foo).to.equal(bar), the call to equal cannot know that it is terminal. You'd have to do something like what some promises library do to signal that the code is finished with a promise and have a call saying "I'm done here" so it would look like expect(foo).to.equal(bar).end(). I'm not saying it would be impossible but it would have wide-ranging repercussions.

like image 77
Louis Avatar answered Sep 23 '22 13:09

Louis


You could do something like:

expect(rendrered_url).to.satisfy(function(url){
    return url === '/my/url?arg1=value1&arg2=value2 || url === '/my/url?arg2=value2&arg1=value1';
});
like image 43
juunas Avatar answered Sep 22 '22 13:09

juunas