UNPKG

4.09 kBJavaScriptView Raw
1const colors = require('colors')
2// List of test describers to be patched.
3const functionsToPatch = ['describe', 'describe.only', 'it', 'it.only']
4// List of environments, the environment define the function name. describe.client, describe.server
5const environments = {
6 CLIENT: 'client',
7 SERVER: 'server'
8}
9
10const isNode =
11 typeof process === 'object' && process.toString() === '[object process]'
12
13export const descriptorsByEnvironmentPatcher = function descriptorsByEnvironmentPatcher() {
14 /**
15 * This function is the one with the purpose of handle and return the function that should be attached to our runOn{client | server} patch.
16 * @param {Object} descriptor Is the object that contains the name of the descriptor base function and in the cases that we have nested function calls the nested name too
17 * @param {String} env Can be one of the constants defined in the environments object - {SERVER, CLIENT}
18 * @param {Boolean} isOnly A boolean function to know if we are trying to run a descriptor with the .only Function
19 */
20 function buildFunctionForEnv({descriptorName, firstLevelFnName, env}) {
21 const shouldReturnDescriber =
22 (isNode && env === environments.SERVER) ||
23 (!isNode && env === environments.CLIENT)
24 const isOnlyServerButRunningAsClient =
25 !isNode && env === environments.SERVER && firstLevelFnName
26 const isOnlyClientButRunningAsServer =
27 isNode && env === environments.CLIENT && firstLevelFnName
28 if (shouldReturnDescriber) {
29 return function() {
30 firstLevelFnName
31 ? global[descriptorName][firstLevelFnName](...arguments)
32 : global[descriptorName](...arguments)
33 }
34 } else if (
35 isOnlyClientButRunningAsServer ||
36 isOnlyServerButRunningAsClient
37 ) {
38 return () => {
39 throw new Error(
40 colors.red(
41 `Seems that you are doing a ${descriptorName}.${env}.only but you are running the tests for the ${
42 isNode ? environments.SERVER : environments.CLIENT
43 }\n\n`
44 )
45 )
46 }
47 } else {
48 return title =>
49 console.warn(
50 colors.yellow(
51 `skiping on the ${
52 isNode ? environments.SERVER : environments.CLIENT
53 } '${descriptorName}('${title}')\n`
54 )
55 )
56 }
57 }
58
59 /**
60 * The patchChainedFunction is the function that will handle to call the buildFunctionForEnv iterating for the environments to attach the function to each one
61 * @param {Array} An array of two elements composed for the baseFnName (usually describe, it....) and a first depth level method (usually .only)
62 */
63 function patchChainedFunction([descriptorName, firstLevelFnName]) {
64 const baseFn = global[descriptorName]
65 const environmentsKeys = Object.keys(environments)
66
67 environmentsKeys.forEach(key => {
68 const env = environments[key]
69 baseFn[`${env}`][firstLevelFnName] = buildFunctionForEnv({
70 descriptorName,
71 firstLevelFnName,
72 env
73 })
74 })
75 }
76
77 /**
78 * Patch base functions will
79 * @param {String} descriptorName is a string with the name of the function to be patched.
80 */
81 function patchBaseFunctions(descriptorName) {
82 const environmentsKeys = Object.keys(environments)
83
84 environmentsKeys.forEach(key => {
85 const env = environments[key]
86 global[descriptorName][`${env}`] = buildFunctionForEnv({
87 descriptorName,
88 env
89 })
90 })
91 }
92
93 /**
94 * patchFunction is the entry method that will handle with the logic to know if is a depth descriptor patch or a baseDescriptor patch. Regarding on that will call one or another patching function
95 * @param {String} fnName is a string with the name of the function to be patched.
96 */
97 function patchFunction(fnName) {
98 const functionChainNames = fnName.split('.')
99 const isOnly = functionChainNames.length > 1
100 isOnly
101 ? patchChainedFunction(functionChainNames)
102 : patchBaseFunctions(fnName)
103 }
104
105 // Init of our patcher.
106 functionsToPatch.forEach(fnName => patchFunction(fnName))
107}