Исправить паузу после возврата в игру
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/** Device-level contract for leaving and returning to an active puzzle. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class GameLifecycleTest {
|
||||
@Test
|
||||
public void returningFromBackgroundKeepsPuzzleVisiblePausedAndClearsHeldInput() {
|
||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
try (ActivityScenario<MainActivity> scenario = ActivityScenario.launch(MainActivity.class)) {
|
||||
final GameView[] view = new GameView[1];
|
||||
scenario.onActivity(activity -> view[0] = activity.gameViewForAutomation());
|
||||
createRetainedCorpse(instrumentation, view[0]);
|
||||
|
||||
runOnGame(instrumentation, view[0], false, false, true, false);
|
||||
scenario.moveToState(Lifecycle.State.STARTED);
|
||||
GameView.AutomationSnapshot backgroundStart = snapshot(instrumentation, view[0]);
|
||||
sleep(700L);
|
||||
GameView.AutomationSnapshot backgroundEnd = snapshot(instrumentation, view[0]);
|
||||
|
||||
assertEquals(5, backgroundEnd.levelNumber());
|
||||
assertEquals(backgroundStart.deaths(), backgroundEnd.deaths());
|
||||
assertEquals(backgroundStart.corpseCount(), backgroundEnd.corpseCount());
|
||||
assertEquals(backgroundStart.playerX(), backgroundEnd.playerX(), 0.01f);
|
||||
assertEquals(backgroundStart.elapsedMilliseconds(), backgroundEnd.elapsedMilliseconds());
|
||||
|
||||
scenario.moveToState(Lifecycle.State.RESUMED);
|
||||
GameView.AutomationSnapshot returned = snapshot(instrumentation, view[0]);
|
||||
assertTrue("Returning to an active puzzle must show the pause screen", returned.visiblyPaused());
|
||||
assertFalse("Held touch input must not survive backgrounding", returned.inputActive());
|
||||
assertEquals(backgroundEnd.deaths(), returned.deaths());
|
||||
assertEquals(backgroundEnd.corpseCount(), returned.corpseCount());
|
||||
|
||||
scenario.onActivity(MainActivity::onBackPressed);
|
||||
sleep(80L);
|
||||
GameView.AutomationSnapshot resumed = snapshot(instrumentation, view[0]);
|
||||
assertFalse("Back from the visible pause screen must resume the puzzle", resumed.visiblyPaused());
|
||||
runOnGame(instrumentation, view[0], false, false, true, false);
|
||||
sleep(250L);
|
||||
runOnGame(instrumentation, view[0], false, false, false, false);
|
||||
GameView.AutomationSnapshot moving = snapshot(instrumentation, view[0]);
|
||||
assertTrue("The resumed simulation must accept movement", moving.playerX() > resumed.playerX() + 20f);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createRetainedCorpse(Instrumentation instrumentation, GameView gameView) {
|
||||
runOnGame(instrumentation, gameView, true, false, true, false);
|
||||
long deadline = System.currentTimeMillis() + 8_000L;
|
||||
boolean died = false;
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
GameView.AutomationSnapshot value = snapshot(instrumentation, gameView);
|
||||
if (!value.playerAlive()) died = true;
|
||||
if (died && value.playerAlive() && value.corpseCount() >= 1) {
|
||||
runOnGame(instrumentation, gameView, false, false, false, false);
|
||||
return;
|
||||
}
|
||||
sleep(24L);
|
||||
}
|
||||
throw new AssertionError("Level 5 did not produce a retained corpse before lifecycle check");
|
||||
}
|
||||
|
||||
private static void runOnGame(Instrumentation instrumentation, GameView gameView,
|
||||
boolean startLevelFive, boolean left, boolean right, boolean jump) {
|
||||
instrumentation.runOnMainSync(() -> {
|
||||
if (startLevelFive) gameView.startLevelForAutomation(5);
|
||||
gameView.setAutomationInput(left, right, jump);
|
||||
});
|
||||
}
|
||||
|
||||
private static GameView.AutomationSnapshot snapshot(Instrumentation instrumentation, GameView gameView) {
|
||||
final GameView.AutomationSnapshot[] value = new GameView.AutomationSnapshot[1];
|
||||
instrumentation.runOnMainSync(() -> value[0] = gameView.automationSnapshot());
|
||||
return value[0];
|
||||
}
|
||||
|
||||
private static void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new AssertionError("Lifecycle test interrupted", interrupted);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user