-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add td.instance() #448
Add td.instance() #448
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,6 +135,23 @@ export function constructor<T>( | |
constructor: Constructor<T> | ||
): TestDoubleConstructor<T>; | ||
|
||
// | ||
// fake: instance objects | ||
// | ||
|
||
/** | ||
* Construct an instance of a faked class. | ||
* | ||
* @export | ||
* @template T | ||
* @param {{ new (...args: any[]): T }} constructor | ||
* @returns {DoubledObject<typeof T>} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was not sure what the return type should be here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lgandecki as resident typescript typings maintainer could you please help with this / add a suggestion for what it should be? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure thing. Looks correct. I've also verified it by cloning the branch and playing around with it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @lgandecki! I agree it would be more convenient to have Looking at this particular change again, I think my use of In my home project, I have the need to annotate a constructor, and I needed IntelliJ to understand that the return value from the annotation function was the constructor. Here's how I expressed that in JSDoc:
If the JSDoc part of a TypeScript declaration understands
I'll try this out later today and see how IntelliJ interprets it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. I'm unfortunately not really familiar with JSDocs :-( |
||
*/ | ||
export function instance<T>( | ||
constructor: Constructor<T> | ||
): DoubledObject<T>; | ||
|
||
|
||
// | ||
// fake: functions | ||
// ---------------------------------------------------------------------------- | ||
|
@@ -252,7 +269,7 @@ export function imitate<T>(original: T, name?: string): TestDouble<T>; | |
export function callback(...args: any[]): void; | ||
|
||
/** | ||
* Swap out real dependenencies with fake one. Intercept calls to `require` | ||
* Swap out real dependencies with fake one. Intercept calls to `require` | ||
* that dependency module and ensure your subject is handed a fake instead. | ||
* | ||
* @export | ||
|
@@ -262,7 +279,7 @@ export function callback(...args: any[]): void; | |
*/ | ||
export function replace(path: string, f?: any): any; | ||
/** | ||
* Swap out real dependenencies with fake one. Intercept calls to `require` | ||
* Swap out real dependencies with fake one. Intercept calls to `require` | ||
* that dependency module and ensure your subject is handed a fake instead. | ||
* | ||
* @export | ||
|
@@ -272,7 +289,7 @@ export function replace(path: string, f?: any): any; | |
*/ | ||
export function replaceCjs(path: string, f?: any): any; | ||
/** | ||
* Swap out real dependenencies with fake one. Intercept calls to `import` | ||
* Swap out real dependencies with fake one. Intercept calls to `import` | ||
* that dependency module and ensure your subject is handed a fake instead. | ||
* | ||
* @export | ||
|
@@ -285,7 +302,7 @@ export function replaceEsm(path: string, namedExportStubs?: any, defaultExportSt | |
Promise<{default?: any, [namedExport: string]: any}>; | ||
|
||
/** | ||
* Swap out real dependenencies with fake one. Reference to the property will | ||
* Swap out real dependencies with fake one. Reference to the property will | ||
* be replace it during your test. | ||
* | ||
* @export | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import constructor from './constructor.js' | ||
|
||
export default function instance (typeOrNames) { | ||
return new (constructor(typeOrNames))() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can redo this if you'd like to recommend a style that better matches the rest of the codebase. Can do the _.tap thing if you think it looks better. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
let Thing, SuperThing, fakeInstance | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pared down version of |
||
|
||
module.exports = { | ||
'being given an mock object instance': { | ||
beforeEach () { | ||
SuperThing = function SuperThing () {} | ||
SuperThing.prototype.biz = () => 1 | ||
Object.defineProperties(SuperThing.prototype, { | ||
secretFunc: { | ||
value () {}, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}) | ||
|
||
Thing = function Thing () {} | ||
Thing.prototype = new SuperThing() | ||
Thing.prototype.foo = () => 2 | ||
Thing.bar = () => 3 | ||
Thing.prototype.instanceAttr = 'baz' | ||
Thing.staticAttr = 'qux' | ||
Object.defineProperties(Thing, { | ||
secretStaticFunc: { | ||
value () {}, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}) | ||
|
||
fakeInstance = td.instance(Thing) | ||
}, | ||
'instance methods can be stubbed' () { | ||
td.when(fakeInstance.foo()).thenReturn(7) | ||
|
||
assert._isEqual(fakeInstance.foo(), 7) | ||
}, | ||
'super type methods can be stubbed, too' () { | ||
td.when(fakeInstance.biz()).thenReturn(6) | ||
|
||
assert._isEqual(fakeInstance.biz(), 6) | ||
}, | ||
'things print OK' () { | ||
assert._isEqual(fakeInstance.foo.toString(), '[test double for "Thing.prototype.foo"]') | ||
}, | ||
'non-enumerables are covered' () { | ||
assert._isEqual(td.explain(fakeInstance.secretFunc).isTestDouble, true) | ||
}, | ||
'instanceof checks out' () { | ||
assert._isEqual(fakeInstance instanceof Thing, true) | ||
}, | ||
'original attributes are carried over' () { | ||
assert._isEqual(fakeInstance.instanceAttr, 'baz') | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please help me refine this documentation section