From 5a219da848d2a4e0c394bf96275e3f8afc3849a4 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Fri, 6 Sep 2019 13:44:15 -0700 Subject: [PATCH] Added basic integration tests for all built-in matchers --- spec/core/integration/MatchersSpec.js | 475 ++++++++++++++++++++++++++ spec/core/matchers/toHaveClassSpec.js | 22 +- spec/helpers/domHelpers.js | 24 ++ spec/support/jasmine-browser.js | 1 + spec/support/jasmine.json | 1 + 5 files changed, 506 insertions(+), 17 deletions(-) create mode 100644 spec/core/integration/MatchersSpec.js create mode 100644 spec/helpers/domHelpers.js diff --git a/spec/core/integration/MatchersSpec.js b/spec/core/integration/MatchersSpec.js new file mode 100644 index 00000000..64c780cd --- /dev/null +++ b/spec/core/integration/MatchersSpec.js @@ -0,0 +1,475 @@ +describe('Matchers (Integration)', function() { + function verifyPasses(expectations) { + var env = new jasmineUnderTest.Env(); + + it('passes', function(done) { + env.it('a spec', function() { + expectations(env); + }); + + var specExpectations = function(result) { + expect(result.status).toEqual('passed'); + expect(result.passedExpectations.length) + .withContext('Number of passed expectations') + .toEqual(1); + expect(result.failedExpectations.length) + .withContext('Number of failed expectations') + .toEqual(0); + expect(result.failedExpectations[0] && result.failedExpectations[0].message) + .withContext('Failure message') + .toBeUndefined(); + }; + + env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.execute(); + }); + } + + function verifyFails(expectations) { + var env = new jasmineUnderTest.Env(); + + it('fails', function(done) { + env.it('a spec', function() { + expectations(env); + }); + + var specExpectations = function(result) { + expect(result.status).toEqual('failed'); + expect(result.failedExpectations.length) + .withContext('Number of failed expectations') + .toEqual(1); + expect(result.failedExpectations[0].message) + .withContext('Failed with a thrown error rather than a matcher failure') + .not.toMatch(/^Error: /); + expect(result.failedExpectations[0].matcherName).withContext('Matcher name') + .not.toEqual(''); + }; + + env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.execute(); + }); + } + + function verifyPassesAsync(expectations) { + var env = new jasmineUnderTest.Env(); + + it('passes', function(done) { + jasmine.getEnv().requirePromises(); + + env.it('a spec', function() { + return expectations(env); + }); + + var specExpectations = function(result) { + expect(result.status).toEqual('passed'); + expect(result.passedExpectations.length) + .withContext('Number of passed expectations') + .toEqual(1); + expect(result.failedExpectations.length) + .withContext('Number of failed expectations') + .toEqual(0); + expect(result.failedExpectations[0] && result.failedExpectations[0].message) + .withContext('Failure message') + .toBeUndefined(); + }; + + env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.execute(); + }); + } + + function verifyFailsAsync(expectations) { + var env = new jasmineUnderTest.Env(); + + it('fails', function(done) { + jasmine.getEnv().requirePromises(); + + env.it('a spec', function() { + return expectations(env); + }); + + var specExpectations = function(result) { + expect(result.status).toEqual('failed'); + expect(result.failedExpectations.length) + .withContext('Number of failed expectations') + .toEqual(1); + expect(result.failedExpectations[0].message) + .withContext('Failed with a thrown error rather than a matcher failure') + .not.toMatch(/^Error: /); + expect(result.failedExpectations[0].matcherName).withContext('Matcher name') + .not.toEqual(''); + }; + + env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.execute(); + }); + } + + describe('nothing', function() { + verifyPasses(function(env) { + env.expect().nothing(); + }); + }); + + describe('toBe', function() { + verifyPasses(function(env) { + env.expect(1).toBe(1); + }); + + verifyFails(function(env) { + env.expect(2).toBe(1); + }); + }); + + describe('toBeCloseTo', function() { + verifyPasses(function(env) { + env.expect(1.001).toBeCloseTo(1, 2); + }); + + verifyFails(function(env) { + env.expect(1.1).toBeCloseTo(1, 2); + }); + }); + + describe('toBeDefined', function() { + verifyPasses(function(env) { + env.expect({}).toBeDefined(); + }); + + verifyFails(function(env) { + env.expect(undefined).toBeDefined(); + }); + }); + + describe('toBeFalse', function() { + verifyPasses(function(env) { + env.expect(false).toBeFalse(); + }); + + verifyFails(function(env) { + env.expect(true).toBeFalse(); + }); + }); + + describe('toBeFalsy', function() { + verifyPasses(function(env) { + env.expect(false).toBeFalsy(); + }); + + verifyFails(function(env) { + env.expect(true).toBeFalsy(); + }); + }); + + describe('toBeGreaterThan', function() { + verifyPasses(function(env) { + env.expect(2).toBeGreaterThan(1); + }); + + verifyFails(function(env) { + env.expect(1).toBeGreaterThan(2); + }); + }); + + describe('toBeGreaterThanOrEqual', function() { + verifyPasses(function(env) { + env.expect(2).toBeGreaterThanOrEqual(1); + }); + + verifyFails(function(env) { + env.expect(1).toBeGreaterThanOrEqual(2); + }); + }); + + describe('toBeInstanceOf', function() { + function Ctor() {} + + verifyPasses(function(env) { + env.expect(new Ctor()).toBeInstanceOf(Ctor); + }); + + verifyFails(function(env) { + env.expect({}).toBeInstanceOf(Ctor); + }); + }); + + describe('toBeLessThan', function() { + verifyPasses(function(env) { + env.expect(1).toBeLessThan(2); + }); + + verifyFails(function(env) { + env.expect(2).toBeLessThan(1); + }); + }); + + describe('toBeLessThanOrEqual', function() { + verifyPasses(function(env) { + env.expect(1).toBeLessThanOrEqual(2); + }); + + verifyFails(function(env) { + env.expect(2).toBeLessThanOrEqual(1); + }); + }); + + describe('toBeNaN', function() { + verifyPasses(function(env) { + env.expect(NaN).toBeNaN(); + }); + + verifyFails(function(env) { + env.expect(2).toBeNaN(); + }); + }); + + describe('toBeNegativeInfinity', function() { + verifyPasses(function(env) { + env.expect(Number.NEGATIVE_INFINITY).toBeNegativeInfinity(); + }); + + verifyFails(function(env) { + env.expect(2).toBeNegativeInfinity(); + }); + }); + + describe('toBeNull', function() { + verifyPasses(function(env) { + env.expect(null).toBeNull(); + }); + + verifyFails(function(env) { + env.expect(2).toBeNull(); + }); + }); + + describe('toBePositiveInfinity', function() { + verifyPasses(function(env) { + env.expect(Number.POSITIVE_INFINITY).toBePositiveInfinity(); + }); + + verifyFails(function(env) { + env.expect(2).toBePositiveInfinity(); + }); + }); + + describe('toBeResolved', function() { + verifyPassesAsync(function(env) { + return env.expectAsync(Promise.resolve()).toBeResolved(); + }); + + verifyFailsAsync(function(env) { + return env.expectAsync(Promise.reject()).toBeResolved(); + }); + }); + + describe('toBeResolvedTo', function() { + verifyPassesAsync(function(env) { + return env.expectAsync(Promise.resolve('foo')).toBeResolvedTo('foo'); + }); + + verifyFailsAsync(function(env) { + return env.expectAsync(Promise.resolve('foo')).toBeResolvedTo('bar'); + }); + }); + + describe('toBeRejected', function() { + verifyPassesAsync(function(env) { + return env.expectAsync(Promise.reject('nope')).toBeRejected(); + }); + + verifyFailsAsync(function(env) { + return env.expectAsync(Promise.resolve()).toBeRejected(); + }); + }); + + describe('toBeRejectedWith', function() { + verifyPassesAsync(function(env) { + return env.expectAsync(Promise.reject('nope')).toBeRejectedWith('nope'); + }); + + verifyFailsAsync(function(env) { + return env.expectAsync(Promise.resolve()).toBeRejectedWith('nope'); + }); + }); + + describe('toBeRejectedWithError', function() { + function MyCustomError() {} + MyCustomError.prototype = new Error(); + + verifyPassesAsync(function(env) { + return env.expectAsync(Promise.reject(new MyCustomError())).toBeRejectedWithError(MyCustomError); + }); + + verifyFailsAsync(function(env) { + return env.expectAsync(Promise.resolve()).toBeRejectedWithError(MyCustomError); + }); + }); + + describe('toBeTrue', function() { + verifyPasses(function(env) { + env.expect(true).toBeTrue(); + }); + + verifyFails(function(env) { + env.expect(false).toBeTrue(); + }); + }); + + describe('toBeTruthy', function() { + verifyPasses(function(env) { + env.expect(true).toBeTruthy(); + }); + + verifyFails(function(env) { + env.expect(false).toBeTruthy(); + }); + }); + + describe('toBeUndefined', function() { + verifyPasses(function(env) { + env.expect(undefined).toBeUndefined(); + }); + + verifyFails(function(env) { + env.expect(1).toBeUndefined(); + }); + }); + + describe('toContain', function() { + verifyPasses(function(env) { + env.expect('foobar').toContain('oo'); + }); + + verifyFails(function(env) { + env.expect('bar').toContain('oo'); + }); + }); + + describe('toEqual', function() { + verifyPasses(function(env) { + env.expect('a').toEqual('a'); + }); + + verifyFails(function(env) { + env.expect('a').toEqual('b'); + }); + }); + + describe('toHaveBeenCalled', function() { + verifyPasses(function(env) { + var spy = env.createSpy('spy'); + spy(); + env.expect(spy).toHaveBeenCalled(); + }); + + verifyFails(function(env) { + var spy = env.createSpy('spy'); + env.expect(spy).toHaveBeenCalled(); + }); + }); + + describe('toHaveBeenCalledBefore', function() { + verifyPasses(function(env) { + var a = env.createSpy('a'), b = env.createSpy('b'); + a(); + b(); + env.expect(a).toHaveBeenCalledBefore(b); + }); + + verifyFails(function(env) { + var a = env.createSpy('a'), b = env.createSpy('b'); + b(); + a(); + env.expect(a).toHaveBeenCalledBefore(b); + }); + }); + + describe('toHaveBeenCalledTimes', function() { + verifyPasses(function(env) { + var spy = env.createSpy('spy'); + spy(); + env.expect(spy).toHaveBeenCalledTimes(1); + }); + + verifyFails(function(env) { + var spy = env.createSpy('spy'); + env.expect(spy).toHaveBeenCalledTimes(1); + }); + }); + + describe('toHaveBeenCalledWith', function() { + verifyPasses(function(env) { + var spy = env.createSpy(); + spy('foo'); + env.expect(spy).toHaveBeenCalledWith('foo'); + }); + + verifyFails(function(env) { + var spy = env.createSpy(); + env.expect(spy).toHaveBeenCalledWith('foo'); + }); + }); + + describe('toHaveClass', function() { + beforeEach(function() { + this.domHelpers = jasmine.getEnv().domHelpers(); + }); + + verifyPasses(function(env) { + var domHelpers = jasmine.getEnv().domHelpers(); + var el = domHelpers.createElementWithClassName('foo'); + env.expect(el).toHaveClass('foo'); + }); + + verifyFails(function(env) { + var domHelpers = jasmine.getEnv().domHelpers(); + var el = domHelpers.createElementWithClassName('foo'); + env.expect(el).toHaveClass('bar'); + }); + }); + + describe('toMatch', function() { + verifyPasses(function(env) { + env.expect('foo').toMatch(/oo$/); + }); + + verifyFails(function(env) { + env.expect('bar').toMatch(/oo$/); + }); + }); + + describe('toThrow', function() { + verifyPasses(function(env) { + env.expect(function() { throw new Error(); }).toThrow(); + }); + + verifyFails(function(env) { + env.expect(function() {}).toThrow(); + }); + }); + + describe('toThrowError', function() { + verifyPasses(function(env) { + env.expect(function() { throw new Error(); }).toThrowError(); + }); + + verifyFails(function(env) { + env.expect(function() { }).toThrowError(); + }); + }); + + describe('toThrowMatching', function() { + function throws() { + throw new Error('nope'); + } + + verifyPasses(function(env) { + env.expect(throws).toThrowMatching(function() { return true; }); + }); + + verifyFails(function(env) { + env.expect(throws).toThrowMatching(function() { return false; }); + }); + }); +}); diff --git a/spec/core/matchers/toHaveClassSpec.js b/spec/core/matchers/toHaveClassSpec.js index 4e4ef00d..109babbb 100644 --- a/spec/core/matchers/toHaveClassSpec.js +++ b/spec/core/matchers/toHaveClassSpec.js @@ -1,30 +1,18 @@ describe('toHaveClass', function() { beforeEach(function() { - this.createElementWithClassName = function(className) { - var el = this.doc.createElement('div'); - el.className = className; - return el; - }; - - if (typeof document !== 'undefined') { - this.doc = document; - } else { - var JSDOM = require('jsdom').JSDOM; - var dom = new JSDOM(); - this.doc = dom.window.document; - } + this.domHelpers = jasmine.getEnv().domHelpers(); }); it('fails for a DOM element that lacks the expected class', function() { var matcher = jasmineUnderTest.matchers.toHaveClass(), - result = matcher.compare(this.createElementWithClassName(''), 'foo'); + result = matcher.compare(this.domHelpers.createElementWithClassName(''), 'foo'); expect(result.pass).toBe(false); }); it('passes for a DOM element that has the expected class', function() { var matcher = jasmineUnderTest.matchers.toHaveClass(), - el = this.createElementWithClassName('foo bar baz'); + el = this.domHelpers.createElementWithClassName('foo bar baz'); expect(matcher.compare(el, 'foo').pass).toBe(true); expect(matcher.compare(el, 'bar').pass).toBe(true); @@ -33,7 +21,7 @@ describe('toHaveClass', function() { it('fails for a DOM element that only has other classes', function() { var matcher = jasmineUnderTest.matchers.toHaveClass(), - el = this.createElementWithClassName('foo bar'); + el = this.domHelpers.createElementWithClassName('foo bar'); expect(matcher.compare(el, 'fo').pass).toBe(false); }); @@ -49,7 +37,7 @@ describe('toHaveClass', function() { matcher.compare(undefined, 'foo'); }).toThrowError('undefined is not a DOM element'); - var textNode = this.doc.createTextNode(''); + var textNode = this.domHelpers.document.createTextNode(''); expect(function() { matcher.compare(textNode, 'foo') }).toThrowError('HTMLNode is not a DOM element'); diff --git a/spec/helpers/domHelpers.js b/spec/helpers/domHelpers.js new file mode 100644 index 00000000..79175df3 --- /dev/null +++ b/spec/helpers/domHelpers.js @@ -0,0 +1,24 @@ +(function(env) { + function domHelpers() { + var doc; + + if (typeof document !== 'undefined') { + doc = document; + } else { + var JSDOM = require('jsdom').JSDOM; + var dom = new JSDOM(); + doc = dom.window.document; + } + + return { + document: doc, + createElementWithClassName: function(className) { + var el = this.document.createElement('div'); + el.className = className; + return el; + } + }; + } + + env.domHelpers = domHelpers; +})(jasmine.getEnv()); diff --git a/spec/support/jasmine-browser.js b/spec/support/jasmine-browser.js index 9986ba08..41c9e703 100644 --- a/spec/support/jasmine-browser.js +++ b/spec/support/jasmine-browser.js @@ -23,6 +23,7 @@ module.exports = { 'helpers/checkForSet.js', 'helpers/checkForSymbol.js', 'helpers/checkForTypedArrays.js', + 'helpers/domHelpers.js', 'helpers/integrationMatchers.js', 'helpers/promises.js', 'helpers/defineJasmineUnderTest.js' diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json index ffcd6b7d..033207ec 100644 --- a/spec/support/jasmine.json +++ b/spec/support/jasmine.json @@ -10,6 +10,7 @@ "helpers/checkForSet.js", "helpers/checkForSymbol.js", "helpers/checkForTypedArrays.js", + "helpers/domHelpers.js", "helpers/integrationMatchers.js", "helpers/promises.js", "helpers/nodeDefineJasmineUnderTest.js"