Skip to content

Commit 534e13b

Browse files
sunnylqmclaude
andcommitted
test(e2e): switch between cases via resetToPackagedBundle, not reinstall
Per-case cleanup used launchApp({delete:true}) — a full uninstall + reinstall whose simctl ritual costs 30-60s per case on CI and is the biggest remaining flake source (terminate retry stalls). The suite now reinstalls once in beforeAll and each case resets through the app's new reset-to-packaged button + relaunch, which also gives the Phase 1 resetToPackagedBundle API standing on-device e2e coverage on every run (a reset failure surfaces immediately in the BINARY_BASE assertion). Verified on-device: iOS 2/2, android emulator 2/2. Depends on the resetToPackagedBundle feature commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e6bdf45 commit 534e13b

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

‎Example/e2etest/e2e/local-merge.test.ts‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,43 @@ async function runDeferredUpdate(
166166
}
167167

168168
describe('Local Update Merge E2E', () => {
169-
beforeEach(async () => {
169+
beforeAll(async () => {
170+
// 只在套件开头做一次卸载重装保证初装干净;用例间的状态清理走
171+
// resetToPackagedBundle(见 beforeEach),省掉每用例 ~30-60s 的
172+
// uninstall/reinstall 仪式(CI 上还是 simctl flake 大户)。
170173
await device.launchApp({
171174
newInstance: true,
172175
delete: true,
173176
...getDetoxLaunchArgs(),
174177
});
178+
});
179+
180+
beforeEach(async () => {
181+
await device.launchApp({
182+
newInstance: true,
183+
...getDetoxLaunchArgs(),
184+
});
175185
// 更新下载/检查请求在飞时不能算 "app busy":否则 Detox 的 idle 同步
176186
// 会干等主队列清空直到用例超时(iOS 上的高频 flake 来源,症状是
177187
// "work items pending on the dispatch queue")。
178188
await device.setURLBlacklist([`.*:${LOCAL_UPDATE_PORT}.*`]);
189+
190+
// 无条件 reset(已是基座时为幂等空操作)再重启,统一回到打包基座。
191+
// 顺带让 resetToPackagedBundle 获得每次 CI 的常驻 e2e 覆盖——
192+
// 它坏了会在下面的 BINARY_BASE 断言上立刻暴露。
193+
await waitForReady();
194+
await waitFor(element(by.id('reset-to-packaged')))
195+
.toBeVisible()
196+
.withTimeout(10000);
197+
await element(by.id('reset-to-packaged')).tap();
198+
await waitFor(element(by.id('last-event')))
199+
.toHaveText('lastEvent: resetDone')
200+
.withTimeout(15000);
201+
await relaunchAppPreservingData();
202+
await device.setURLBlacklist([`.*:${LOCAL_UPDATE_PORT}.*`]);
203+
await waitForReady();
204+
await waitForBundleLabel(LOCAL_UPDATE_LABELS.base);
205+
await waitForHash('');
179206
});
180207

181208
it('covers local full update, diff merge, package diff, and v2-track diff through checkUpdate + silentAndNow', async () => {

‎Example/e2etest/src/index.tsx‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ function App() {
2525
lastError,
2626
progress: { received, total } = {},
2727
currentVersionInfo,
28+
resetToPackagedBundle,
2829
} = useUpdate();
2930
const client = contextClient!;
3031
const [lastEvent, setLastEvent] = useState('idle');
@@ -103,6 +104,22 @@ function App() {
103104
>
104105
<Text style={styles.buttonText}>Use SilentAndLater</Text>
105106
</Pressable>
107+
<Pressable
108+
testID="reset-to-packaged"
109+
style={styles.button}
110+
onPress={async () => {
111+
setLastEvent('triggerReset');
112+
try {
113+
await resetToPackagedBundle({ restart: false });
114+
setLastEvent('resetDone');
115+
} catch (e) {
116+
setLastEvent('resetFailed');
117+
setLastEventData(e instanceof Error ? e.message : String(e));
118+
}
119+
}}
120+
>
121+
<Text style={styles.buttonText}>Reset</Text>
122+
</Pressable>
106123
</View>
107124

108125
<Pressable

0 commit comments

Comments
 (0)