1 | import * as theredoc from 'theredoc'
|
2 | import _ from '../wrap/lodash'
|
3 | import log from '../log'
|
4 | import tdFunction from '../function'
|
5 | import store from '../store'
|
6 |
|
7 | export default function proxy<T> (name: string, { excludeMethods } : { excludeMethods?: string[] } = {}) : T {
|
8 | ensureProxySupport(name)
|
9 | return new Proxy({}, generateHandler(name, excludeMethods))
|
10 | }
|
11 |
|
12 | const ensureProxySupport = (name) => {
|
13 | if (typeof Proxy === 'undefined') {
|
14 | log.error('td.object', theredoc`\
|
15 | The current runtime does not have Proxy support, which is what
|
16 | testdouble.js depends on when a string name is passed to \`td.object()\`.
|
17 |
|
18 | More details here:
|
19 | https://github.com/testdouble/testdouble.js/blob/master/docs/4-creating-test-doubles.md#objectobjectname
|
20 |
|
21 | Did you mean \`td.object(['${name}'])\`?
|
22 | `)
|
23 | }
|
24 | }
|
25 |
|
26 | const generateHandler = (internalName, excludeMethods) => ({
|
27 | get (target, propKey) {
|
28 | return generateGet(target, propKey, internalName, excludeMethods)
|
29 | }
|
30 | })
|
31 |
|
32 | const generateGet = (target, propKey, internalName, excludeMethods) => {
|
33 | if (!Object.prototype.hasOwnProperty.call(target, propKey) &&
|
34 | !_.includes(excludeMethods, propKey)) {
|
35 | const nameWithProp = `${internalName || ''}.${String(propKey)}`
|
36 | const tdFunc = tdFunction(nameWithProp)
|
37 | const tdFuncProxy = new Proxy(tdFunc, generateHandler(nameWithProp, excludeMethods))
|
38 | store.registerAlias(tdFunc, tdFuncProxy)
|
39 | target[propKey] = tdFuncProxy
|
40 | }
|
41 | return target[propKey]
|
42 | }
|