截至 2020 年 12 月,我将 detox 17.14.3 与 Expo 39.0.5 一起使用,并且无需使用独立版本即可解决此问题。下面提供了补丁和解释。
原来detox-expo-helpers 覆盖了一个环境变量(特别是SIMCTL_CHILD_DYLD_INSERT_LIBRARIES)来指定ExpoDetoxHook 框架的路径(由expo-detox-hook 包提供)。好吧,对环境的更新现在在周期中发生得太晚了。它发生在运行 Detox 的 reloadApp 时,但到那时,Detox 已经启动了 Jest,它让工作人员使用自己的 process.env 副本运行。在创建时 get a copy 的 process.env 的工作人员,并且它们不与父进程共享,因此该库对环境变量所做的更改不会反映在 Jest 工作人员内部。正在运行的应用程序无法使用钩子框架,因此 Detox 卡在等待未到来的就绪信号。
Detox 的 iOS 模拟器 launchApp 使用 SIMCTL_CHILD_DYLD_INSERT_LIBRARIES 指定它自己的库,但由于环境变量在工作器中是隔离的,它看不到这个包所做的更改。为了解决这个问题,我修改了这个库,将对 process.env 的更改作为一个单独的导出函数公开,然后我在测试生命周期的更早的时候调用它,以确保在启动任何工作程序之前设置它。这是一个兼容patch-package的补丁。
# file patches/detox-expo-helpers+0.6.0.patch
diff --git a/node_modules/detox-expo-helpers/index.js b/node_modules/detox-expo-helpers/index.js
index 864493b..3147a55 100644
--- a/node_modules/detox-expo-helpers/index.js
+++ b/node_modules/detox-expo-helpers/index.js
@@ -45,7 +45,16 @@ function resetEnvDyldVar(oldEnvVar) {
}
}
-const reloadApp = async (params) => {
+let initialized = false;
+let detoxVersion;
+let oldEnvVar;
+const init = () => {
+ if (initialized) {
+ return;
+ }
+
+ initialized = true;
+
if (!fs.existsSync(expoDetoxHookPackageJsonPath)) {
throw new Error("expo-detox-hook is not installed in this directory. You should declare it in package.json and run `npm install`");
}
@@ -56,12 +65,16 @@ const reloadApp = async (params) => {
throw new Error ("expo-detox-hook is not installed in your osx Library. Run `npm install -g expo-detox-cli && expotox clean-framework-cache && expotox build-framework-cache` to fix this.");
}
- const detoxVersion = getDetoxVersion();
- const oldEnvVar = process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES;
+ detoxVersion = getDetoxVersion();
+ oldEnvVar = process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES;
if (semver.gte(detoxVersion, '9.0.6')) {
process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES = expoDetoxHookFrameworkPath;
}
+}
+
+const reloadApp = async (params) => {
+ init();
const formattedBlacklistArg = await blacklistCmdlineFormat(params && params.urlBlacklist);
const url = await getAppUrl();
@@ -121,5 +134,6 @@ module.exports = {
getAppUrl,
getAppHttpUrl,
blacklistLiveReloadUrl,
+ init,
reloadApp,
};
有了这个,我修改了我的e2e/environment.js 文件,如下所示。添加的是initExpo 调用。当它在测试生命周期的早期运行时,环境会在任何工作程序启动之前被修改,因此,对reloadApp 的调用不再无限期地等待。
/* eslint-disable import/no-extraneous-dependencies */
const { init: initExpo } = require('detox-expo-helpers');
const { DetoxCircusEnvironment, SpecReporter, WorkerAssignReporter } = require('detox/runners/jest-circus');
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config) {
super(config);
initExpo();
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
});
}
}
module.exports = CustomDetoxEnvironment;