Coder Social home page Coder Social logo

squire.js's Introduction

Squire.js

Squire.js is a dependency injector for Require.js users to make mocking dependencies easy!

Squire.js - The Squire

Installation

Bower

bower install squire

NPM

npm install squirejs

API

constructor

First you have to load Squire in, just like any other Require.js module. Beyond this example the rest of the documentation will assume you already loaded Squire as a module dependency.

Default Configuration

define(['Squire'], function(Squire) {
  var injector = new Squire();
});

Different Context

var injector = new Squire('other-requirejs-context');

require(Array dependencies, Function callback, Function errback)

var injector = new Squire();
injector.require(['utilities/Calculator'], function(Calculator) {
  // Calculator has been loaded.
},
function(err) {
  // Calculator threw an error loading.
});

mock(String name | Object(name: mock), Object mock)

The mock method lets you pass in mocks to be used for a given modules dependency. The first argument is the module name, the second argument is the mock itself. For multiple mocks you can pass an object, the objects key will be the path and the corresponding value will be used as the mock.

var injector = new Squire();

// Key value mocking.
injector.mock(dependencyName, mockForDependency);

// You can pass an object literal as well.
injector.mock(dependencyNameAndMock);
var injector = new Squire();
injector.mock('CrazyCalculatorDependency', {
    sin: 10
  })
  .require(['utilities/Calculator'], function(Calculator) {
    // The Calculators dependency 'CrazyCalculatorDependency' has been mocked to
    // use the object literal { sin: 10 } that we passed in.
  });

store(String name | Array names)

The store method allows you to get a pointer back to a dependency so you can stub it.

var injector = new Squire();
injector
  .store('CrazyCalculatorDependency')
  .require(['utilities/Calculator', 'mocks'], function(Calculator, mocks) {
    // mocks.store.CrazyCalculatorDependency is the Calculators dependency, you can
    // manipulate it or stub it with Sinon now.
  });

clean(Optional (String name | Array names))

The clean method allows you to remove mocks by name from your Squire instance, or remove all mocks.

var injector = new Squire();
injector.mock('something', { other: 'mock'});

// You do stuff but want to be able to get the real 'something' now.
injector.clean('something');

// Or a collection of mocks
injector.clean(['something', 'something/else']);

Or clean out all the mocks stored in a Squire instance.

injector.clean();

remove()

Remove all the dependencies loaded by this instance of Squire.

injector.remove();

run()

Run generates a function that will receive a done callback and execute it after your test function is complete. Particularly useful for frameworks where asynchrony is handled with a callback. Here is an example with Mocha.js. Jasmine can offer this callback approach using Jasmin.Async.

it('should execute this test using run', injector.run(['mocks/Shirt'], function(Shirt) {
  Shirt.color.should.equal('Red');
}));

Utilities

Squire.js offers a few helper functions to ease pains associated with mocking and testing AMD modules.

Squire.Helpers.returns(Any what)

Create a mock that returns mockViewInstance

injector.mock('Views/AwesomeView', Squire.Helpers.returns(mockViewInstance));

Squire.Helpers.constructs(Any what)

Often times AMD modules return constructor functions which means that mocking such a class would end up having to create a function that returns a function that returns your mocked instance. Squire.js eases that pain by wrapping up your instance for you.

injector.mock('Views/AwesomeView', Squire.Helpers.constructs(mockViewInstance));

Now any module that uses Views/AwesomeView as a constructor dependency will use get your mock instead:

// when invoked with in an Squire.injector.require call
var awesome = new AwesomeView(); // awesome now gets your mockViewInstance

Credits

Illustration by Adam Christiansen

squire.js's People

Contributors

iammerrick avatar adampearse avatar jonotron avatar daveduchene avatar jahed avatar jergason avatar

Stargazers

Min Huang avatar Mindula Dilthushan Manamperi avatar Marian avatar tianruo avatar Alex Strizhak avatar Yun Song avatar Viktor Petryk avatar Dan Mooney avatar zhouhao avatar vulcangz avatar Eliran Malka avatar Vangelis Xanthakis avatar Bailey Malone avatar Martin Borbola avatar Andriyan Ivanov avatar Robert McCoy avatar Zhenyu Lin avatar Daniel Blendea avatar GAURAV avatar Mike Talley avatar Cezar Mauricio avatar jm avatar Cyrille Pontvieux avatar Dave.Kim avatar Knut Behrends avatar Walter Rafelsberger avatar Kane Elfman avatar Mark Fox avatar Nicholas Lee avatar Oleksandr Denysenko avatar Miacis Hex avatar Stefan Walther avatar Héctor Paúl Cervera-García avatar Deepak Vasalamarri avatar Murat Knecht avatar Thibault avatar  avatar Matthew Piskorz avatar LaTale avatar herbert avatar liyuanfeng avatar Dene Boulton avatar Michał Malik avatar  avatar Naftali Lubin avatar Adrian Carballo avatar Nicolas Hefti avatar Lars Kristian Bremnes avatar Yevgen Poltorakov avatar Craig Hopgood avatar Rizky  avatar John Sorrentino avatar Bill Sorensen avatar Charles avatar Oleg avatar Lucas S. B. Mastella avatar Phil Klinefelter avatar  avatar Prayag Verma  avatar Ihor Pavlenko avatar Pavel Birukov  avatar David Falkner avatar  avatar Rhy Moore avatar Angus H. avatar Chion avatar Claude Betancourt avatar Brian Bonner avatar YANSHUO HUANG avatar lijian avatar Christoph Stickel avatar  avatar Thales Caricati avatar Maciej Lis avatar Mateusz Kocz avatar  avatar Ilya Pukhalski avatar Fredrik Rombach Ekelund avatar Matthew Nichols avatar Ben Regenspan avatar andr avatar Tamás Hetesi avatar Tristian Barrett avatar Edwar avatar Lochlan McIntosh avatar Will Price avatar Michele Di Salvatore avatar Stuart Butler avatar Mathieu Darse avatar Matt Clawson avatar Gavin Jones avatar Andris Sīlis avatar 嫣识 avatar Arthur Christoph avatar AJ avatar Zhang Xin avatar Ben Barnett avatar Jonas Oppenlaender avatar Garrick Cheung avatar  avatar

Watchers

Gunnar Wrobel avatar Facundo Cabrera avatar  avatar evandrix avatar dragonpig avatar Vimal avatar Cengiz Poyraz avatar  avatar James Cloos avatar Joe Eames avatar Joel avatar Ricardo Montoya avatar Vangelis Xanthakis avatar  avatar

squire.js's Issues

npm publish

Could you please publish version 0.2.0 to npm. Thanks, Jason

Inline define must be mocked?

I found that inline defined module cannot be loaded by its name:

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Spec Runner</title>
    <link rel="stylesheet" href="lib/jasmine-1.2.0/jasmine.css">
    <script src="lib/jasmine-1.2.0/jasmine.js"></script>
    <script src="lib/jasmine-1.2.0/jasmine-html.js"></script>
    <script src="lib/jquery-1.7.2.js"></script>
    <script src="lib/jasmine-helper.js"></script>
    <script src="lib/jasmine.async.js"></script>
    <script src="lib/require-2.1.4.js"></script>
        var requirejsConfig = {
            baseUrl: '.',
            waitSeconds: 15,
            urlArgs: 'bust='+new Date().getTime()
        };
        require.config(requirejsConfig);
        define("sys", {ver: '0.0.1'}); //inline defined module

        require([
            'spec/component-a_spec.js'
        ], function(){
            jasmineEnv.execute();
        });
    </script>
</head>
<body></body>
</html>

component-a.js

define(['components/component-b', 'sys'], function(b, sys){
    return { name:'A' , ver: sys.ver, b: b };
});

component-a_spec.js

define(['lib/squire'], function(Squire){

    describe("component-a", function() {

        var async = new AsyncSpec(this), a;
        async.beforeEach(function(done){
            new Squire()
            .mock({'components/component-b':{test:false}})
            .require(['components/component-a'], function(com) {
                a = com;
                done();
            })
        });

        it('should be defined', function(a){
            expect(a).toBeDefined();
            expect(a.name).toEqual('A');
            expect(a.b.test).toEqual(false);
        });
    });
});

Browser will look for sys.js, but it is already defined inline. So these inline-defined module must be mocked as well?

UMD wrap

Would it be possible to wrap the module in a universal module pattern so that it can be required in node?
This would remove the additional work of setting up the module path via requirejs.config. More importantly, it would allow other node modules to use it without polluting global requirejs config space.

If this makes sense I could also create a pull request.

Difference between store and additional require?

To me it seems store doesn't do that much different from adding the desired module to the require call.

Is there any difference between this:

var injector = new Squire();
injector
  .store('CrazyCalculatorDependency')
  .require(['utilities/Calculator', 'mocks'], function(Calculator, mocks) {
    // use mocks.store.CrazyCalculatorDependency 
  });

and this:

var injector = new Squire();
injector
  .require(['utilities/Calculator', 'CrazyCalculatorDependency'], function(Calculator, CrazyCalculatorDependency) {
    // use CrazyCalculatorDependency
  });

And if so what are they?

Squire is breaking other tests

I'm using Karma, Jasmine, Jasmine.Async, Sinon and Chai.

The good news...this test works correctly. The dependency is mocked, spies get called, and intentionally breaking the test subject results in failed tests.

define(['chai', 'squire'], function (chai, Squire) {

    var should = chai.should(),
        async = new AsyncSpec(this),
        subject, injector = new Squire();

    describe('EventsView', function () {

        describe('when an event is clicked', function () {
            var mockModel, stub;

            async.beforeEach(function (done) {
                setFixtures('<div id="screen"></div>');

                mockModel = {
                    toJSON: function () {
                        return {
                            dimensions: "hu1 vu2",
                            events: [{
                                date: "8/29/2013",
                                id: "8923",
                                title: "Fancy Show",
                                venue: "Lovely venue",
                            }, {
                                date: "8/29/2013",
                                id: "9034",
                                title: "Exciting Game",
                                venue: "Lovely stadium"
                            }],
                            id: 3566,
                            kind: "events",
                            title: "Top events this week"
                        };
                    },
                    fetch: function () {}
                };
                stub = sinon.stub();
                injector.mock('tiles/events-tile/events-detail-model', Squire.Helpers.constructs({
                    fetch: stub
                }));
                injector.require(["tiles/events-tile/events-view"], function (ev) {
                    subject = new ev(mockModel);
                    done();
                });
            });

            async.afterEach(function (done) {
                injector.clean();
                injector.remove();
                done();
            });


            async.it('should attempt to fetch the event details', function (done) {
                $('#screen').html(subject.$el);
                $('.event').first().click();
                stub.called.should.be.true;
                done();
            });
        });
    });
});

The bad news...a shed load of other tests that were previously fine are now failing for weird reasons. For example:
Error: Backbone.history has already been started
and
TypeError: 'undefined' is not an object (evaluating 'Backbone.Validation.mixin')

If I comment out the snippet

injector.require(["tiles/events-tile/events-view"], function (ev) {
  subject = new ev(mockModel);
    done();
});

Then the other tests work again. I've had stuff like this happen before and it has usually been down to a sinon mock not getting restored. The injector.clean() call doesn't seem to be providing the magic bullet I was hoping for.

storing mocks with directory paths

when I tried the following, I didn't get mocks back:

    injector
        .store('directory/module')
        .require('someOtherModule', function(someOtherModule, mocks){
            console.log(mocks); // it returns undefined
        });

Something I'm doing wrong? Should mocks have a property named 'directory/module' in this case?

Cannot properly test modules that export a constructor

A module (A) requires a module (B) that exports a constructor (aka a class).

We want to mock "module B" and at least be able to measure:

  1. If it has been instantiated and how many times.
  2. If a method of "module B" has been invoked and how many times.

We also want to control what results the method returns or what callbacks are yielded, but let's not get ahead of ourselves at this point.

The tool we use for mocking and measuring is sinon.js.

I have tried two ways to accomplish the above task:

1. Mocking the Dependency

Mocking the dependency by using the injector.mock() method. I could not find a satisfactory solution with that.

2. Storing the Dependency

Storing the dependency using injector.store() method. Using this method there was an unexpected result. The app behaved like there was no stubbing on the provided namespace (mocks.store['moduleName']) thus providing no useful information as to if the dependency was invoked.

Demo

Please see this plnkr where the issue is illustrated.

Approach 1 is implemented in file moduleA.test.js

Approach 2 is implemented in file moduleA.test2.js

undef not found when used with requirejs 2.1.4

I try to run the tests with requirejs 2.1.4. The clean method has error.

clean
should not mock the requested module
TypeError: Object #<Object> has no method 'undef'
    at Squire.clean (file:///D:/workspace/web/Squire.js/src/Squire.js:134:37)
    at Context.<anonymous> (file:///D:/workspace/web/Squire.js/test/tests/SquireTests.js:262:12)
    at Test.Runnable.run (file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3471:15)
    at Runner.runTest (file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3796:10)
    at file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3842:12
    at next (file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3724:14)
    at file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3733:7
    at next (file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3681:23)
    at file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:3701:5
    at process.removeListener.window.onerror (file:///D:/workspace/web/Squire.js/test/vendor/mocha.js:4621:44)

Why require wrapping mock functions in functions?

First I want to say that now that I am getting the hang of the API, I am finding Squire very useful.

That said, I did find the mock() API unduly confusing at first and wanted to make some recommendations.

The reason for the existence of the two helper methods documented at the end of the readme escaped me for a while. After looking at Squire's unit tests, I finally came to the understanding that what one passes to mock() is exactly what a regular module would pass as the final argument to define(). In other words, it can be an object or a function, but if it is a function, Require will assume it is is a factory that returns the real value.

In the case of define, this makes sense, because the function can accept arguments, namely any dependencies that were declared in the second argument to define(). However, in Squire there is presently no way for any dependencies to be passed to the function. So what value has it as a factory? It seems to me that any code that it might execute beyond returning the mock could be executed in the enclosing closure. This in turn negates the value of any implementation of the factory other than the one that just returns the mock.

If this is indeed the case, why doesn't mock just automatically wrap its second argument in a function and be done with it? Even if the value were not a function, wrapping it in one would have no effect on Require that I am aware of. If I am wrong, mock could conditionally wrap the argument only if it is a function. This would make the API a lot less confusing.

This cause quite some consternation when I was first trying to use Squire to mock a class function (constructor) , overriding the original class definition. The fact that I had to pass new function(){ return MyMockClass; } instead of just MyMockClass to mock was dumbfounding for a while, especially in light of the documentation for the mock method: "the second argument is the mock itself" [emphasis added].

At the very least the documentation for mock needs to be improved on this point. Alternatively, I would prefer having mock wrap functions automatically. If we do want to leave the possibility open for meaningful factory functions, maybe add an optional argument to mock that is an array of dependency names to pass to the factory method, in the pattern of define(), and only auto-wrap if said argument is undefined.

Just some thoughts...

Update documentation with store method

The README says that Squire.store() should accept an array of paths. The tests and your code reflect that its expecting as string and the array is not supported.

The workaround for now is to chain stores('dependency'), which works for me

Feedback

I am still new to the needs for mock testing. So this may be ill-informed. If it is, then listing where this falls short in the readme may help distinguish the use cases:

For mock testing, it should be enough just to call define() with a named module that has the mock, then require as usual. So, if there is a module 'bar' that depends on 'foo', and 'foo' will be mocked:

var mock1Require = requirejs.config({
    //create a context for the mock
    context: 'mock1',
    paths: {
        //Either store the mock as a separate file,
        //or do the inline define below
        foo: 'mocks/foo1'
    }
});

//If not using the paths to direct 'foo' to a separate mock
//file, inline define it:
define('foo', function () {
    return {};
});

mock1Require(['bar'], function(bar) {
    //Do tests with bar, which will be using the mocked foo
});

Looking at the squire API it seems to do more than this, but my first approximation is that it is enough to at least start mock testing. Says the person that does not really do mocks :)

I definitely support raising awareness of how to do mock testing with requirejs. It does seem to come up now and then. I would like to have a resource I could point to for it, maybe link to it on the testing wiki page

Feature request: accept re-usable mock paths

Currently it seems you must provide the literal mock you wish to use.

We want to re-use our mocks. We store them in modules, just like any other code.

If you require the mocks, so you can provide the literal, you can end up breaking the sandbox you have built around the test.

It would be nice to be able to provide the path to the module, and clean it up properly to prevent sharing modules between tests.

Nuget package

Hi!
Have you considered hosting your project as a Nuget package?

Add a tag for v0.2.1

The tag for 0.2.1 is missing, which means that it's not found when installing with Bower.

Can't mock module dependency

This might not be possible, but I'm trying to mock the module config for a module, see http://requirejs.org/docs/api.html#config-moduleconfig

This how I try it.

new Squire()
  .mock('module', {
    config: function() {
      return {
        someProperty: 5
      };
    }
  })
  .require(['moduleThatUsesConfig'], function(moduleThatUsesConfig) {
    //etc
  });
});

With this module

define(['module'], function(module) {
  var apiBasePath = module.config().apiBasePath;
  //etc
});

Doesn't work, it just get the original module object. Is this a limitation or not implemented yet? Bug?

Needs further documentation/usage examples

Squire.js looks like just what I need for mocking require.js dependencies in my tests, but I don't understand how to use it properly. Can you put together some documentation on how to get started using it? Some examples would be great, particularly with the jasmine test framework. Even just a blog post would be helpful!

Needs a license

I'd love to use this at work, but I need to know how it's licensed first. Thanks.

Can I store all dependencies?

My spec file seems to be somehow cumbersome:

define(['lib/squire'], function(Squire){

var injector = new Squire();
injector.mock({
    'components/lazytab': jasmine.createSpyObj('lazytab', ['create']),
    'app/pages/m1':{},
    'app/pages/m1':{}
}).store([
    'components/lazytab',
    'app/pages/m1',
    'app/pages/m2'
]);

injector.require([
    'app/pages/page_modules',
    'mocks'
], function(page, mocks){

    var LazyTab = mocks.store['components/lazytab'];
    var m1 = mocks.store['app/pages/m1'];
    var m2 = mocks.store['app/pages/m2'];

    describe("modules", function(){
        it("should have called lazyTab.init", fucntion(){
            var p = page.create();
            expect(lazyTab.init).toHaveBeenCalled();
        });
    });
});

});

I have to repeat the locations of the module three times. Is there something like .store('*')

Cannot mock an array

If the required module you are trying to mock is a simple array:

"use strict";
define('emptyArray', function() {
    return [];
});
"use strict";
define('thingToTest', ['emptyArray'], function(emptyArray) {
    if (emptyArray.length > 0) {
        return false;
    } else {
        return true;
    }
});

And you need to mock it to contain specific items for a test:

"use strict";
define(["squire"], function(Squire) {
    describe("thingToTest", function() {
        it("Will fail as squire can't mock an array", function() {
            var thingToTest;
            var emptyArrayMock;
            var ready;

            emptyArrayMock = [{},{},{}];

            new Squire()
                .mock('emptyArray', emptyArrayMock)
                .require(['thingToTest'], function(thing) {
                    thingToTest = thing;
                    ready = true;
                });

            waitsFor(function() {
                return ready;
            });

            runs(function() {
                expect(thingToTest).toEqual(false);
            });
        });
    });
});

SquireJS will assign nothing to the dependency, leaving it undefined.

Karma require.js do not work with squire

Hi

i want to run the following snippet:

define(['fixtures/squired'], function(Squire){
    describe("test", function(){
        it("etestset", function(done){
                injector = new Squire();
                injector.mock("jquery", {})
                .require(['utilities/Calculator'], function(Calculator) {
                    done();
                });
        })
    })
});

The fixtures/squired file looks like:

/*jslint white: true */
define(['Squire'], function(Squire) {
    'use strict';
    return Squire;
});

My test looks like:

define(['fixtures/squired'], function(Squire){
    describe("test", function(){
        it("should better work", function(done){
                injector = new Squire();
                injector.mock("jquery", {})
                .require(['utilities/Calculator'], function(Calculator) {
                    done();
                });
        })
    })
});

It runs with karma, but the tests are running bad. For example karma says sth. like
Executed 2 of 1 SUCCESS on the next run it outputs sth. like Executed 38 of 1 SUCCESS

Any idea what i am doing wrong? There seems some kind of recursion call somewhere :(

Calling `require()` or `run()` without a dependency on `'mocks'` does not run test

Using mocha, if I write a test like:

suite("main", function() {
    var Squire = requirejs('squirejs');
    var injector = new Squire();
    var myStub;
    setup("setup", function() {
        myStub = { someObjectDefinition: true };
        injector.mock("myModule/someDependency", myStub);
    }
    teardown("teardown", function() {
        injector.clean();
    }
    test("Some test", injector.run(["myModule"], function(myModule) {
        // Test something
        assert.isTrue(whatever);
    }));
});

...the test never runs. If I change injector.run(["myModule", function(myModule) { ... }) to injector.run(["myModule", "mocks"], function(myModule, mock) {...}, the test runs, even though I have no use for the mock parameter. The same issue seems to occur when using injector.require within the test function instead of using injector.run as the test function.

Squire: requirejs is not defined

Hi. I'm trying to use squire with Mocha and Gulp on a front end project.

var chai = require('chai')
  , requirejs = require("requirejs")
  , assert = require("assert")
  , should = require("should")
  , define = require('amdefine/intercept')
  ;

requirejs.config({
  baseUrl: 'components',
  nodeRequire: require
});

var Squire = requirejs("squirejs");

describe('Test', function() {
  var injector = new Squire()
    , Service
    ;

  injector
    .mock('foo', {
      foo : function() {
        return "foofoo"; /* instead of just foo */
      }
    });

  beforeEach(function(done) {

    injector.require(["service"], function(service) {
        Service = service;
        done();
      });
  });

  it('Should be 2.', function() {
    console.log('it');
  });

});

but I catch this error in Squire module:

ReferenceError: requirejs is not defined
    at getContext (node_modules/squirejs/src/Squire.js:58:12)
    at Squire.configure (node_modules/squirejs/src/Squire.js:107:15)
    at new Squire (node_modules/squirejs/src/Squire.js:82:20)
    at Suite.<anonymous> (service.test.js:18:18)
    at context.describe.context.context (node_modules/gulp-mocha/node_modules/mocha/lib/interfaces/bdd.js:49:10)
    at Object.<anonymous> (service.test.js:16:1)

Where is my mistake?

I've found also this gist, but it looks equal to mine.

Starting tests as part of config results in multiple executions

requirejs.config({
  baseUrl: '/base/app',
  //etc

  // ask Require.js to load these files (all our tests)
  deps: ['test1', 'test2'],

  // start test run, once Require.js is done
  callback: window.__karma__.start
});

According to the karma guide for requirejs this is how you should do it.

It seems Squire when creating a new instance is using this config and refires the callback function, meaning it runs the tests multiple times.

Resolved it with using no deps and callback in the config, but rather calling require(tests, window.__karma__.start); after the config call.

I do not know if it is because of a bug in Squire, or if this is expected behaviour. But it would have been nice if this was warned about in the squire README.

Something like, "any original callbacks on the config will be fired again when you do new Squire().require([...], callback)

copying contexts

Is there a reason why the contexts are being copied as opposed to using the existing references, https://github.com/iammerrick/Squire.js/blob/master/src/Squire.js#L121? Would it be possible to just return a loader that uses the same context reference?

A use case was presented in which creating a new context was causing errors because when instanceofwas used to test the return value of a module it differed because the value being tested was loaded in a different context. The expectation was that since no context was explicitly defined that the default context _ reference would be used not a new context created with same configuration.

Squire fails to load dependecy

Working with karma, jasmine and requirejs. My test-main in karma is defined as follows:

var tests = [];
for (var file in window.__karma__.files) {
    if (window.__karma__.files.hasOwnProperty(file)) {
        if (/Spec\.js$/.test(file)) {
            tests.push(file);
        }
    }
}

requirejs.config({
    // Karma serves files from '/base'
    baseUrl: '/base/src/js',

    paths: {
        'squire': '/base/node_modules/squirejs/src/Squire'
    },

    // ask Require.js to load these files (all our tests)
    deps: tests,

    // start test run, once Require.js is done
    callback: window.__karma__.start
});

Which is pretty normal as I understand. It loads a single test file:

define(['squire'],function(Squire) {
    var injector = new Squire();

    // describe('test',function() {
    //     it('should pass',function() {
    //         expect(true).toBe(true);
    //     });
    // });
    //
    console.log(injector);

    injector.require(['services/fs-nw'],function(fs) {
        console.log('fs');
        describe('test',function() {
            it('should pass',function() {
                expect(true).toBe(true);
            });
        });
    },function() {
        console.log('fail');
    });
});

And it doen't run any test, somehow, the factory function is not executed, nor is the error callback. Without squire, like so:

define(['services/fs-nw'],function(fs) {
    console.log('fs');
    describe('test',function() {
        it('should pass',function() {
            expect(true).toBe(true);
        });
    });
});

it works like a charm. Any ideas?

Problem installing using Twitter Bower

First, this is an awesome project. It's been very handy in a new Yeoman project I'm working on. Cheers!

Second, I had some trouble installing with Twitter Bower. I got the error:

grunt-mocha not found

I fixed it in the attached PR.

With Jasmine.js Tests Run Always Positive No Matter What Inside the Mock Function

I'm using Require.js to use AMD in my project. I use it in my project and in my Jasmine tests with no problems.

I'm using Squire.js to mock my DAO classes in my Services. When I expect the test to fail in a simple as a true to be false, the test should fail but it does not fail. Even expect 2 to be 3 runs positive and green but only inside the require space like so:

define(
[
"Squire",
"DAO/MockUserDAO"
],
function(Squire,MockUserDAO){
describe("UserService",function(){

    it("should return an array of  4 users on getAll()",function(){

        var squire = new Squire();

        squire.mock(["DAO/UserDAO"],MockUserDAO)
            .require(["services/UserService"], function(UserService){
                        var userCount = UserService.getAll().length;
                        expect(2).toBe(1);  // DOES NOT FAIL!
                    }); 

    });

    it("should return true",function(){
        expect(true).toBe(false);  // FAILS as expected
    });


}); 

}

Squire makes the test cases to run twice.

I have started using Squire.js along with my karma-mocha setup.

The problem I'm facing is the test cases which does uses Squire, something like this:

new Squire();

Those test cases alone runs twice. I really don't know whats the issue with this.

I have even tried turning off autowatch in karma config to off. But still the same issue.

Require Plugins

Would it be possible to add an example of how to mock a Require plugin using Squire? Is this supported...?

Squire Mock with CanJS

When mocking a module that has a dependency to canJS, I get the following error: Uncaught TypeError: Cannot read property 'setup' of undefined. If I remove canJS as depedency marked as "can" it works.

  // Code: simple object having a dependency to CanJS
  define(["can"],function(can){ return {id = 1}; }); 

 // Test
 define(
   [
    "Squire",
    "DAO/MockWebsiteDAO"
  ],
function(Squire,MockWebsiteDAO){
    describe("WebsiteControllerTest",function(){  
        var async = new AsyncSpec(this);

        async.it("should return all websites as an array",function(done){
            var squire = new Squire();
            squire.mock(["DAO/WebsiteDAO"],MockWebsiteDAO).require(["controllers/TestController"], function(TestController){
                            // fails because of the canJS dependency in TestController
                            done();
                        });  


        });

    }); 

});

trace:

can.Control.can.Construct._isAction control.js:95
can.Control.can.Construct.setup control.js:63
can.extend.extend construct.js:165
can.Construct construct.js:21
(anonymous function) control.js:43
j.execCb require.js:28
W.check require.js:18
(anonymous function) require.js:22
(anonymous function) require.js:8
(anonymous function) require.js:23
x require.js:7
W.emit require.js:23
W.check require.js:19
(anonymous function) require.js:22
(anonymous function) require.js:8
(anonymous function) require.js:23
x require.js:7
W.emit require.js:23
W.check require.js:19
(anonymous function) require.js:22
(anonymous function) require.js:8
(anonymous function) require.js:23
x require.js:7
W.emit require.js:23
W.check require.js:19
(anonymous function) require.js:22
(anonymous function) require.js:8
(anonymous function) require.js:23
x require.js:7
W.emit require.js:23
W.check require.js:19
(anonymous function) require.js:22
(anonymous function) require.js:8
(anonymous function) require.js:23
x require.js:7
W.emit require.js:23
W.check require.js:19
W.enable require.js:22
W.init require.js:16
D require.js:14
j.completeLoad require.js:27
j.onScriptLoad require.js:29

Make it work with Karma runner?

Not sure if this will be an issue for Squire or for Karma, but I'm trying to use it and nothing seems to happen:

it('should have Squire working', function (done) {
  var injector = new Squire();
  expect(injector).to.be.an.instanceOf(Squire); // passes
  console.log('trying to load...');
  injector.require(['my/dependency'], function(MyDepencency) {
    console.log('loaded');
    expect(MyDepencency).to.not.exist;
    done();
  }, function (err) {
    console.log('err');
    console.log(err);
    done();
  });

Here after "trying to load..." nothing else logs.

After digging a bit more, I realised that requirejs variable in your Squire.prototype.configure is null, and it should have the requirejs function.

Or is there any configuration that I missed? Did you manage to get it working with Karma?

Unable to mock/store dependency that is relative

Hi,

I'm trying to mock a dependency for a module that contains the following:

foo = require('./bar');

but neither mock nor store seems to work. Is there a way to do this?

If I change the path to something like foo/bar/baz then it works, but that would be very annoying to change in every case where the dependency is in the same directory.

Thanks

Fire event when container.require calls back?

I am trying to use Squire with some mocha tests and PhantomJS. The tests suites all initialize a Squire container, put in some stubs, and then call container.require to require the file to test. They then define the Mocha tests inside the callback to container.require.

The problem is, we only want to call mocha.run() to start the tests once all the tests are defined. We could put special logic in all our tests to fire events after the tests were defined, but that clutters up the tests with something that isn't really their problem.

Could container emit an event once the callback was called so we know when the tests are defined and ready to run? Do you have any other ideas around this problem?

Feature request: support aliases of stored mocks

It would be great when using store with a string, to be able to pass in an alias for the stored mock so that we can easily grab it.

This turns this:

new Squire()
    .store('my/longComplicated/stored/mockName')
    .require(['moduleUnderTest', 'mocks'], function(module, mocks) {
      var mock = mocks['my/longComplicated/stored/mockName'];
    });

into this:

new Squire()
    .store('my/longComplicated/stored/mockName', 'mymock')
    .require(['moduleUnderTest', 'mocks'], function(module, mocks) {
      var mock = mocks.mymock;
    });

If it is a desired feature I can probably create a PR myself.

Load Order Issues

I am trying to use Squire to help bring test coverage to a fairly complicated application (200+ coffeescript files) and am running into some timing depended load issues. I have managed to create a simple example app that sometimes demonstrates the problem.

The problem is simply this. We are using jQuery and a jQuery plugin called BlockUI, that later is in turn used in a several views. All is fine in normal usage, but when we use Squire to load the view for testing, jQuery and BlockUI both get loaded twice (once on the default context, once in "context0"). This is because we have two specs. One that uses squire and one that does not.

If everything goes well (about 80% of the time on my machine) the load order is jQuery in the default context, BlockUI in the default context, jQuery in context0, blockUI in context0. The rest of the time, both jQuery instances load first, followed by both BlockUI instances. This causes both BlockUI instances to plug into the second jQuery instance. Consequently the tests that try to use BlockUI on the first instance blow up as $.blockUI is undefined in that case.

I can reproduce this issue in both Chrome and Firefox, but would expect to see it in any browser.

In the aforementioned example app, just run the ./test.sh script. Then in the browser, turn off caching and hit refresh several times till the problem appears (as a failing test).

In the example I have inserted logging code into both jQuery and BlockUI to track instances identity and log what is going on. A good log looks like this:

JQuery init: 1
JQuery.blockUI init: 2 with jQuery: 1
JQuery init: 3
JQuery.blockUI init: 4 with jQuery: 3

A log showing the issue looks like this:

JQuery init: 1 
JQuery init: 2
JQuery.blockUI init: 3 with jQuery: 2
JQuery.blockUI init: 4 with jQuery: 2

AssertionError: $.blockUI was undefined in example-view: expected undefined to not equal undefined
    at Assertion.assertEqual (http://localhost:7357/4673/.mimosa/testemRequire/chai.js:862:12)
    at Assertion.ctx.(anonymous function) [as equal] (http://localhost:7357/4673/.mimosa/testemRequire/chai.js:3048:25)
    at Function.assert.isDefined (http://localhost:7357/4673/.mimosa/testemRequire/chai.js:2073:36)
    at Context.<anonymous> (http://localhost:7357/js/app/example-squire-spec.js:13:23)
    at Test.Runnable.run (http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:3726:32)
    at Runner.runTest (http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:4081:10)
    at http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:4127:12
    at next (http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:4007:14)
    at http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:4016:7
    at next (http://localhost:7357/4673/.mimosa/testemRequire/mocha.js:3964:23)

It seems to me that a solution to this would be to be able to configure Squire with a list of assets that should never be reloaded but rather should be shared across contexts. It should then be an error to ever specify one of those assets' identifiers to .mock().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.