From 5b126fee17ebc20024774e43b128c8107f12d6ac Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 21 Dec 2020 18:33:12 +0100 Subject: [PATCH 01/19] Sketch out some basic tests --- test/camelCaseSyntax.spec.js | 226 +++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 test/camelCaseSyntax.spec.js diff --git a/test/camelCaseSyntax.spec.js b/test/camelCaseSyntax.spec.js new file mode 100644 index 000000000..df2c77d56 --- /dev/null +++ b/test/camelCaseSyntax.spec.js @@ -0,0 +1,226 @@ +/* global expect */ +describe('camel case syntax', () => { + describe('with an assertion that is defined for the given subject type', () => { + it('should succeed', () => { + expect(456).toBeGreaterThan(123); + }); + + it('should fail', () => { + expect(() => expect(123).toBeGreaterThan(456)).toThrow( + 'expected 123 to be greater than 456' + ); + }); + + describe('with a flag', () => { + it('should succeed', () => { + expect(123).notToBeGreaterThan(456); + }); + + it('should fail', () => { + expect(() => expect(456).notToBeGreaterThan(123)).toThrow( + 'expected 456 not to be greater than 123' + ); + }); + }); + }); + + describe('within an assertion', () => { + it('should succeed', () => { + const clonedExpect = expect.clone(); + clonedExpect.addAssertion(' to foo', (expect, subject) => + expect(subject).toEqual('foo') + ); + clonedExpect('foo').toFoo(); + }); + + it('should fail', () => { + const clonedExpect = expect.clone(); + clonedExpect.addAssertion(' to foo', (expect, subject) => + expect(subject).toEqual('foo') + ); + expect(() => clonedExpect('bar').toFoo()).toThrow( + "expected 'bar' to equal 'foo'\n" + '\n' + '-bar\n' + '+foo' + ); + }); + }); + + describe('in a clone', () => { + it('should succeed', () => { + expect.clone()(456).toBeGreaterThan(123); + }); + + it('should fail', () => { + expect(() => expect.clone()(123).toBeGreaterThan(456)).toThrow( + 'expected 123 to be greater than 456' + ); + }); + + it('should not support an assertion subsequently added to the original expect', () => { + const originalExpect = expect.clone(); + const clonedExpect = originalExpect.clone(); + originalExpect.addAssertion(' to foo', (expect, subject) => + expect(subject).toEqual('foo') + ); + expect(clonedExpect('foo').toFoo).notToBeAFunction(); + }); + }); + + describe('in a child', () => { + it('should succeed', () => { + expect.child()(456).toBeGreaterThan(123); + }); + + it('should fail', () => { + expect(() => expect.child()(123).toBeGreaterThan(456)).toThrow( + 'expected 123 to be greater than 456' + ); + }); + + it('should support an assertion subsequently added to the parent', () => { + const parentExpect = expect.clone(); + const childExpect = parentExpect.child(); + parentExpect.addAssertion(' to foo', (expect, subject) => + expect(subject).toEqual('foo') + ); + childExpect('foo').toFoo(); + }); + }); + + describe('with an assertion that is defined for the base of the given subject type', () => { + it('should succeed', () => { + function foo() {} + foo.bar = 123; + expect(foo).toHaveProperty('bar', 123); + }); + + it('should fail', () => { + function foo() {} + expect(() => expect(foo).toHaveProperty('bar', 123)).toThrow( + "expected function foo() {} to have property 'bar', 123" + ); + }); + }); + + describe('with an assertion that is not defined for the given subject type', () => { + it('should not expose a function', () => { + expect(expect(123).toContain).toBeUndefined(); + }); + }); + + describe('with a middle rocket assertion', () => { + it('should succeed', () => { + expect([1, 2, 3]).whenPassedAsParametersTo(Math.max).toEqual(3); + }); + + it('should fail', () => { + expect(() => + expect([1, 2, 3]).whenPassedAsParametersTo(Math.max).toEqual(2) + ).toThrow('expected 3 to equal 2'); + }); + }); + + describe('with the expect.it equivalent', () => { + it('should succeed', () => { + expect({ foo: 123 }).toSatisfy({ foo: expect.toBeANumber() }); + }); + + describe('and extra chaining with .and...', () => { + it('should succeed', () => { + expect({ foo: 123 }).toSatisfy({ + foo: expect.toBeANumber().andToBeGreaterThan(100), + }); + }); + + it('should fail', () => { + expect(() => + expect({ foo: 123 }).toSatisfy({ + foo: expect.toBeANumber().andToBeGreaterThan(200), + }) + ).toThrow( + 'expected { foo: 123 } to satisfy\n' + + '{\n' + + " foo: expect.it('to be a number')\n" + + " .and('to be greater than', 200)\n" + + '}\n' + + '\n' + + '{\n' + + ' foo: 123 // ✓ should be a number and\n' + + ' // ⨯ should be greater than 200\n' + + '}' + ); + }); + }); + + describe('and extra chaining with .or...', () => { + it('should succeed', () => { + expect({ foo: 123 }).toSatisfy({ + foo: expect.toBeAString().orToBeGreaterThan(100), + }); + }); + + it('should fail', () => { + expect(() => + expect({ foo: 123 }).toSatisfy({ + foo: expect.toBeAString().orToBeGreaterThan(200), + }) + ).toThrow( + 'expected { foo: 123 } to satisfy\n' + + '{\n' + + " foo: expect.it('to be a string')\n" + + " .or('to be greater than', 200)\n" + + '}\n' + + '\n' + + '{\n' + + ' foo: 123 // ⨯ should be a string or\n' + + ' // ⨯ should be greater than 200\n' + + '}' + ); + }); + }); + + it('should fail', () => { + expect(() => + expect({ foo: 123 }).toSatisfy({ foo: expect.notToBeANumber() }) + ).toThrow( + "expected { foo: 123 } to satisfy { foo: expect.it('not to be a number') }\n" + + '\n' + + '{\n' + + ' foo: 123 // should not be a number\n' + + '}' + ); + }); + + describe('in a child', () => { + describe('with an assertion subsequently added to the parent', () => { + it('should succeed', () => { + const parentExpect = expect.clone(); + const childExpect = parentExpect.child(); + parentExpect.addAssertion(' to foo', (expect, subject) => { + return expect(subject).toEqual('foo'); + }); + childExpect({ hey: 'foo' }).toSatisfy({ hey: childExpect.toFoo() }); + }); + + it('should fail', () => { + const parentExpect = expect.clone(); + const childExpect = parentExpect.child(); + parentExpect.addAssertion(' to foo', (expect, subject) => + expect(subject).toEqual('foo') + ); + expect(() => + childExpect({ hey: 'bar' }).toSatisfy({ hey: childExpect.toFoo() }) + ).toThrow( + "expected { hey: 'bar' } to satisfy { hey: expect.it('to foo') }\n" + + '\n' + + '{\n' + + " hey: 'bar' // should equal 'foo'\n" + + ' //\n' + + ' // -bar\n' + + ' // +foo\n' + + '}' + ); + }); + }); + }); + }); +}); From f59f4e3a0a63aae384ad71e319ad24162b147c81 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 22 Dec 2020 11:58:40 +0100 Subject: [PATCH 02/19] Slow, naive implementation of the basic cases --- lib/createTopLevelExpect.js | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index f18287dd2..40c839ec1 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1442,12 +1442,43 @@ expectPrototype._executeExpect = function ( return oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)); }; +expectPrototype._camelCaser = function (subject, context) { + const subjectType = this.findTypeOf(subject); + const methods = {}; + let instance = this; + while (instance) { + Object.keys(instance.assertions).forEach((testDescriptionString) => { + if ( + instance.assertions[testDescriptionString].some((assertion) => + subjectType.is(assertion.subject.type) + ) + ) { + methods[ + testDescriptionString.replace(/ [a-z]/g, ($0) => + $0.charAt(1).toUpperCase() + ) + ] = (...args) => { + return this._expect(context, [ + subject, + testDescriptionString, + ...args, + ]); + }; + } + }); + instance = instance.parent; + } + return methods; +}; + expectPrototype._expect = function (context, args, forwardedFlags) { const subject = args[0]; const testDescriptionString = args[1]; - if (args.length < 2) { - throw new Error('The expect function requires at least two parameters.'); + if (args.length < 1) { + throw new Error('The expect function requires at least one parameter.'); + } else if (args.length === 1) { + return this._camelCaser(subject, context); } else if (typeof testDescriptionString === 'function') { return this.withError( () => testDescriptionString(subject), From b211873899be8624c9032fa8c14462e05915f512 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 22 Dec 2020 22:36:12 +0100 Subject: [PATCH 03/19] Support camel case syntax within an assertion Removes support for expect(oneArg) returning an object with .and etc., but we can maybe get that back later --- lib/createTopLevelExpect.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 40c839ec1..d73232c8b 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1301,11 +1301,7 @@ expectPrototype._createWrappedExpect = function ( if (arguments.length === 0) { throw new Error('The expect function requires at least one parameter.'); } else if (arguments.length === 1) { - return addAdditionalPromiseMethods( - makePromise.resolve(subject), - wrappedExpect, - subject - ); + return parentExpect._camelCaser(subject, context); } else if (typeof testDescriptionString === 'function') { wrappedExpect.errorMode = 'nested'; return wrappedExpect.withError( From 5a1d6c14acb469d5016c84ff9a0da1d794524637 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Wed, 23 Dec 2020 00:59:45 +0100 Subject: [PATCH 04/19] Add expect.it shorthands --- lib/createTopLevelExpect.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index d73232c8b..acd1a6971 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -707,6 +707,17 @@ expectPrototype.addAssertion = function ( // Make sure that all flags are defined. handler.flags = extend({}, defaultValueByFlag, handler.flags); + this[ + handler.testDescriptionString.replace(/ [a-z]/g, ($0) => + $0.charAt(1).toUpperCase() + ) + ] = (...args) => + createExpectIt( + this._topLevelExpect, + [[testDescriptionString, ...args]], + this.flags + ); + const assertionHandlers = assertions[handler.testDescriptionString]; handler.specificity = calculateAssertionSpecificity(handler); if (!assertionHandlers) { @@ -1579,6 +1590,11 @@ expectPrototype.clone = function () { const clonedAssertions = {}; Object.keys(this.assertions).forEach(function (assertion) { clonedAssertions[assertion] = [].concat(this.assertions[assertion]); + // FIXME: We would get this for free if the assertions were recreated in the clone with addAssertion: + this[assertion.replace(/ [a-z]/g, ($0) => $0.charAt(1).toUpperCase())] = ( + ...args + ) => + createExpectIt(this._topLevelExpect, [[assertion, ...args]], this.flags); }, this); const expect = createTopLevelExpect({ assertions: clonedAssertions, From 933f8223b4128026e4d18d17f0b5e08df042dc48 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Wed, 23 Dec 2020 02:23:12 +0100 Subject: [PATCH 05/19] Fix additional promise methods and expect.it --- lib/addAdditionalPromiseMethods.js | 43 +++++++++++++++++++++++ lib/createTopLevelExpect.js | 56 ++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/lib/addAdditionalPromiseMethods.js b/lib/addAdditionalPromiseMethods.js index dbb00bb8b..9d9eb6234 100644 --- a/lib/addAdditionalPromiseMethods.js +++ b/lib/addAdditionalPromiseMethods.js @@ -1,3 +1,5 @@ +const Context = require('./Context'); + function addAdditionalPromiseMethods(promise, expect, subject) { promise.and = function (...args) { function executeAnd() { @@ -19,6 +21,47 @@ function addAdditionalPromiseMethods(promise, expect, subject) { } }; + const camelCaseMethods = expect._camelCaser(expect.context || new Context()); + Object.keys(camelCaseMethods).forEach((methodName) => { + promise[methodName] = function (...args) { + function execute(shiftedSubject) { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return addAdditionalPromiseMethods( + args[0](shiftedSubject), + expect, + subject + ); + } else { + return camelCaseMethods[methodName](shiftedSubject)(...args); + } + } + + if (this.isFulfilled()) { + return execute(this.value()); + } else { + return addAdditionalPromiseMethods(this.then(execute), expect, subject); + } + }; + + promise[ + `and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` + ] = function (...args) { + function execute() { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return addAdditionalPromiseMethods(args[0](subject), expect, subject); + } else { + return camelCaseMethods[methodName](subject)(...args); + } + } + + if (this.isFulfilled()) { + return execute(this.value()); + } else { + return addAdditionalPromiseMethods(this.then(execute), expect, subject); + } + }; + }); + return promise; } diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index acd1a6971..1f0d05696 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -244,6 +244,32 @@ function createExpectIt(expect, expectations, forwardedFlags) { copiedExpectations.push(OR, args); return createExpectIt(expect, copiedExpectations, forwardedFlags); }; + + const camelCaseMethods = expect._camelCaser(expect.context || new Context()); + Object.keys(camelCaseMethods).forEach((methodName) => { + expectIt[ + `and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` + ] = function (...args) { + const copiedExpectations = expectations.slice(); + copiedExpectations.push([ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this + ...args, + ]); + return createExpectIt(expect, copiedExpectations, forwardedFlags); + }; + + expectIt[ + `or${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` + ] = function (...args) { + const copiedExpectations = expectations.slice(); + copiedExpectations.push(OR, [ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this + ...args, + ]); + return createExpectIt(expect, copiedExpectations, forwardedFlags); + }; + }); + return expectIt; } @@ -714,7 +740,7 @@ expectPrototype.addAssertion = function ( ] = (...args) => createExpectIt( this._topLevelExpect, - [[testDescriptionString, ...args]], + [[handler.testDescriptionString, ...args]], this.flags ); @@ -1312,7 +1338,11 @@ expectPrototype._createWrappedExpect = function ( if (arguments.length === 0) { throw new Error('The expect function requires at least one parameter.'); } else if (arguments.length === 1) { - return parentExpect._camelCaser(subject, context); + return parentExpect._camelCaser( + context, + parentExpect.findTypeOf(subject), + subject + ); } else if (typeof testDescriptionString === 'function') { wrappedExpect.errorMode = 'nested'; return wrappedExpect.withError( @@ -1449,28 +1479,34 @@ expectPrototype._executeExpect = function ( return oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)); }; -expectPrototype._camelCaser = function (subject, context) { - const subjectType = this.findTypeOf(subject); +expectPrototype._camelCaser = function (context, subjectType, subject) { const methods = {}; let instance = this; while (instance) { Object.keys(instance.assertions).forEach((testDescriptionString) => { if ( + !subjectType || instance.assertions[testDescriptionString].some((assertion) => subjectType.is(assertion.subject.type) ) ) { - methods[ - testDescriptionString.replace(/ [a-z]/g, ($0) => - $0.charAt(1).toUpperCase() - ) - ] = (...args) => { + let method = (subject) => (...args) => { return this._expect(context, [ subject, testDescriptionString, ...args, ]); }; + + if (subjectType) { + method = method(subject); + } + + methods[ + testDescriptionString.replace(/ [a-z]/g, ($0) => + $0.charAt(1).toUpperCase() + ) + ] = method; } }); instance = instance.parent; @@ -1485,7 +1521,7 @@ expectPrototype._expect = function (context, args, forwardedFlags) { if (args.length < 1) { throw new Error('The expect function requires at least one parameter.'); } else if (args.length === 1) { - return this._camelCaser(subject, context); + return this._camelCaser(context, this.findTypeOf(subject), subject); } else if (typeof testDescriptionString === 'function') { return this.withError( () => testDescriptionString(subject), From ff045ca531199bad521c667d0bc9d2c962e53f6f Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Wed, 23 Dec 2020 02:34:26 +0100 Subject: [PATCH 06/19] Remove no longer relevant test --- test/unexpected.spec.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/test/unexpected.spec.js b/test/unexpected.spec.js index e9fcee6b8..152aecb0f 100644 --- a/test/unexpected.spec.js +++ b/test/unexpected.spec.js @@ -30,17 +30,7 @@ describe('unexpected', () => { expect(); }, 'to throw', - 'The expect function requires at least two parameters.' - ); - }); - - it('fails when given only one parameter', () => { - expect( - function () { - expect('foo'); - }, - 'to throw', - 'The expect function requires at least two parameters.' + 'The expect function requires at least one parameter.' ); }); From 98369253643583e0f06f9e3a22e78747b6401443 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Wed, 23 Dec 2020 02:35:04 +0100 Subject: [PATCH 07/19] wrapped expect: Back to just using addAdditionalPromiseMethods --- lib/createTopLevelExpect.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 1f0d05696..8e39df79b 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1338,9 +1338,9 @@ expectPrototype._createWrappedExpect = function ( if (arguments.length === 0) { throw new Error('The expect function requires at least one parameter.'); } else if (arguments.length === 1) { - return parentExpect._camelCaser( - context, - parentExpect.findTypeOf(subject), + return addAdditionalPromiseMethods( + makePromise.resolve(subject), + wrappedExpect, subject ); } else if (typeof testDescriptionString === 'function') { From 2bcf9a41544a1a75c633d4ca86a06e3f10de5311 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 27 Dec 2020 13:55:26 +0100 Subject: [PATCH 08/19] Expect the full context to be captured when delegating from a middle rocket assertion --- test/camelCaseSyntax.spec.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/camelCaseSyntax.spec.js b/test/camelCaseSyntax.spec.js index df2c77d56..29d971486 100644 --- a/test/camelCaseSyntax.spec.js +++ b/test/camelCaseSyntax.spec.js @@ -115,7 +115,11 @@ describe('camel case syntax', () => { it('should fail', () => { expect(() => expect([1, 2, 3]).whenPassedAsParametersTo(Math.max).toEqual(2) - ).toThrow('expected 3 to equal 2'); + ).toThrow( + 'expected [ 1, 2, 3 ]\n' + + 'when passed as parameters to function max() { /* native code */ } to equal 2\n' + + ' expected 3 to equal 2' + ); }); }); From 9aea0a4d9e1f17cb673523a32864bc4c92520c08 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 20 Feb 2022 23:50:52 +0100 Subject: [PATCH 09/19] WIP --- lib/addAdditionalPromiseMethods.js | 7 ++++++- lib/createTopLevelExpect.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/addAdditionalPromiseMethods.js b/lib/addAdditionalPromiseMethods.js index 9d9eb6234..ebf74a9cc 100644 --- a/lib/addAdditionalPromiseMethods.js +++ b/lib/addAdditionalPromiseMethods.js @@ -1,6 +1,6 @@ const Context = require('./Context'); -function addAdditionalPromiseMethods(promise, expect, subject) { +function addAdditionalPromiseMethods(promise, expect, subject, args) { promise.and = function (...args) { function executeAnd() { if (expect.findTypeOf(args[0]).is('expect.it')) { @@ -32,6 +32,11 @@ function addAdditionalPromiseMethods(promise, expect, subject) { subject ); } else { + return expect.execute( + shiftedSubject, + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), + ...args + ); return camelCaseMethods[methodName](shiftedSubject)(...args); } } diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 8e39df79b..1c120943c 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1553,7 +1553,12 @@ expectPrototype._expect = function (context, args, forwardedFlags) { } else { result = makePromise.resolve(result); } - return addAdditionalPromiseMethods(result, this, subject); + return addAdditionalPromiseMethods( + result, + this, + subject, + Array.prototype.slice.call(args, 0, 2) + ); } catch (e) { if (e && e._isUnexpected) { let newError = e; From d713df18312a4fe66ef6dcf2a176a50e8035cb83 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 29 May 2022 22:38:14 +0200 Subject: [PATCH 10/19] Fiddle --- lib/addAdditionalPromiseMethods.js | 70 ++++++++---- lib/createTopLevelExpect.js | 171 +++++++++++++++-------------- 2 files changed, 139 insertions(+), 102 deletions(-) diff --git a/lib/addAdditionalPromiseMethods.js b/lib/addAdditionalPromiseMethods.js index ebf74a9cc..e5b178b6d 100644 --- a/lib/addAdditionalPromiseMethods.js +++ b/lib/addAdditionalPromiseMethods.js @@ -1,6 +1,12 @@ const Context = require('./Context'); -function addAdditionalPromiseMethods(promise, expect, subject, args) { +function addAdditionalPromiseMethods( + promise, + expect, + subject, + args, + wrappedExpect +) { promise.and = function (...args) { function executeAnd() { if (expect.findTypeOf(args[0]).is('expect.it')) { @@ -32,12 +38,25 @@ function addAdditionalPromiseMethods(promise, expect, subject, args) { subject ); } else { - return expect.execute( - shiftedSubject, - methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), - ...args - ); - return camelCaseMethods[methodName](shiftedSubject)(...args); + if (wrappedExpect) { + return wrappedExpect.shifty( + shiftedSubject, + wrappedExpect.args || [], + [ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), + ...args, + ] + ); + } else { + // find ud af at fange konteksten + return expect._executeExpect( + new Context(), + shiftedSubject, + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), + args, + {} // forwardedFlags + ); + } } } @@ -48,23 +67,30 @@ function addAdditionalPromiseMethods(promise, expect, subject, args) { } }; - promise[ - `and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` - ] = function (...args) { - function execute() { - if (expect.findTypeOf(args[0]).is('expect.it')) { - return addAdditionalPromiseMethods(args[0](subject), expect, subject); - } else { - return camelCaseMethods[methodName](subject)(...args); + promise[`and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}`] = + function (...args) { + function execute() { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return addAdditionalPromiseMethods( + args[0](subject), + expect, + subject + ); + } else { + return camelCaseMethods[methodName](subject)(...args); + } } - } - if (this.isFulfilled()) { - return execute(this.value()); - } else { - return addAdditionalPromiseMethods(this.then(execute), expect, subject); - } - }; + if (this.isFulfilled()) { + return execute(this.value()); + } else { + return addAdditionalPromiseMethods( + this.then(execute), + expect, + subject + ); + } + }; }); return promise; diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 1c120943c..e3c407260 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -247,27 +247,25 @@ function createExpectIt(expect, expectations, forwardedFlags) { const camelCaseMethods = expect._camelCaser(expect.context || new Context()); Object.keys(camelCaseMethods).forEach((methodName) => { - expectIt[ - `and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` - ] = function (...args) { - const copiedExpectations = expectations.slice(); - copiedExpectations.push([ - methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this - ...args, - ]); - return createExpectIt(expect, copiedExpectations, forwardedFlags); - }; + expectIt[`and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}`] = + function (...args) { + const copiedExpectations = expectations.slice(); + copiedExpectations.push([ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this + ...args, + ]); + return createExpectIt(expect, copiedExpectations, forwardedFlags); + }; - expectIt[ - `or${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}` - ] = function (...args) { - const copiedExpectations = expectations.slice(); - copiedExpectations.push(OR, [ - methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this - ...args, - ]); - return createExpectIt(expect, copiedExpectations, forwardedFlags); - }; + expectIt[`or${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}`] = + function (...args) { + const copiedExpectations = expectations.slice(); + copiedExpectations.push(OR, [ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), // Eeeeek, fix this + ...args, + ]); + return createExpectIt(expect, copiedExpectations, forwardedFlags); + }; }); return expectIt; @@ -1358,14 +1356,15 @@ expectPrototype._createWrappedExpect = function ( for (let i = 2; i < arguments.length; i += 1) { args[i - 2] = arguments[i]; } - return wrappedExpect._callInNestedContext(() => - parentExpect._executeExpect( - context.child(), - subject, - testDescriptionString, - args, - wrappedExpect.flags - ) + return wrappedExpect._callInNestedContext( + () => + parentExpect._executeExpect( + context.child(), + subject, + testDescriptionString, + args, + wrappedExpect.flags + ).result ); } @@ -1476,7 +1475,10 @@ expectPrototype._executeExpect = function ( forwardedFlags ); - return oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)); + return { + result: oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)), + wrappedExpect, + }; }; expectPrototype._camelCaser = function (context, subjectType, subject) { @@ -1490,13 +1492,15 @@ expectPrototype._camelCaser = function (context, subjectType, subject) { subjectType.is(assertion.subject.type) ) ) { - let method = (subject) => (...args) => { - return this._expect(context, [ - subject, - testDescriptionString, - ...args, - ]); - }; + let method = + (subject) => + (...args) => { + return this._expect(context, [ + subject, + testDescriptionString, + ...args, + ]); + }; if (subjectType) { method = method(subject); @@ -1532,7 +1536,7 @@ expectPrototype._expect = function (context, args, forwardedFlags) { } try { - let result = this._executeExpect( + let { result, wrappedExpect } = this._executeExpect( context, subject, testDescriptionString, @@ -1557,7 +1561,8 @@ expectPrototype._expect = function (context, args, forwardedFlags) { result, this, subject, - Array.prototype.slice.call(args, 0, 2) + Array.prototype.slice.call(args, 0, 2), + wrappedExpect ); } catch (e) { if (e && e._isUnexpected) { @@ -1837,6 +1842,53 @@ expectPrototype._callInNestedContext = function (callback) { } }; +expectPrototype.shifty = function (subject, args, rest) { + this._assertWrappedExpect(); + + const nextArgumentType = this.findTypeOf(rest[0]); + if (arguments.length > 1) { + // Legacy + this.argsOutput = (output) => { + args.forEach((arg, index) => { + if (index > 0) { + output.text(', '); + } + output.appendInspected(arg); + }); + + if (args.length > 0) { + output.sp(); + } + if (nextArgumentType.is('string')) { + output.error(rest[0]); + } else if (rest.length > 0) { + output.appendInspected(rest[0]); + } + if (rest.length > 1) { + output.sp(); + } + rest.slice(1).forEach((arg, index) => { + if (index > 0) { + output.text(', '); + } + output.appendInspected(arg); + }); + }; + } + if (nextArgumentType.is('expect.it')) { + return this.withError( + () => rest[0](subject), + (err) => { + this.fail(err); + } + ); + } else if (nextArgumentType.is('string')) { + return this.execute(subject, ...rest); + } else { + return subject; + } +}; + expectPrototype.shift = function (subject, assertionIndex) { this._assertWrappedExpect(); if (arguments.length <= 1) { @@ -1860,48 +1912,7 @@ expectPrototype.shift = function (subject, assertionIndex) { if (assertionIndex !== -1) { const args = this.args.slice(0, assertionIndex); const rest = this.args.slice(assertionIndex); - const nextArgumentType = this.findTypeOf(rest[0]); - if (arguments.length > 1) { - // Legacy - this.argsOutput = (output) => { - args.forEach((arg, index) => { - if (index > 0) { - output.text(', '); - } - output.appendInspected(arg); - }); - - if (args.length > 0) { - output.sp(); - } - if (nextArgumentType.is('string')) { - output.error(rest[0]); - } else if (rest.length > 0) { - output.appendInspected(rest[0]); - } - if (rest.length > 1) { - output.sp(); - } - rest.slice(1).forEach((arg, index) => { - if (index > 0) { - output.text(', '); - } - output.appendInspected(arg); - }); - }; - } - if (nextArgumentType.is('expect.it')) { - return this.withError( - () => rest[0](subject), - (err) => { - this.fail(err); - } - ); - } else if (nextArgumentType.is('string')) { - return this.execute(subject, ...rest); - } else { - return subject; - } + return this.shifty(subject, args, rest); } else { // No assertion to delegate to. Provide the new subject as the fulfillment value: return subject; From 0ac7ffc22ba4e623ad2ad0df1d82c55466939f82 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 29 May 2022 22:48:26 +0200 Subject: [PATCH 11/19] Fix shifty legacy mode --- lib/createTopLevelExpect.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index e3c407260..c28d4500b 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1842,11 +1842,11 @@ expectPrototype._callInNestedContext = function (callback) { } }; -expectPrototype.shifty = function (subject, args, rest) { +expectPrototype.shifty = function (subject, args, rest, legacyMode) { this._assertWrappedExpect(); const nextArgumentType = this.findTypeOf(rest[0]); - if (arguments.length > 1) { + if (legacyMode) { // Legacy this.argsOutput = (output) => { args.forEach((arg, index) => { @@ -1912,7 +1912,7 @@ expectPrototype.shift = function (subject, assertionIndex) { if (assertionIndex !== -1) { const args = this.args.slice(0, assertionIndex); const rest = this.args.slice(assertionIndex); - return this.shifty(subject, args, rest); + return this.shifty(subject, args, rest, arguments.length > 1); } else { // No assertion to delegate to. Provide the new subject as the fulfillment value: return subject; From 553182f313b90122239892d1e921518fd5044d54 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 29 May 2022 22:55:56 +0200 Subject: [PATCH 12/19] fix --- lib/addAdditionalPromiseMethods.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/addAdditionalPromiseMethods.js b/lib/addAdditionalPromiseMethods.js index e5b178b6d..8610a00fd 100644 --- a/lib/addAdditionalPromiseMethods.js +++ b/lib/addAdditionalPromiseMethods.js @@ -45,7 +45,8 @@ function addAdditionalPromiseMethods( [ methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), ...args, - ] + ], + true // legacy mode (FIXME) ); } else { // find ud af at fange konteksten From 13996cf3855520c260cef4d970e8c8546d9c1265 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 30 May 2022 23:11:31 +0200 Subject: [PATCH 13/19] Hacketyfix --- lib/createTopLevelExpect.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index c28d4500b..7b9f3e4b1 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1458,14 +1458,6 @@ expectPrototype._executeExpect = function ( } } - if (assertionRule.expect && assertionRule.expect !== this._topLevelExpect) { - return assertionRule.expect._expect(context, [ - subject, - testDescriptionString, - ...args, - ]); - } - const wrappedExpect = this._createWrappedExpect( assertionRule, subject, @@ -1475,6 +1467,17 @@ expectPrototype._executeExpect = function ( forwardedFlags ); + if (assertionRule.expect && assertionRule.expect !== this._topLevelExpect) { + return { + result: assertionRule.expect._expect(context, [ + subject, + testDescriptionString, + ...args, + ]), + expect: wrappedExpect, + }; + } + return { result: oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)), wrappedExpect, From 6c72280bb3a03908255fb6ed41d6a222d2516e03 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 30 May 2022 23:32:43 +0200 Subject: [PATCH 14/19] fix --- lib/addAdditionalPromiseMethods.js | 100 ------------------------- lib/createTopLevelExpect.js | 115 +++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 105 deletions(-) delete mode 100644 lib/addAdditionalPromiseMethods.js diff --git a/lib/addAdditionalPromiseMethods.js b/lib/addAdditionalPromiseMethods.js deleted file mode 100644 index 8610a00fd..000000000 --- a/lib/addAdditionalPromiseMethods.js +++ /dev/null @@ -1,100 +0,0 @@ -const Context = require('./Context'); - -function addAdditionalPromiseMethods( - promise, - expect, - subject, - args, - wrappedExpect -) { - promise.and = function (...args) { - function executeAnd() { - if (expect.findTypeOf(args[0]).is('expect.it')) { - return addAdditionalPromiseMethods(args[0](subject), expect, subject); - } else { - return expect(subject, ...args); - } - } - - if (this.isFulfilled()) { - return executeAnd(); - } else { - return addAdditionalPromiseMethods( - this.then(executeAnd), - expect, - subject - ); - } - }; - - const camelCaseMethods = expect._camelCaser(expect.context || new Context()); - Object.keys(camelCaseMethods).forEach((methodName) => { - promise[methodName] = function (...args) { - function execute(shiftedSubject) { - if (expect.findTypeOf(args[0]).is('expect.it')) { - return addAdditionalPromiseMethods( - args[0](shiftedSubject), - expect, - subject - ); - } else { - if (wrappedExpect) { - return wrappedExpect.shifty( - shiftedSubject, - wrappedExpect.args || [], - [ - methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), - ...args, - ], - true // legacy mode (FIXME) - ); - } else { - // find ud af at fange konteksten - return expect._executeExpect( - new Context(), - shiftedSubject, - methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), - args, - {} // forwardedFlags - ); - } - } - } - - if (this.isFulfilled()) { - return execute(this.value()); - } else { - return addAdditionalPromiseMethods(this.then(execute), expect, subject); - } - }; - - promise[`and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}`] = - function (...args) { - function execute() { - if (expect.findTypeOf(args[0]).is('expect.it')) { - return addAdditionalPromiseMethods( - args[0](subject), - expect, - subject - ); - } else { - return camelCaseMethods[methodName](subject)(...args); - } - } - - if (this.isFulfilled()) { - return execute(this.value()); - } else { - return addAdditionalPromiseMethods( - this.then(execute), - expect, - subject - ); - } - }; - }); - - return promise; -} - -module.exports = addAdditionalPromiseMethods; diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 7b9f3e4b1..5abc757ef 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -4,7 +4,6 @@ const magicpen = require('magicpen'); const extend = utils.extend; const ukkonen = require('ukkonen'); const makePromise = require('./makePromise'); -const addAdditionalPromiseMethods = require('./addAdditionalPromiseMethods'); const wrapPromiseIfNecessary = require('./wrapPromiseIfNecessary'); const oathbreaker = require('./oathbreaker'); const UnexpectedError = require('./UnexpectedError'); @@ -1321,6 +1320,112 @@ expectPrototype.setErrorMessage = function (err) { err.serializeMessage(this.outputFormat()); }; +expectPrototype.addAdditionalPromiseMethods = function ( + promise, + expect, + subject, + args, + wrappedExpect +) { + // const expect = this; + promise.and = function (...args) { + function executeAnd() { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return expect.addAdditionalPromiseMethods( + args[0](subject), + expect, + subject + ); + } else { + return expect(subject, ...args); + } + } + + if (this.isFulfilled()) { + return executeAnd(); + } else { + return expect.addAdditionalPromiseMethods( + this.then(executeAnd), + expect, + subject + ); + } + }; + + const camelCaseMethods = expect._camelCaser(expect.context || new Context()); + Object.keys(camelCaseMethods).forEach((methodName) => { + promise[methodName] = function (...args) { + function execute(shiftedSubject) { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return expect.addAdditionalPromiseMethods( + args[0](shiftedSubject), + expect, + subject + ); + } else { + if (wrappedExpect) { + return wrappedExpect.shifty( + shiftedSubject, + wrappedExpect.args || [], + [ + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), + ...args, + ], + true // legacy mode (FIXME) + ); + } else { + // find ud af at fange konteksten + return expect._executeExpect( + new Context(), + shiftedSubject, + methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), + args, + {} // forwardedFlags + ); + } + } + } + + if (this.isFulfilled()) { + return execute(this.value()); + } else { + return expect.addAdditionalPromiseMethods( + this.then(execute), + expect, + subject + ); + } + }; + + promise[`and${methodName.replace(/^[a-z]/, ($0) => $0.toUpperCase())}`] = + function (...args) { + function execute() { + if (expect.findTypeOf(args[0]).is('expect.it')) { + return expect.addAdditionalPromiseMethods( + args[0](subject), + expect, + subject + ); + } else { + return camelCaseMethods[methodName](subject)(...args); + } + } + + if (this.isFulfilled()) { + return execute(this.value()); + } else { + return expect.addAdditionalPromiseMethods( + this.then(execute), + expect, + subject + ); + } + }; + }); + + return promise; +}; + expectPrototype._createWrappedExpect = function ( assertionRule, subject, @@ -1336,7 +1441,7 @@ expectPrototype._createWrappedExpect = function ( if (arguments.length === 0) { throw new Error('The expect function requires at least one parameter.'); } else if (arguments.length === 1) { - return addAdditionalPromiseMethods( + return wrappedExpect.addAdditionalPromiseMethods( makePromise.resolve(subject), wrappedExpect, subject @@ -1474,7 +1579,7 @@ expectPrototype._executeExpect = function ( testDescriptionString, ...args, ]), - expect: wrappedExpect, + wrappedExpect, }; } @@ -1560,7 +1665,7 @@ expectPrototype._expect = function (context, args, forwardedFlags) { } else { result = makePromise.resolve(result); } - return addAdditionalPromiseMethods( + return wrappedExpect.addAdditionalPromiseMethods( result, this, subject, @@ -1834,7 +1939,7 @@ expectPrototype._callInNestedContext = function (callback) { } else { result = makePromise.resolve(result); } - return addAdditionalPromiseMethods(result, this.execute, this.subject); + return this.addAdditionalPromiseMethods(result, this.execute, this.subject); } catch (e) { if (e && e._isUnexpected) { const wrappedError = new UnexpectedError(this, e); From 638162c663c0d54905d15ffda31c43667af599f9 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 30 May 2022 23:42:05 +0200 Subject: [PATCH 15/19] Unhack --- lib/createTopLevelExpect.js | 87 +++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 5abc757ef..8b09a7dc4 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1461,15 +1461,14 @@ expectPrototype._createWrappedExpect = function ( for (let i = 2; i < arguments.length; i += 1) { args[i - 2] = arguments[i]; } - return wrappedExpect._callInNestedContext( - () => - parentExpect._executeExpect( - context.child(), - subject, - testDescriptionString, - args, - wrappedExpect.flags - ).result + return wrappedExpect._callInNestedContext(() => + parentExpect._executeExpect( + context.child(), + subject, + testDescriptionString, + args, + wrappedExpect.flags + ) ); } @@ -1573,20 +1572,39 @@ expectPrototype._executeExpect = function ( ); if (assertionRule.expect && assertionRule.expect !== this._topLevelExpect) { - return { - result: assertionRule.expect._expect(context, [ - subject, - testDescriptionString, - ...args, - ]), - wrappedExpect, - }; + return assertionRule.expect._expect(context, [ + subject, + testDescriptionString, + ...args, + ]); } - return { - result: oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args)), - wrappedExpect, - }; + let result = oathbreaker( + assertionRule.handler(wrappedExpect, subject, ...args) + ); + + if (utils.isPromise(result)) { + result = wrapPromiseIfNecessary(result); + if (result.isPending()) { + result = result.then(undefined, (e) => { + if (e && e._isUnexpected && context.level === 0) { + this.setErrorMessage(e); + } + throw e; + }); + this.notifyPendingPromise(result); + } + } else { + result = makePromise.resolve(result); + } + // Her mangler vi wrappedExpect? + return wrappedExpect.addAdditionalPromiseMethods( + result, + this, + subject, + Array.prototype.slice.call(args, 0, 2), + wrappedExpect + ); }; expectPrototype._camelCaser = function (context, subjectType, subject) { @@ -1644,34 +1662,13 @@ expectPrototype._expect = function (context, args, forwardedFlags) { } try { - let { result, wrappedExpect } = this._executeExpect( + return this._executeExpect( context, subject, testDescriptionString, Array.prototype.slice.call(args, 2), forwardedFlags ); - if (utils.isPromise(result)) { - result = wrapPromiseIfNecessary(result); - if (result.isPending()) { - result = result.then(undefined, (e) => { - if (e && e._isUnexpected && context.level === 0) { - this.setErrorMessage(e); - } - throw e; - }); - this.notifyPendingPromise(result); - } - } else { - result = makePromise.resolve(result); - } - return wrappedExpect.addAdditionalPromiseMethods( - result, - this, - subject, - Array.prototype.slice.call(args, 0, 2), - wrappedExpect - ); } catch (e) { if (e && e._isUnexpected) { let newError = e; @@ -1951,8 +1948,6 @@ expectPrototype._callInNestedContext = function (callback) { }; expectPrototype.shifty = function (subject, args, rest, legacyMode) { - this._assertWrappedExpect(); - const nextArgumentType = this.findTypeOf(rest[0]); if (legacyMode) { // Legacy @@ -1991,7 +1986,7 @@ expectPrototype.shifty = function (subject, args, rest, legacyMode) { } ); } else if (nextArgumentType.is('string')) { - return this.execute(subject, ...rest); + return this(subject, ...rest); } else { return subject; } From 060a56eeae1c52c095bc2dd844c60e42ea12d1b9 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 31 May 2022 00:08:28 +0200 Subject: [PATCH 16/19] simplify --- lib/createTopLevelExpect.js | 40 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 8b09a7dc4..16dc88299 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1322,20 +1322,16 @@ expectPrototype.setErrorMessage = function (err) { expectPrototype.addAdditionalPromiseMethods = function ( promise, - expect, subject, - args, - wrappedExpect ) { + const stack = new Error('hey').stack; + const wrappedExpect = this; + const expect = this._topLevelExpect; // const expect = this; promise.and = function (...args) { function executeAnd() { if (expect.findTypeOf(args[0]).is('expect.it')) { - return expect.addAdditionalPromiseMethods( - args[0](subject), - expect, - subject - ); + return expect.addAdditionalPromiseMethods(args[0](subject), subject); } else { return expect(subject, ...args); } @@ -1344,11 +1340,7 @@ expectPrototype.addAdditionalPromiseMethods = function ( if (this.isFulfilled()) { return executeAnd(); } else { - return expect.addAdditionalPromiseMethods( - this.then(executeAnd), - expect, - subject - ); + return expect.addAdditionalPromiseMethods(this.then(executeAnd), subject); } }; @@ -1359,14 +1351,13 @@ expectPrototype.addAdditionalPromiseMethods = function ( if (expect.findTypeOf(args[0]).is('expect.it')) { return expect.addAdditionalPromiseMethods( args[0](shiftedSubject), - expect, subject ); } else { - if (wrappedExpect) { + if (wrappedExpect !== expect) { return wrappedExpect.shifty( shiftedSubject, - wrappedExpect.args || [], + wrappedExpect.args, [ methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), ...args, @@ -1389,11 +1380,7 @@ expectPrototype.addAdditionalPromiseMethods = function ( if (this.isFulfilled()) { return execute(this.value()); } else { - return expect.addAdditionalPromiseMethods( - this.then(execute), - expect, - subject - ); + return expect.addAdditionalPromiseMethods(this.then(execute), subject); } }; @@ -1403,7 +1390,6 @@ expectPrototype.addAdditionalPromiseMethods = function ( if (expect.findTypeOf(args[0]).is('expect.it')) { return expect.addAdditionalPromiseMethods( args[0](subject), - expect, subject ); } else { @@ -1416,7 +1402,6 @@ expectPrototype.addAdditionalPromiseMethods = function ( } else { return expect.addAdditionalPromiseMethods( this.then(execute), - expect, subject ); } @@ -1441,9 +1426,8 @@ expectPrototype._createWrappedExpect = function ( if (arguments.length === 0) { throw new Error('The expect function requires at least one parameter.'); } else if (arguments.length === 1) { - return wrappedExpect.addAdditionalPromiseMethods( + return parentExpect.addAdditionalPromiseMethods( makePromise.resolve(subject), - wrappedExpect, subject ); } else if (typeof testDescriptionString === 'function') { @@ -1597,13 +1581,9 @@ expectPrototype._executeExpect = function ( } else { result = makePromise.resolve(result); } - // Her mangler vi wrappedExpect? return wrappedExpect.addAdditionalPromiseMethods( result, - this, subject, - Array.prototype.slice.call(args, 0, 2), - wrappedExpect ); }; @@ -1936,7 +1916,7 @@ expectPrototype._callInNestedContext = function (callback) { } else { result = makePromise.resolve(result); } - return this.addAdditionalPromiseMethods(result, this.execute, this.subject); + return this.addAdditionalPromiseMethods(result, this.subject); } catch (e) { if (e && e._isUnexpected) { const wrappedError = new UnexpectedError(this, e); From f96b3861d6337d4e203517235317efbf4ab22af4 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 31 May 2022 07:28:12 +0200 Subject: [PATCH 17/19] Clean --- lib/createTopLevelExpect.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index 16dc88299..f4f826916 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1320,14 +1320,9 @@ expectPrototype.setErrorMessage = function (err) { err.serializeMessage(this.outputFormat()); }; -expectPrototype.addAdditionalPromiseMethods = function ( - promise, - subject, -) { - const stack = new Error('hey').stack; +expectPrototype.addAdditionalPromiseMethods = function (promise, subject) { const wrappedExpect = this; const expect = this._topLevelExpect; - // const expect = this; promise.and = function (...args) { function executeAnd() { if (expect.findTypeOf(args[0]).is('expect.it')) { @@ -1581,10 +1576,7 @@ expectPrototype._executeExpect = function ( } else { result = makePromise.resolve(result); } - return wrappedExpect.addAdditionalPromiseMethods( - result, - subject, - ); + return wrappedExpect.addAdditionalPromiseMethods(result, subject); }; expectPrototype._camelCaser = function (context, subjectType, subject) { From 834abfe23b150fcb590a8c7ff8c37a8842b98e24 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 31 May 2022 07:37:06 +0200 Subject: [PATCH 18/19] simplify --- lib/createTopLevelExpect.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index f4f826916..c22b84d1b 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1360,13 +1360,11 @@ expectPrototype.addAdditionalPromiseMethods = function (promise, subject) { true // legacy mode (FIXME) ); } else { - // find ud af at fange konteksten return expect._executeExpect( new Context(), shiftedSubject, methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), - args, - {} // forwardedFlags + args ); } } From a3b3ee08c2ffa51e0f5fac8aa88bd4b733733a1c Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 31 May 2022 07:47:36 +0200 Subject: [PATCH 19/19] clean --- lib/createTopLevelExpect.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/createTopLevelExpect.js b/lib/createTopLevelExpect.js index c22b84d1b..5becbe075 100644 --- a/lib/createTopLevelExpect.js +++ b/lib/createTopLevelExpect.js @@ -1350,14 +1350,14 @@ expectPrototype.addAdditionalPromiseMethods = function (promise, subject) { ); } else { if (wrappedExpect !== expect) { - return wrappedExpect.shifty( + return wrappedExpect._shifty( shiftedSubject, wrappedExpect.args, [ methodName.replace(/[A-Z]/g, ($0) => ` ${$0.toLowerCase()}`), ...args, ], - true // legacy mode (FIXME) + true // setArgsOutput ); } else { return expect._executeExpect( @@ -1917,10 +1917,9 @@ expectPrototype._callInNestedContext = function (callback) { } }; -expectPrototype.shifty = function (subject, args, rest, legacyMode) { +expectPrototype._shifty = function (subject, args, rest, setArgsOutput) { const nextArgumentType = this.findTypeOf(rest[0]); - if (legacyMode) { - // Legacy + if (setArgsOutput) { this.argsOutput = (output) => { args.forEach((arg, index) => { if (index > 0) { @@ -1985,7 +1984,8 @@ expectPrototype.shift = function (subject, assertionIndex) { if (assertionIndex !== -1) { const args = this.args.slice(0, assertionIndex); const rest = this.args.slice(assertionIndex); - return this.shifty(subject, args, rest, arguments.length > 1); + const setArgsOutput = arguments.length > 1; + return this._shifty(subject, args, rest, setArgsOutput); } else { // No assertion to delegate to. Provide the new subject as the fulfillment value: return subject;