Giter VIP home page Giter VIP logo

jasmine-co's Introduction

Build Status

Table of Contents

jasmine-co

jasmine-co is a simple Jasmine 2.x adapter that allows you to use co and ES6 generator functions to greatly simplify your asynchronous test code using synchronous patterns.

jasmine-co also enables you to return promises from your specs without manually worrying about handling Jasmine's done callback. For you TypeScript fans, this means you can trivially use async/await.

Testing asynchronous functions doesn't have to be painful.

Requirements

  1. NodeJS with support for generators
    • you can use [email protected] with --harmony
    • or save yourself some trouble and just use [email protected] which enables support for generators, arrow functions, and other ES6 features by default
  2. Jasmine 2.x

Quick Start

  1. Install jasmine-co
    • globally, e.g. in a helpers file
    • install / uninstall within a specific describe block
    • install / uninstall for a specific it
    • one-off usage
    • etc.
  2. Write tests as normal, but instead of using function + done, either...
    • use function* and yield, or
    • a function that returns a promise (thennable)
  3. That's it.
Installed globally
// spec/helpers/jasmine-co.helper.js
require('jasmine-co').install();

// spec/bookService.spec.js
describe("user models", function() {
    beforeEach(function*(){
        this.user = yield getUser(1);
    });

    it("should be able to get a list of owned books", function*() {
        var books = yield bookService.getBooksForUser(this.user);
        expect(books).toEqual(jasmine.any(Array));
    });

    it("should also work when promises are returned", function() {
        return bookService.getBooksForUser(this.user).then(function(books) {
            expect(books).toEqual(jasmine.any(Array));
        });
    });
});
Installed temporarily
// spec/bookService.spec.js
var jasmineCo = require('jasmine-co');
describe("user models", function() {
    // install jasmine-co for methods in this describe block
    jasmineCo.install();

    beforeEach(function*(){
        this.user = yield getUser(1);
    });

    it("should be able to get a list of owned books", function*() {
        var books = yield bookService.getBooksForUser(this.user);
        expect(books).toEqual(jasmine.any(Array));
    });

    it("should also work when promises are returned", function() {
        return bookService.getBooksForUser(this.user).then(function(books) {
            expect(books).toEqual(jasmine.any(Array));
        });
    });

    // clean up
    jasmineCo.uninstall();
});
One-off usage
// spec/bookService.spec.js
var jasmineCo = require('jasmine-co');
describe("user models", function() {
    // use jasmine-co as a one-off
    beforeEach(jasmineCo(function*(){
        this.user = yield getUser(1);
    }));

    // use jasmine-co as a one-off again
    it("should be able to get a list of owned books", jasmineCo(function*() {
        var books = yield bookService.getBooksForUser(this.user);
        expect(books).toEqual(jasmine.any(Array));
    }));

    // use jasmine-co as a one-off for a promise-returning spec
    it("should also work when promises are returned", function() {
        return bookService.getBooksForUser(this.user).then(function(books) {
            expect(books).toEqual(jasmine.any(Array));
        });
    });
});
TypeScript async/await example
// spec/helpers/jasmine-co.helper.js
require('jasmine-co').install();

// spec/bookService.spec.ts
describe("user models", function() {
    beforeEach(async function(){
        this.user = await getUser(1);
    });

    it("should be able to get a list of owned books", async function() {
        var books = await bookService.getBooksForUser(this.user);
        expect(books).toEqual(jasmine.any(Array));
    });
});

Comparison / Examples

How does jasmine-co actually help you clean up your test code? To answer that question, consider the following examples.

All examples are functionally equivalent.

1. Promises
beforeEach(function(done) {
    var self = this;
    userService.getUser(1).then(function(user) {
        self.user = user;
        return bookService.getBooksForUser(user);
    }).then(function(books) {
        self.books = books;
    }).then(done, done.fail);
});

it('should track books that are listed for sale', function(done) {
    var self = this;
    var book = this.books[0];
    book.listForSale(3.99).then(function() {
        return bookService.getBooksListedForSaleByUser(self.user);
    }).then(function(forSale) {
        expect(forSale[0].isbn).toEqual(book.isbn);
    }).then(done, done.fail);
});
2. Using co directly
var co = require('co');
beforeEach(function(done) {
    var self = this;
    co(function*() {
        self.user = yield userService.getUser(1);
        self.books = yield bookService.getBooksForUser(self.user);
    }).then(done, done.fail);
});

it('should track books that are listed for sale', function(done) {
    var self = this;
    var book = this.books[0];
    co(function*() {
        yield book.listForSale(3.99);
        var forSale = yield bookService.getBooksListedForSaleByUser(self.user);
        expect(forSale[0].isbn).toEqual(book.isbn);
    }).then(done, done.fail);
});
3. Using jasmine-co
require('jasmine-co').install();
beforeEach(function*() {
    this.user = yield userService.getUser(1);
    this.books = yield bookService.getBooksForUser(this.user);
});

it('should track books that are listed for sale', function*() {
    var book = this.books[0];
    yield book.listForSale(3.99);
    var forSale = yield bookService.getBooksListedForSaleByUser(this.user);
    expect(forSale[0].isbn).toEqual(book.isbn);
});

License

This software is licensed under the MIT License.

jasmine-co's People

Contributors

pishposh avatar putermancer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

pishposh

jasmine-co's Issues

await expression is only allowed within an async function

I tried to follow the TS example from the readme but I'm confused how TS is supposed to know that it is an async function.

I call require('jasmine-co').install(); but I still get error await expression is only allowed within an async function as the definition files still point to @types\jasmine\index.d.ts

Do I have to update the definition files from jasmine-co?

Tests marked as passed while they should fail

I recreated the example in typescript:

function getUser(userId: number): Promise<string> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(`user${userId}`);
        }, 1000);
    })
}

function getBooksForUser(user: string): Promise<string[]> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(['book1', 'book2']);
        }, 1000);
    })
}

// spec/bookService.spec.ts
describe("user models", function () {
    beforeEach(async function () {
        this.user = await this.getUser(1);
    });

    it("should be able to get a list of owned books", async function () {
        var books = await this.getBooksForUser(this.user);
        expect(books).toEqual('test');
    });
});

And when running the tests it takes a while for it to complete, but it always passes:
Chrome 55.0.2883 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (6.419 secs / 0.005 secs)

When moving the expect above the var books... statement, it will correctly fail.

Add support for custom timeout interval

Allow to pass in 3rd argument to it to set default timeout interval. Change should be fairly easy:

        // ...
        if (isGeneratorFn(userFn)) {
            // ...
            args = [function(done) {
                return co(userFn.bind(this)).then(done, done.fail);
            }];

            // do a check for 3rd argument
            var customTimeout = arguments[2];
            if (customTimeout){
                args.push(customTimeout);
            }

            if (expectsName) { args.unshift(arguments[0]); }
            return origFn.apply(null, args);
        } else if // ...

You'd probably also have to do a check to make sure it's an it function.

ES6 let used outside strict mode

On Node 4.4.0, getting the following error:

/Users/ben/Dev/Git/.../node_modules/jasmine-co/index.js:66
                let result = userFn.call(this);
                ^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

`this` not created when describe uses `() =>` syntax instead of `function ()` syntax

Like the title says,

describe("Applying", async () => {

  const jasmineCo = require('jasmine-co');
  jasmineCo.install();

  beforeEach(async () => {
    this;  //undefined

notice that this is undefined.
Changing the describe to use a function instead results in this populating properly

describe("Applying", function () {

  const jasmineCo = require('jasmine-co');
  jasmineCo.install();

  beforeEach(async () => {
    this;  //defined

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.