(
metadata: MockMetadata<T>,
restore?: () => void,
)
| 615 | ): Record<string, any>; |
| 616 | /* eslint-enable @typescript-eslint/unified-signatures */ |
| 617 | private _makeComponent<T extends UnknownFunction>( |
| 618 | metadata: MockMetadata<T>, |
| 619 | restore?: () => void, |
| 620 | ): Record<string, any> | Array<unknown> | RegExp | T | Mock | undefined { |
| 621 | if (metadata.type === 'object') { |
| 622 | return new this._environmentGlobal.Object(); |
| 623 | } else if (metadata.type === 'array') { |
| 624 | return new this._environmentGlobal.Array(); |
| 625 | } else if (metadata.type === 'regexp') { |
| 626 | return new this._environmentGlobal.RegExp(''); |
| 627 | } else if ( |
| 628 | metadata.type === 'constant' || |
| 629 | metadata.type === 'collection' || |
| 630 | metadata.type === 'null' || |
| 631 | metadata.type === 'undefined' |
| 632 | ) { |
| 633 | return metadata.value; |
| 634 | } else if (metadata.type === 'function') { |
| 635 | const prototype = metadata.members?.prototype?.members ?? {}; |
| 636 | const prototypeSlots = this._getSlots(prototype); |
| 637 | // eslint-disable-next-line @typescript-eslint/no-this-alias |
| 638 | const mocker = this; |
| 639 | const mockConstructor = matchArity(function ( |
| 640 | this: ReturnType<T>, |
| 641 | ...args: Parameters<T> |
| 642 | ) { |
| 643 | const mockState = mocker._ensureMockState(f); |
| 644 | const mockConfig = mocker._ensureMockConfig(f); |
| 645 | mockState.instances.push(this); |
| 646 | mockState.contexts.push(this); |
| 647 | mockState.calls.push(args); |
| 648 | // Create and record an "incomplete" mock result immediately upon |
| 649 | // calling rather than waiting for the mock to return. This avoids |
| 650 | // issues caused by recursion where results can be recorded in the |
| 651 | // wrong order. |
| 652 | const mockResult: MockFunctionResult = { |
| 653 | type: 'incomplete', |
| 654 | value: undefined, |
| 655 | }; |
| 656 | mockState.results.push(mockResult); |
| 657 | mockState.invocationCallOrder.push(mocker._invocationCallCounter++); |
| 658 | |
| 659 | // Will be set to the return value of the mock if an error is not thrown |
| 660 | let finalReturnValue; |
| 661 | // Will be set to the error that is thrown by the mock (if it throws) |
| 662 | let thrownError; |
| 663 | // Will be set to true if the mock throws an error. The presence of a |
| 664 | // value in `thrownError` is not a 100% reliable indicator because a |
| 665 | // function could throw a value of undefined. |
| 666 | let callDidThrowError = false; |
| 667 | |
| 668 | try { |
| 669 | // The bulk of the implementation is wrapped in an immediately |
| 670 | // executed arrow function so the return value of the mock function |
| 671 | // can be easily captured and recorded, despite the many separate |
| 672 | // return points within the logic. |
| 673 | finalReturnValue = (() => { |
| 674 | if (this instanceof f) { |
no test coverage detected