angelakuo/citydogshare

View on GitHub
public/assets/spec/core/integration/EnvSpec-efa0357e647d1a0069b356277458a54d5b7136f39d3cd1abdd88e60bbf85915b.js

Summary

Maintainability
F
3 days
Test Coverage
describe("Env integration", function() {
  beforeEach(function() {
    jasmine.addMatchers({
      toHaveFailedExpecationsForRunnable: function(util, customeEqualityTesters) {
        return {
          compare: function(actual, fullName, expectedFailures) {
            var foundRunnable = false, expectations = true, foundFailures = [];
            for (var i = 0; i < actual.calls.count(); i++) {
              var args = actual.calls.argsFor(i)[0];

              if (args.fullName === fullName) {
                foundRunnable = true;

                for (var j = 0; j < args.failedExpectations.length; j++) {
                  foundFailures.push(args.failedExpectations[j].message);
                }

                for (var j = 0; j < expectedFailures.length; j++) {
                  var failure = foundFailures[j];
                  var expectedFailure = expectedFailures[j];

                  if (Object.prototype.toString.call(expectedFailure) === '[object RegExp]') {
                    expectations = expectations && expectedFailure.test(failure);
                  } else {
                    expectations = expectations && failure === expectedFailure;
                  }
                }
                break;
              }
            }

            return {
              pass: foundRunnable && expectations,
              message: !foundRunnable ? 'The runnable "' + fullName + '" never finished' :
                'Expected runnable "' + fullName + '" to have failures ' + jasmine.pp(expectedFailures) + ' but it had ' + jasmine.pp(foundFailures)
            };
          }
        };
      }
    });
  });

  it("Suites execute as expected (no nesting)", function(done) {
    var env = new jasmineUnderTest.Env(),
        calls = [];

    var assertions = function() {
      expect(calls).toEqual([
        "with a spec",
        "and another spec"
      ]);

      done();
    };

    env.addReporter({ jasmineDone: assertions});

    env.describe("A Suite", function() {
      env.it("with a spec", function() {
        calls.push("with a spec");
      });
      env.it("and another spec", function() {
        calls.push("and another spec");
      });
    });

    env.execute();
  });

  it("Nested Suites execute as expected", function(done) {
    var env = new jasmineUnderTest.Env(),
        calls = [];

    var assertions = function() {
      expect(calls).toEqual([
        'an outer spec',
        'an inner spec',
        'another inner spec'
      ]);

      done();
    };

    env.addReporter({ jasmineDone: assertions });

    env.describe("Outer suite", function() {
      env.it("an outer spec", function() {
        calls.push('an outer spec')
      });
      env.describe("Inner suite", function() {
        env.it("an inner spec", function() {
          calls.push('an inner spec');
        });
        env.it("another inner spec", function() {
          calls.push('another inner spec');
        });
      });
    });

    env.execute();
  });

  it("Multiple top-level Suites execute as expected", function(done) {
    var env = new jasmineUnderTest.Env(),
        calls = [];

    var assertions = function() {
      expect(calls).toEqual([
        'an outer spec',
        'an inner spec',
        'another inner spec',
        'a 2nd outer spec'
      ]);

      done();
    };

    env.addReporter({ jasmineDone: assertions });


    env.describe("Outer suite", function() {
      env.it("an outer spec", function() {
        calls.push('an outer spec');
      });
      env.describe("Inner suite", function() {
        env.it("an inner spec", function() {
          calls.push('an inner spec');
        });
        env.it("another inner spec", function() {
          calls.push('another inner spec');
        });
      });
    });

    env.describe("Another outer suite", function() {
      env.it("a 2nd outer spec", function() {
        calls.push('a 2nd outer spec')
      });
    });

    env.execute();
  });

  it('explicitly fails a spec', function(done) {
    var env = new jasmineUnderTest.Env(),
        specDone = jasmine.createSpy('specDone');

    env.addReporter({
      specDone: specDone,
      jasmineDone: function() {
        expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
          description: 'has a default message',
          failedExpectations: [jasmine.objectContaining({
            message: 'Failed'
          })]
        }));
        expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
          description: 'specifies a message',
          failedExpectations: [jasmine.objectContaining({
            message: 'Failed: messy message'
          })]
        }));
        expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
          description: 'has a message and stack trace from an Error',
          failedExpectations: [jasmine.objectContaining({
            message: 'Failed: error message',
            stack: {
              asymmetricMatch: function(other) {
                if (!other) {
                  // IE doesn't give us a stacktrace so just ignore it.
                  return true;
                }
                var split = other.split('\n'),
                    firstLine = split[0];
                if (firstLine.indexOf('error message') >= 0) {
                  // Chrome inserts the message and a newline before the first stacktrace line.
                  firstLine = split[1];
                }
                return firstLine.indexOf('EnvSpec') >= 0;
              }
            }
          })]
        }));
        done();
      }
    });

    env.describe('failing', function() {
      env.it('has a default message', function() {
        env.fail();
      });

      env.it('specifies a message', function() {
        env.fail('messy message');
      });

      env.it('has a message and stack trace from an Error', function() {
        env.fail(new Error('error message'));
      });
    });

    env.execute();
  });


  it("calls associated befores/specs/afters with the same 'this'", function(done) {
    var env = new jasmineUnderTest.Env();

    env.addReporter({jasmineDone: done});
    env.describe("tests", function() {
      var firstTimeThrough = true, firstSpecContext, secondSpecContext;

      env.beforeEach(function() {
        if (firstTimeThrough) {
          firstSpecContext = this;
        } else {
          secondSpecContext = this;
        }
        expect(this).toEqual({});
      });

      env.it("sync spec", function() {
        expect(this).toBe(firstSpecContext);
      });

      env.it("another sync spec", function() {
        expect(this).toBe(secondSpecContext);
      });

      env.afterEach(function() {
        if (firstTimeThrough) {
          expect(this).toBe(firstSpecContext);
          firstTimeThrough = false;
        } else {
          expect(this).toBe(secondSpecContext);
        }
      });
    });

    env.execute();
  });

  it("calls associated befores/its/afters with the same 'this' for an async spec", function(done) {
    var env = new jasmineUnderTest.Env();

    env.addReporter({jasmineDone: done});

    env.describe("with an async spec", function() {
      var specContext;

      env.beforeEach(function() {
        specContext = this;
        expect(this).toEqual({});
      });

      env.it("sync spec", function(underTestCallback) {
        expect(this).toBe(specContext);
        underTestCallback();
      });

      env.afterEach(function() {
        expect(this).toBe(specContext);
      });
    });

    env.execute();
  });

  it("calls associated beforeAlls/afterAlls only once per suite", function(done) {
    var env = new jasmineUnderTest.Env(),
        before = jasmine.createSpy('beforeAll'),
        after = jasmine.createSpy('afterAll');

    env.addReporter({
      jasmineDone: function() {
        expect(after).toHaveBeenCalled();
        expect(after.calls.count()).toBe(1);
        expect(before.calls.count()).toBe(1);
        done();
      }
    });

    env.describe("with beforeAll and afterAll", function() {
      env.it("spec", function() {
        expect(before).toHaveBeenCalled();
        expect(after).not.toHaveBeenCalled();
      });

      env.it("another spec", function() {
        expect(before).toHaveBeenCalled();
        expect(after).not.toHaveBeenCalled();
      });

      env.beforeAll(before);
      env.afterAll(after);
    });

    env.execute();
  });

  it("calls associated beforeAlls/afterAlls only once per suite for async", function(done) {
    var env = new jasmineUnderTest.Env(),
        before = jasmine.createSpy('beforeAll'),
        after = jasmine.createSpy('afterAll');

    env.addReporter({
      jasmineDone: function() {
        expect(after).toHaveBeenCalled();
        expect(after.calls.count()).toBe(1);
        expect(before.calls.count()).toBe(1);
        done();
      }
    });

    env.describe("with beforeAll and afterAll", function() {
      env.it("spec", function() {
        expect(before).toHaveBeenCalled();
        expect(after).not.toHaveBeenCalled();
      });

      env.it("another spec", function() {
        expect(before).toHaveBeenCalled();
        expect(after).not.toHaveBeenCalled();
      });

      env.beforeAll(function(beforeCallbackUnderTest) {
        before();
        beforeCallbackUnderTest();
      });

      env.afterAll(function(afterCallbackUnderTest) {
        after();
        afterCallbackUnderTest();
      });
    });

    env.execute();
  });

  it("calls associated beforeAlls/afterAlls with the cascaded 'this'", function(done) {
    var env = new jasmineUnderTest.Env();

    env.addReporter({jasmineDone: done});

    env.describe("with beforeAll and afterAll", function() {
      env.beforeAll(function() {
        this.x = 1;
      });

      env.it("has an x at the root", function() {
        expect(this.x).toBe(1);
      });

      env.describe("child that deletes", function() {
        env.beforeAll(function() {
          expect(this.x).toBe(1);
          delete this.x;
        });

        env.it("has no x", function() {
          expect(this.x).not.toBeDefined();
        });
      });

      env.describe("child should still have x", function() {
        env.beforeAll(function(innerDone) {
          expect(this.x).toBe(1);
          innerDone();
        });

        env.it("has an x", function() {
          expect(this.x).toBe(1);
          delete this.x;
        });

        env.it("still has an x", function() {
          expect(this.x).toBe(1);
        });

        env.it("adds a y", function() {
          this.y = 2;
          expect(this.y).toBe(2);
        });

        env.it("doesn't have y that was added in sibling", function() {
          expect(this.y).not.toBeDefined();
        });
      });
    });

    env.execute();
  });

  it("fails all underlying specs when the beforeAll fails", function (done) {
    var env = new jasmineUnderTest.Env(),
      reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]);

    reporter.jasmineDone.and.callFake(function() {
      expect(reporter.specDone.calls.count()).toEqual(2);

      expect(reporter.specDone.calls.argsFor(0)[0])
        .toEqual(jasmine.objectContaining({status: 'failed'}));
      expect(reporter.specDone.calls.argsFor(0)[0].failedExpectations[0].message)
        .toEqual("Expected 1 to be 2.");

      expect(reporter.specDone.calls.argsFor(1)[0])
        .toEqual(jasmine.objectContaining({status: 'failed'}));
      expect(reporter.specDone.calls.argsFor(1)[0].failedExpectations[0].message)
        .toEqual("Expected 1 to be 2.");
      done();
    });

    env.addReporter(reporter);

    env.describe('A suite', function(){
      env.beforeAll(function() {
        env.expect(1).toBe(2);
      });

      env.it("spec that will be failed", function() {
      });

      env.describe("nesting", function() {
        env.it("another spec to fail", function() {
        });
      });
    });

    env.execute();
  });

  describe('suiteDone reporting', function(){
    it("reports when an afterAll fails an expectation", function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('my suite', [
          'Expected 1 to equal 2.',
          'Expected 2 to equal 3.'
        ]);
        done();
      });

      env.addReporter(reporter);

      env.describe('my suite', function() {
        env.it('my spec', function() {
        });

        env.afterAll(function() {
          env.expect(1).toEqual(2);
          env.expect(2).toEqual(3);
        });
      });

      env.execute();
    });

    it("if there are no specs, it still reports correctly", function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('outer suite', [
          'Expected 1 to equal 2.',
          'Expected 2 to equal 3.'
        ]);
        done();
      });

      env.addReporter(reporter);

      env.describe('outer suite', function() {
        env.describe('inner suite', function() {
          env.it('spec', function(){ });
        });

        env.afterAll(function() {
          env.expect(1).toEqual(2);
          env.expect(2).toEqual(3);
        });
      });

      env.execute();
    });

    it("reports when afterAll throws an exception", function(done) {
      var env = new jasmineUnderTest.Env(),
        error = new Error('After All Exception'),
        reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('my suite', [
          (/^Error: After All Exception/)
        ]);
        done();
      });

      env.addReporter(reporter);

      env.describe('my suite', function() {
        env.it('my spec', function() {
        });

        env.afterAll(function() {
          throw error;
        });
      });

      env.execute();
    });

    it("reports when an async afterAll fails an expectation", function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('my suite', [
          'Expected 1 to equal 2.'
        ]);
        done();
      });

      env.addReporter(reporter);

      env.describe('my suite', function() {
        env.it('my spec', function() {
        });

        env.afterAll(function(afterAllDone) {
          env.expect(1).toEqual(2);
          afterAllDone();
        });
      });

      env.execute();
    });

    it("reports when an async afterAll throws an exception", function(done) {
      var env = new jasmineUnderTest.Env(),
        error = new Error('After All Exception'),
        reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);


      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('my suite', [
          (/^Error: After All Exception/)
        ]);
        done();
      });

      env.addReporter(reporter);

      env.describe('my suite', function() {
        env.it('my spec', function() {
        });

        env.afterAll(function(afterAllDone) {
          throw error;
        });
      });

      env.execute();
    });
  });

  it('cascades expecatation failures in global beforeAll down to children', function(done) {
    var env = new jasmineUnderTest.Env(),
      reporter = jasmine.createSpyObj(['specDone', 'jasmineDone']);

    reporter.jasmineDone.and.callFake(function(results) {
      expect(results.failedExpectations).toEqual([]);
      expect(reporter.specDone).toHaveFailedExpecationsForRunnable('is a spec', [
        'Expected 1 to be 0.'
      ]);
      done();
    });

    env.beforeAll(function() {
      env.expect(1).toBe(0);
    });

    env.it('is a spec', function() {
      env.expect(true).toBe(true);
    });

    env.addReporter(reporter);

    env.execute();
  });

  it('reports expectation failures in global afterAll', function(done) {
    var env = new jasmineUnderTest.Env(),
      reporter = jasmine.createSpyObj(['jasmineDone']);

    reporter.jasmineDone.and.callFake(function(results) {
      expect(results.failedExpectations).toEqual([jasmine.objectContaining({ message: 'Expected 1 to be 0.' })]);
      done();
    });

    env.afterAll(function() {
      env.expect(1).toBe(0);
    });

    env.it('is a spec', function() {
      env.expect(true).toBe(true);
    });

    env.addReporter(reporter);

    env.execute();
  });

  it("Allows specifying which specs and suites to run", function(done) {
    var env = new jasmineUnderTest.Env(),
        calls = [],
        suiteCallback = jasmine.createSpy('suite callback'),
        firstSpec,
        secondSuite;

    var assertions = function() {
      expect(calls).toEqual([
        'third spec',
        'first spec'
      ]);
      expect(suiteCallback).toHaveBeenCalled();
      done();
    };

    env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback});

    env.describe("first suite", function() {
      firstSpec = env.it("first spec", function() {
        calls.push('first spec');
      });
      env.it("second spec", function() {
        calls.push('second spec');
      });
    });

    secondSuite = env.describe("second suite", function() {
      env.it("third spec", function() {
        calls.push('third spec');
      });
    });

    env.execute([secondSuite.id, firstSpec.id]);
  });

  it('runs before and after all functions for runnables provided to .execute()', function(done) {
    var env = new jasmineUnderTest.Env(),
      calls = [],
      first_spec,
      second_spec;

    var assertions = function() {
      expect(calls).toEqual([
        "before",
        "first spec",
        "second spec",
        "after"
      ]);
      done();
    };

    env.addReporter({jasmineDone: assertions});

    env.describe("first suite", function() {
      env.beforeAll(function() {
        calls.push("before");
      });
      env.afterAll(function() {
        calls.push("after")
      });
      first_spec = env.it("spec", function() {
        calls.push('first spec');
      });
      second_spec = env.it("spec 2", function() {
        calls.push("second spec");
      });
    });

    env.execute([first_spec.id, second_spec.id]);
  });

  it("Functions can be spied on and have their calls tracked", function (done) {
    var env = new jasmineUnderTest.Env();

    var originalFunctionWasCalled = false;
    var subject = {
      spiedFunc: function() {
        originalFunctionWasCalled = true;
        return "original result";
      }
    };

    env.addReporter({jasmineDone: done});

    env.it("works with spies", function() {
      var spy = env.spyOn(subject, 'spiedFunc').and.returnValue("stubbed result");

      expect(subject.spiedFunc).toEqual(spy);
      expect(subject.spiedFunc.calls.any()).toEqual(false);
      expect(subject.spiedFunc.calls.count()).toEqual(0);

      subject.spiedFunc('foo');

      expect(subject.spiedFunc.calls.any()).toEqual(true);
      expect(subject.spiedFunc.calls.count()).toEqual(1);
      expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
      expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
      expect(subject.spiedFunc.calls.mostRecent().returnValue).toEqual("stubbed result");
      expect(originalFunctionWasCalled).toEqual(false);

      subject.spiedFunc.and.callThrough();
      subject.spiedFunc('bar');
      expect(subject.spiedFunc.calls.count()).toEqual(2);
      expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
      expect(subject.spiedFunc.calls.mostRecent().returnValue).toEqual("original result");
      expect(originalFunctionWasCalled).toEqual(true);
    });

    env.execute();
  });

  it('can be configured to allow respying on functions', function () {
    var env = new jasmineUnderTest.Env(),
        foo = {
          bar: function () {
            return 1;
          }
        };

    env.allowRespy(true);

    env.describe('test suite', function(){
      env.it('spec 0', function(){
        env.spyOn(foo,'bar');

        var error = null;

        expect(function() {
          env.spyOn(foo, 'bar');
        }).not.toThrow();
      });
    });

    env.execute();
  });

  it('removes all spies added in a spec after the spec is complete', function(done) {
    var env = new jasmineUnderTest.Env(),
      originalFoo = function() {},
      testObj = {
        foo: originalFoo
      },
      firstSpec = jasmine.createSpy('firstSpec').and.callFake(function() {
        env.spyOn(testObj, 'foo');
      }),
      secondSpec = jasmine.createSpy('secondSpec').and.callFake(function() {
        expect(testObj.foo).toBe(originalFoo);
      });
      env.describe('test suite', function() {
        env.it('spec 0', firstSpec);
        env.it('spec 1', secondSpec);
      });

    var assertions = function() {
      expect(firstSpec).toHaveBeenCalled();
      expect(secondSpec).toHaveBeenCalled();
      done();
    };

    env.addReporter({ jasmineDone: assertions });

    env.execute();
  });

  it('removes all spies added in a suite after the suite is complete', function(done) {
    var env = new jasmineUnderTest.Env(),
      originalFoo = function() {},
      testObj = {
        foo: originalFoo
      };

      env.describe('test suite', function() {
        env.beforeAll(function() { env.spyOn(testObj, 'foo');})

        env.it('spec 0', function() {
          expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(true);
        });

        env.it('spec 1', function() {
          expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(true);
        });
      });

      env.describe('another suite', function() {
        env.it('spec 2', function() {
          expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(false);
        });
      });

    env.addReporter({ jasmineDone: done });

    env.execute();
  });

  it('removes a spy from the top suite after the run is complete', function(done) {
    var env = new jasmineUnderTest.Env(),
      originalFoo = function() {},
      testObj = {
        foo: originalFoo
      };

    env.beforeAll(function() {
      env.spyOn(testObj, 'foo');
    });

    env.it('spec', function() {
      expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(true);
    });

    env.addReporter({
      jasmineDone: function() {
        expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(false);
        done();
      }
    });

    env.execute();
  });

  it("Mock clock can be installed and used in tests", function(done) {
    var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
        delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
        delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
        env = new jasmineUnderTest.Env({global: { setTimeout: globalSetTimeout }});

    var assertions = function() {
      expect(delayedFunctionForMockClock).toHaveBeenCalled();
      expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100);

      done();
    };

    env.addReporter({ jasmineDone: assertions });

    env.describe("tests", function() {
      env.it("test with mock clock", function() {
        env.clock.install();
        env.clock.setTimeout(delayedFunctionForMockClock, 100);
        env.clock.tick(100);
        env.clock.uninstall();
      });
      env.it("test without mock clock", function() {
        env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
      });
    });

    expect(globalSetTimeout).not.toHaveBeenCalled();
    expect(delayedFunctionForMockClock).not.toHaveBeenCalled();

    env.execute();
  });

  it("should run async specs in order, waiting for them to complete", function(done) {
    var env = new jasmineUnderTest.Env(), mutatedVar;

    env.describe("tests", function() {
      env.beforeEach(function() {
        mutatedVar = 2;
      });

      env.it("async spec", function(underTestCallback) {
        setTimeout(function() {
          expect(mutatedVar).toEqual(2);
          underTestCallback();
          done();
        }, 0);
      });

      env.it("after async spec", function() {
        mutatedVar = 3;
      });
    });

    env.execute();
  });

  describe("with a mock clock", function() {
    var originalTimeout;

    beforeEach(function() {
      originalTimeout = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
      jasmine.clock().install();
    });

    afterEach(function() {
      jasmine.clock().uninstall();
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });

    it("should wait a specified interval before failing specs haven't called done yet", function(done) {
      var env = new jasmineUnderTest.Env(),
          reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]);

      reporter.specDone.and.callFake(function() {
        expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
      });

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.jasmineDone.calls.count()).toEqual(1);
        done();
      });

      env.addReporter(reporter);
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 8414;

      env.it("async spec that doesn't call done", function(underTestCallback) {
        env.expect(true).toBeTruthy();
        jasmine.clock().tick(8416);
      });

      env.execute();
    });

    it("should wait a specified interval before failing beforeAll's and their associated specs that haven't called done", function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.specDone.calls.count()).toEqual(2);
        expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'failed'}));
        expect(reporter.specDone.calls.argsFor(1)[0]).toEqual(jasmine.objectContaining({status: 'failed'}));
        done();
      });

      env.addReporter(reporter);
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 1290;

      env.beforeAll(function(done) {
        jasmine.clock().tick(1290);
      });

      env.it("spec that will be failed", function() {
      });

      env.describe("nesting", function() {
        env.it("another spec to fail", function() {
        });
      });

      env.execute();
    });

    it("should not use the mock clock for asynchronous timeouts", function(){
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]),
        clock = env.clock;

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.specDone.calls.count()).toEqual(1);
        expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'passed'}));
      });

      env.addReporter(reporter);
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 5;

      env.beforeAll(function() {
        clock.install();
      });

      env.afterAll(function() {
        clock.uninstall();
      });

      env.it("spec that should not time out", function(done) {
        clock.tick(6);
        expect(true).toEqual(true);
        done();
      });

      env.execute();
    });

    it("should wait the specified interval before reporting an afterAll that fails to call done", function(done) {
      var env = new jasmineUnderTest.Env(),
      reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('my suite', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);
        done();
      });

      env.addReporter(reporter);
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 3000;

      env.describe('my suite', function() {
        env.it('my spec', function() {
        });

        env.afterAll(function(innerDone) {
          jasmine.clock().tick(3001);
          innerDone();
        });
      });

      env.execute();
    });

    it('should wait a custom interval before reporting async functions that fail to call done', function(done) {
      var env = new jasmineUnderTest.Env(),
          reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite beforeAll times out', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);

        expect(reporter.suiteDone).toHaveFailedExpecationsForRunnable('suite afterAll', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);

        expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite beforeEach times out', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);

        expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite afterEach times out', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);

        expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite it times out', [
          (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./)
        ]);

        done();
      });

      env.addReporter(reporter);
      jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 10000;

      env.describe('suite', function() {
        env.describe('beforeAll', function() {
          env.beforeAll(function(innerDone) {
            jasmine.clock().tick(5001);
            innerDone();
          }, 5000);

          env.it('times out', function() {});
        });

        env.describe('afterAll', function() {
          env.afterAll(function(innerDone) {
            jasmine.clock().tick(2001);
            innerDone();
          }, 2000);

          env.it('times out', function() {});
        });

        env.describe('beforeEach', function() {
          env.beforeEach(function(innerDone) {
            jasmine.clock().tick(1001);
            innerDone();
          }, 1000);

          env.it('times out', function() {});
        });

        env.describe('afterEach', function() {
          env.afterEach(function(innerDone) {
            jasmine.clock().tick(4001);
            innerDone();
          }, 4000);

          env.it('times out', function() {});
        });

        env.it('it times out', function(innerDone) {
          jasmine.clock().tick(6001);
          innerDone();
        }, 6000);
      });

      env.execute();
    });

    it('explicitly fails an async spec', function(done) {
      var env = new jasmineUnderTest.Env(),
      specDone = jasmine.createSpy('specDone');

      env.addReporter({
        specDone: specDone,
        jasmineDone: function() {
          expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
            description: 'has a default message',
            failedExpectations: [jasmine.objectContaining({
              message: 'Failed'
            })]
          }));
          expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
            description: 'specifies a message',
            failedExpectations: [jasmine.objectContaining({
              message: 'Failed: messy message'
            })]
          }));
          expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
            description: 'fails via the done callback',
            failedExpectations: [jasmine.objectContaining({
              message: 'Failed: done failed'
            })]
          }));
          expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
            description: 'has a message from an Error',
            failedExpectations: [jasmine.objectContaining({
              message: 'Failed: error message'
            })]
          }));
          done();
        }
      });

      env.describe('failing', function() {
        env.it('has a default message', function(innerDone) {
          setTimeout(function() {
            env.fail();
            innerDone();
          }, 1);
        });

        env.it('specifies a message', function(innerDone) {
          setTimeout(function() {
            env.fail('messy message');
            innerDone();
          }, 1);
        });

        env.it('fails via the done callback', function(innerDone) {
          setTimeout(function() {
            innerDone.fail('done failed');
          }, 1);
        });

        env.it('has a message from an Error', function(innerDone) {
          setTimeout(function() {
            env.fail(new Error('error message'));
            innerDone();
          }, 1);
        });
      });

      env.execute();
      jasmine.clock().tick(1);
      jasmine.clock().tick(1);
      jasmine.clock().tick(1);
      jasmine.clock().tick(1);
    });
  });

  describe('focused tests', function() {
    it('should only run the focused tests', function(done) {
      var env = new jasmineUnderTest.Env(),
        calls = [];

      var assertions = function() {
        expect(calls).toEqual(['focused']);
        done();
      };

      env.addReporter({jasmineDone: assertions});

      env.describe('a suite', function() {
        env.fit('is focused', function() {
          calls.push('focused');
        });

        env.it('is not focused', function() {
          calls.push('freakout');
        })
      });

      env.execute();
    });

    it('should only run focused suites', function(){
      var env = new jasmineUnderTest.Env(),
        calls = [];

      var assertions = function() {
        expect(calls).toEqual(['focused']);
        done();
      };

      env.addReporter({jasmineDone: assertions});

      env.fdescribe('a focused suite', function() {
        env.it('is focused', function() {
          calls.push('focused');
        });
      });

      env.describe('a regular suite', function() {
        env.it('is not focused', function() {
          calls.push('freakout');
        })
      });

      env.execute();
    });

    it('should run focused tests inside an xdescribe', function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineStarted",
          "jasmineDone",
          "suiteStarted",
          "suiteDone",
          "specStarted",
          "specDone"
        ]);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.jasmineStarted).toHaveBeenCalledWith({
          totalSpecsDefined: 1
        });

        expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
          description: 'with a fit spec',
          status: 'failed'
        }));

        done();
      });

      env.addReporter(reporter);

      env.xdescribe("xd suite", function() {
        env.fit("with a fit spec", function() {
          env.expect(true).toBe(false);
        });
      });

      env.execute();
    });

    it('should run focused suites inside an xdescribe', function(done) {
      var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineStarted",
          "jasmineDone",
          "suiteStarted",
          "suiteDone",
          "specStarted",
          "specDone"
        ]);

      reporter.jasmineDone.and.callFake(function() {
        expect(reporter.jasmineStarted).toHaveBeenCalledWith({
          totalSpecsDefined: 1
        });

        expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
          description: 'with a spec',
          status: 'failed'
        }));

        done();
      });

      env.addReporter(reporter);

      env.xdescribe("xd suite", function() {
        env.fdescribe("fd suite", function() {
          env.it("with a spec", function() {
            env.expect(true).toBe(false);
          });
        });
      });

      env.execute();
    });
  });

  it("should report as expected", function(done) {
    var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineStarted",
          "jasmineDone",
          "suiteStarted",
          "suiteDone",
          "specStarted",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      expect(reporter.jasmineStarted).toHaveBeenCalledWith({
        totalSpecsDefined: 5
      });

      expect(reporter.specDone.calls.count()).toBe(5);

      expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
        description: 'with a top level spec',
        status: 'passed'
      }));

      expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
        description: "with an x'ed spec",
        status: 'pending'
      }));

      expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
        description: 'with a spec',
        status: 'failed'
      }));

      expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
        description: 'is pending',
        status: 'pending'
      }));

      var suiteResult = reporter.suiteStarted.calls.argsFor(0)[0];
      expect(suiteResult.description).toEqual("A Suite");

      done();
    });

    env.addReporter(reporter);

    env.describe("A Suite", function() {
      env.it("with a top level spec", function() {
        env.expect(true).toBe(true);
      });
      env.describe("with a nested suite", function() {
        env.xit("with an x'ed spec", function() {
          env.expect(true).toBe(true);
        });
        env.it("with a spec", function() {
          env.expect(true).toBe(false);
        });
      });

      env.describe('with only non-executable specs', function() {
        env.it('is pending');
        env.xit('is xed', function() {
          env.expect(true).toBe(true);
        });
      });
    });

    env.execute();
  });

  it('should report pending spec messages', function(done) {
    var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          'specDone',
          'jasmineDone'
        ]);

    reporter.jasmineDone.and.callFake(function() {
      var specStatus = reporter.specDone.calls.argsFor(0)[0];

      expect(specStatus.pendingReason).toBe('with a message');

      done();
    });

    env.addReporter(reporter);

    env.it('will be pending', function() {
      env.pending('with a message');
    });

    env.execute();
  });

  it('should report using fallback reporter', function(done) {
    var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          'specDone',
          'jasmineDone'
        ]);

    reporter.jasmineDone.and.callFake(function() {
      expect(reporter.specDone).toHaveBeenCalled();

      done();
    });

    env.provideFallbackReporter(reporter);

    env.it('will be pending', function() {
      env.pending('with a message');
    });

    env.execute();
  });

  it('should report xdescribes as expected', function(done) {
    var env = new jasmineUnderTest.Env(),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineStarted",
          "jasmineDone",
          "suiteStarted",
          "suiteDone",
          "specStarted",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      expect(reporter.jasmineStarted).toHaveBeenCalledWith({
        totalSpecsDefined: 1
      });

      expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({ status: 'pending' }));
      expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ description: 'xd out', status: 'pending' }));
      expect(reporter.suiteDone.calls.count()).toBe(4);

      done();
    });

    env.addReporter(reporter);

    env.describe("A Suite", function() {
      env.describe("nested", function() {
        env.xdescribe("xd out", function() {
          env.describe("nested again", function() {
            env.it("with a spec", function() {
              env.expect(true).toBe(false);
            });
          });
        });
      });
    });

    env.execute();
  });

  it("should be possible to get full name from a spec", function() {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        topLevelSpec, nestedSpec, doublyNestedSpec;

    env.describe("my tests", function() {
      topLevelSpec = env.it("are sometimes top level", function() {
      });
      env.describe("are sometimes", function() {
        nestedSpec = env.it("singly nested", function() {
        });
        env.describe("even", function() {
          doublyNestedSpec = env.it("doubly nested", function() {
          });
        });
      });
    });

    expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level");
    expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested");
    expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested");
  });

  it("Custom equality testers should be per spec", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineDone",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      var firstSpecResult = reporter.specDone.calls.first().args[0],
          secondSpecResult = reporter.specDone.calls.mostRecent().args[0];

      expect(firstSpecResult.status).toEqual("passed");
      expect(secondSpecResult.status).toEqual("failed");

      done();
    });

    env.addReporter(reporter);

    env.describe("testing custom equality testers", function() {
      env.it("with a custom tester", function() {
        env.addCustomEqualityTester(function(a, b) { return true; });
        env.expect("a").toEqual("b");
      });

      env.it("without a custom tester", function() {
        env.expect("a").toEqual("b");
      });
    });

    env.execute();
  });

  it("Custom equality testers should be per suite", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineDone",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      var firstSpecResult = reporter.specDone.calls.first().args[0],
          secondSpecResult = reporter.specDone.calls.argsFor(0)[0],
          thirdSpecResult = reporter.specDone.calls.mostRecent().args[0];

      expect(firstSpecResult.status).toEqual("passed");
      expect(secondSpecResult.status).toEqual("passed");
      expect(thirdSpecResult.status).toEqual("failed");

      done();
    });

    env.addReporter(reporter);

    env.describe("testing custom equality testers", function() {
      env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; }); });

      env.it("with a custom tester", function() {
        env.expect("a").toEqual("b");
      });

      env.it("with the same custom tester", function() {
        env.expect("a").toEqual("b");
      });
    });

    env.describe("another suite", function() {
      env.it("without the custom tester", function(){
        env.expect("a").toEqual("b");
      });
    });

    env.execute();
  });

  it("Custom equality testers for toContain should be per spec", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineDone",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      var firstSpecResult = reporter.specDone.calls.first().args[0],
          secondSpecResult = reporter.specDone.calls.mostRecent().args[0];

      expect(firstSpecResult.status).toEqual("passed");
      expect(secondSpecResult.status).toEqual("failed");

      done();
    });

    env.addReporter(reporter);

    env.describe("testing custom equality testers", function() {
      env.it("with a custom tester", function() {
        env.addCustomEqualityTester(function(a, b) { return true; });
        env.expect(["a"]).toContain("b");
      });

      env.it("without a custom tester", function() {
        env.expect(["a"]).toContain("b");
      });
    });

    env.execute();
  });

  it("produces an understandable error message when an 'expect' is used outside of a current spec", function(done) {
    var env = new jasmineUnderTest.Env();

    env.describe("A Suite", function() {
      env.it("an async spec that is actually synchronous", function(underTestCallback) {
        underTestCallback();
        expect(function() { env.expect('a').toEqual('a'); }).toThrowError(/'expect' was used when there was no current spec/);
        done();
      });
    });

    env.execute();
  });

  it("Custom equality testers for toContain should be per suite", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        reporter = jasmine.createSpyObj('fakeReporter', [
          "jasmineDone",
          "specDone"
        ]);

    reporter.jasmineDone.and.callFake(function() {
      var firstSpecResult = reporter.specDone.calls.first().args[0],
          secondSpecResult = reporter.specDone.calls.argsFor(1)[0],
          thirdSpecResult = reporter.specDone.calls.mostRecent().args[0];

      expect(firstSpecResult.status).toEqual("passed");
      expect(secondSpecResult.status).toEqual("passed");
      expect(thirdSpecResult.status).toEqual("failed");

      done();
    });

    env.addReporter(reporter);

    env.describe("testing custom equality testers", function() {
      env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; })});

      env.it("with a custom tester", function() {
        env.expect(["a"]).toContain("b");
      });

      env.it("also with the custom tester", function() {
        env.expect(["a"]).toContain("b");
      });
    });

    env.describe("another suite", function() {
      env.it("without the custom tester", function() {
        env.expect(["a"]).toContain("b");
      });
    });

    env.execute();
  });

  it("Custom matchers should be per spec", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        matchers = {
          toFoo: function() {}
        };

    env.describe("testing custom matchers", function() {
      env.it("with a custom matcher", function() {
        env.addMatchers(matchers);
        expect(env.expect().toFoo).toBeDefined();
      });

      env.it("without a custom matcher", function() {
        expect(env.expect().toFoo).toBeUndefined();
      });
    });

    env.addReporter({jasmineDone: done});

    env.execute();
  });

  it("Custom matchers should be per suite", function(done) {
    var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
        matchers = {
          toFoo: function() {}
        };

    env.describe("testing custom matchers", function() {
      env.beforeAll(function() { env.addMatchers(matchers); });

      env.it("with a custom matcher", function() {
        expect(env.expect().toFoo).toBeDefined();
      });

      env.it("with the same custom matcher", function() {
        expect(env.expect().toFoo).toBeDefined();
      });
    });

    env.describe("another suite", function() {
      env.it("no longer has the custom matcher", function() {
        expect(env.expect().toFoo).not.toBeDefined();
      });
    });

    env.addReporter({jasmineDone: done});

    env.execute();
  });

  it('throws an exception if you try to create a spy outside of a runnable', function (done) {
    var env = new jasmineUnderTest.Env(),
      obj = {fn: function () {}},
      exception;

    env.describe("a suite", function () {
      try {
        env.spyOn(obj, 'fn');
      } catch(e) {
        exception = e;
      }
    });

    var assertions = function() {
      expect(exception.message).toBe('Spies must be created in a before function or a spec');
      done();
    };

    env.addReporter({jasmineDone: assertions});

    env.execute();
  });

  it('throws an exception if you try to add a matcher outside of a runnable', function (done) {
    var env = new jasmineUnderTest.Env(),
      obj = {fn: function () {}},
      exception;

    env.describe("a suite", function () {
      try {
        env.addMatchers({myMatcher: function(actual,expected){return false;}});
      } catch(e) {
        exception = e;
      }
    });

    var assertions = function() {
      expect(exception.message).toBe('Matchers must be added in a before function or a spec');
      done();
    };

    env.addReporter({jasmineDone: assertions});

    env.execute();
  });

  it('throws an exception if you try to add a custom equality outside of a runnable', function (done) {
    var env = new jasmineUnderTest.Env(),
      obj = {fn: function () {}},
      exception;

    env.describe("a suite", function () {
      try {
        env.addCustomEqualityTester(function(first, second) {return true;});
      } catch(e) {
        exception = e;
      }
    });

    var assertions = function() {
      expect(exception.message).toBe('Custom Equalities must be added in a before function or a spec');
      done();
    };

    env.addReporter({jasmineDone: assertions});

    env.execute();
  });
});