-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add input tests (mouse and keyboard)
- Loading branch information
1 parent
9a9fb5b
commit 5112b3b
Showing
8 changed files
with
278 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package rs.ruffle | ||
|
||
import android.content.ComponentName | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.graphics.Point | ||
import android.graphics.Rect | ||
import android.net.Uri | ||
import android.view.KeyEvent | ||
import androidx.test.core.app.ApplicationProvider | ||
import androidx.test.espresso.matcher.ViewMatchers | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.platform.app.InstrumentationRegistry | ||
import androidx.test.uiautomator.By | ||
import androidx.test.uiautomator.UiDevice | ||
import androidx.test.uiautomator.Until | ||
import java.io.File | ||
import kotlin.math.min | ||
import kotlin.math.roundToInt | ||
import org.hamcrest.CoreMatchers | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
private const val BASIC_SAMPLE_PACKAGE = "rs.ruffle" | ||
private const val LAUNCH_TIMEOUT = 5000L | ||
private const val SWF_WIDTH = 550.0 | ||
private const val SWF_HEIGHT = 400.0 | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class InputEvents { | ||
private lateinit var device: UiDevice | ||
private lateinit var traceOutput: File | ||
private lateinit var swfFile: File | ||
|
||
@Before | ||
fun startMainActivityFromHomeScreen() { | ||
// Initialize UiDevice instance | ||
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) | ||
|
||
// Start from the home screen | ||
device.pressHome() | ||
|
||
// Wait for launcher | ||
val launcherPackage: String = device.launcherPackageName | ||
ViewMatchers.assertThat(launcherPackage, CoreMatchers.notNullValue()) | ||
device.wait( | ||
Until.hasObject(By.pkg(launcherPackage).depth(0)), | ||
LAUNCH_TIMEOUT | ||
) | ||
|
||
// Launch the app | ||
val context = ApplicationProvider.getApplicationContext<Context>() | ||
traceOutput = File.createTempFile("trace", ".txt", context.cacheDir) | ||
swfFile = File.createTempFile("movie", ".swf", context.cacheDir) | ||
val resources = InstrumentationRegistry.getInstrumentation().context.resources | ||
val inStream = resources.openRawResource( | ||
rs.ruffle.test.R.raw.input_test | ||
) | ||
val bytes = inStream.readBytes() | ||
swfFile.writeBytes(bytes) | ||
val intent = context.packageManager.getLaunchIntentForPackage( | ||
BASIC_SAMPLE_PACKAGE | ||
)?.apply { | ||
component = ComponentName("rs.ruffle", "rs.ruffle.PlayerActivity") | ||
data = Uri.fromFile(swfFile) | ||
putExtra("traceOutput", traceOutput.absolutePath) | ||
// Clear out any previous instances | ||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) | ||
} | ||
context.startActivity(intent) | ||
|
||
// Wait for the app to appear | ||
device.wait( | ||
Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), | ||
LAUNCH_TIMEOUT | ||
) | ||
} | ||
|
||
@Test | ||
fun clickEvents() { | ||
device.waitForWindowUpdate(null, 1000) | ||
ViewMatchers.assertThat(device, CoreMatchers.notNullValue()) | ||
|
||
val player = device.findObject(By.desc("Ruffle Player")) | ||
|
||
val red = screenToSwf(player.visibleBounds, Point(50, 50)) | ||
val blue = screenToSwf(player.visibleBounds, Point(500, 350)) | ||
device.click(red) | ||
device.click(blue) | ||
device.drag(red.x, red.y, blue.x, blue.y, 100) | ||
device.waitForWindowUpdate(null, 500) | ||
|
||
val trace = traceOutput.readLines() | ||
ViewMatchers.assertThat( | ||
trace, | ||
CoreMatchers.equalTo( | ||
listOf( | ||
"Test started!", | ||
"red received mouseDown", | ||
"red received mouseUp", | ||
"red received click", | ||
"blue received mouseDown", | ||
"blue received mouseUp", | ||
"blue received click", | ||
"red received mouseDown", | ||
"blue received mouseUp" | ||
) | ||
) | ||
) | ||
} | ||
|
||
@Test | ||
fun keyEvents() { | ||
device.waitForWindowUpdate(null, 1000) | ||
ViewMatchers.assertThat(device, CoreMatchers.notNullValue()) | ||
|
||
device.pressKeyCode(KeyEvent.KEYCODE_A) | ||
device.pressKeyCode(KeyEvent.KEYCODE_B) | ||
|
||
device.waitForWindowUpdate(null, 500) | ||
|
||
val trace = traceOutput.readLines() | ||
ViewMatchers.assertThat( | ||
trace, | ||
CoreMatchers.equalTo( | ||
listOf( | ||
"Test started!", | ||
"keyDown: keyCode = 65, charCode = 97", | ||
"keyUp: keyCode = 65, charCode = 97", | ||
"keyDown: keyCode = 66, charCode = 98", | ||
"keyUp: keyCode = 66, charCode = 98" | ||
) | ||
) | ||
) | ||
} | ||
|
||
private fun screenToSwf(playerBounds: Rect, point: Point): Point { | ||
val stretchX = playerBounds.width() / SWF_WIDTH | ||
val stretchY = playerBounds.height() / SWF_HEIGHT | ||
val scaleFactor = min(stretchX, stretchY) | ||
val swfScreenWidth = SWF_WIDTH * scaleFactor | ||
val swfScreenHeight = SWF_HEIGHT * scaleFactor | ||
val swfOffsetX = (playerBounds.width() - swfScreenWidth) / 2 | ||
val swfOffsetY = (playerBounds.height() - swfScreenHeight) / 2 | ||
return Point( | ||
(playerBounds.left + swfOffsetX + point.x * scaleFactor).roundToInt(), | ||
(playerBounds.top + swfOffsetY + point.y * scaleFactor).roundToInt() | ||
) | ||
} | ||
} | ||
|
||
private fun UiDevice.click(point: Point) { | ||
this.click(point.x, point.y) | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package { | ||
import flash.display.MovieClip; | ||
import flash.events.MouseEvent; | ||
import flash.display.DisplayObject; | ||
import flash.events.KeyboardEvent; | ||
|
||
public class Test extends MovieClip { | ||
public function Test() { | ||
trace("Test started!"); | ||
|
||
addKeyListeners("stage", stage); | ||
addMouseListeners("red", red); | ||
addMouseListeners("blue", blue); | ||
} | ||
|
||
function addMouseListeners(name: String, clip: DisplayObject) { | ||
var listener = function(event: MouseEvent) { | ||
trace(name + " received " + event.type); | ||
}; | ||
clip.addEventListener(MouseEvent.MOUSE_DOWN, listener); | ||
clip.addEventListener(MouseEvent.MOUSE_UP, listener); | ||
//clip.addEventListener(MouseEvent.MOUSE_OVER, listener); | ||
//clip.addEventListener(MouseEvent.MOUSE_OUT, listener); | ||
clip.addEventListener(MouseEvent.CLICK, listener); | ||
} | ||
|
||
function addKeyListeners(name: String, clip: DisplayObject) { | ||
var listener = function(event: KeyboardEvent) { | ||
trace(event.type + ": keyCode = " + event.keyCode + ", charCode = " + event.charCode); | ||
}; | ||
stage.addEventListener(KeyboardEvent.KEY_DOWN, listener); | ||
stage.addEventListener(KeyboardEvent.KEY_UP, listener); | ||
} | ||
} | ||
} |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,85 @@ | ||
use android_activity::input::Keycode as Android; | ||
use ruffle_core::events::KeyCode as Ruffle; | ||
|
||
pub fn android_keycode_to_ruffle(android: Android) -> Option<Ruffle> { | ||
pub fn android_keycode_to_ruffle(android: Android) -> Option<(Ruffle, Option<char>)> { | ||
Some(match android { | ||
Android::A => Ruffle::A, | ||
Android::B => Ruffle::B, | ||
Android::C => Ruffle::C, | ||
Android::D => Ruffle::D, | ||
Android::E => Ruffle::E, | ||
Android::F => Ruffle::F, | ||
Android::G => Ruffle::G, | ||
Android::H => Ruffle::H, | ||
Android::I => Ruffle::I, | ||
Android::J => Ruffle::J, | ||
Android::K => Ruffle::K, | ||
Android::L => Ruffle::L, | ||
Android::M => Ruffle::M, | ||
Android::N => Ruffle::N, | ||
Android::O => Ruffle::O, | ||
Android::P => Ruffle::P, | ||
Android::Q => Ruffle::Q, | ||
Android::R => Ruffle::R, | ||
Android::S => Ruffle::S, | ||
Android::T => Ruffle::T, | ||
Android::U => Ruffle::U, | ||
Android::V => Ruffle::V, | ||
Android::W => Ruffle::W, | ||
Android::X => Ruffle::X, | ||
Android::Y => Ruffle::Y, | ||
Android::Z => Ruffle::Z, | ||
Android::Comma => Ruffle::Comma, | ||
Android::Period => Ruffle::Period, | ||
Android::Tab => Ruffle::Tab, | ||
Android::Space => Ruffle::Space, | ||
Android::Enter => Ruffle::Return, | ||
Android::Del => Ruffle::Delete, | ||
Android::Grave => Ruffle::Grave, | ||
Android::Minus => Ruffle::Minus, | ||
Android::Equals => Ruffle::Equals, | ||
Android::LeftBracket => Ruffle::LBracket, | ||
Android::RightBracket => Ruffle::RBracket, | ||
Android::Backslash => Ruffle::Backslash, | ||
Android::Semicolon => Ruffle::Semicolon, | ||
Android::Apostrophe => Ruffle::Apostrophe, | ||
Android::Slash => Ruffle::Slash, | ||
Android::Plus => Ruffle::Plus, | ||
Android::PageUp => Ruffle::PgUp, | ||
Android::PageDown => Ruffle::PgDown, | ||
Android::Escape => Ruffle::Escape, | ||
Android::ForwardDel => Ruffle::Delete, | ||
Android::CapsLock => Ruffle::CapsLock, | ||
Android::ScrollLock => Ruffle::ScrollLock, | ||
Android::MoveHome => Ruffle::Home, | ||
Android::MoveEnd => Ruffle::End, | ||
Android::Insert => Ruffle::Insert, | ||
Android::F1 => Ruffle::F1, | ||
Android::F2 => Ruffle::F2, | ||
Android::F3 => Ruffle::F3, | ||
Android::F4 => Ruffle::F4, | ||
Android::F5 => Ruffle::F5, | ||
Android::F6 => Ruffle::F6, | ||
Android::F7 => Ruffle::F7, | ||
Android::F8 => Ruffle::F8, | ||
Android::F9 => Ruffle::F9, | ||
Android::F10 => Ruffle::F10, | ||
Android::F11 => Ruffle::F11, | ||
Android::F12 => Ruffle::F12, | ||
Android::Numpad0 => Ruffle::Numpad0, | ||
Android::Numpad1 => Ruffle::Numpad1, | ||
Android::Numpad2 => Ruffle::Numpad2, | ||
Android::Numpad3 => Ruffle::Numpad3, | ||
Android::Numpad4 => Ruffle::Numpad4, | ||
Android::Numpad5 => Ruffle::Numpad5, | ||
Android::Numpad6 => Ruffle::Numpad6, | ||
Android::Numpad7 => Ruffle::Numpad7, | ||
Android::Numpad8 => Ruffle::Numpad8, | ||
Android::Numpad9 => Ruffle::Numpad9, | ||
Android::NumpadDivide => Ruffle::NumpadSlash, | ||
Android::NumpadSubtract => Ruffle::NumpadMinus, | ||
Android::NumpadDot => Ruffle::NumpadPeriod, | ||
Android::NumpadEnter => Ruffle::NumpadEnter, | ||
Android::A => (Ruffle::A, Some('a')), | ||
Android::B => (Ruffle::B, Some('b')), | ||
Android::C => (Ruffle::C, Some('c')), | ||
Android::D => (Ruffle::D, Some('d')), | ||
Android::E => (Ruffle::E, Some('e')), | ||
Android::F => (Ruffle::F, Some('f')), | ||
Android::G => (Ruffle::G, Some('g')), | ||
Android::H => (Ruffle::H, Some('h')), | ||
Android::I => (Ruffle::I, Some('i')), | ||
Android::J => (Ruffle::J, Some('j')), | ||
Android::K => (Ruffle::K, Some('k')), | ||
Android::L => (Ruffle::L, Some('l')), | ||
Android::M => (Ruffle::M, Some('m')), | ||
Android::N => (Ruffle::N, Some('n')), | ||
Android::O => (Ruffle::O, Some('o')), | ||
Android::P => (Ruffle::P, Some('p')), | ||
Android::Q => (Ruffle::Q, Some('q')), | ||
Android::R => (Ruffle::R, Some('r')), | ||
Android::S => (Ruffle::S, Some('s')), | ||
Android::T => (Ruffle::T, Some('t')), | ||
Android::U => (Ruffle::U, Some('u')), | ||
Android::V => (Ruffle::V, Some('v')), | ||
Android::W => (Ruffle::W, Some('w')), | ||
Android::X => (Ruffle::X, Some('x')), | ||
Android::Y => (Ruffle::Y, Some('y')), | ||
Android::Z => (Ruffle::Z, Some('z')), | ||
Android::Comma => (Ruffle::Comma, Some(',')), | ||
Android::Period => (Ruffle::Period, Some('.')), | ||
Android::Tab => (Ruffle::Tab, Some('\t')), | ||
Android::Space => (Ruffle::Space, Some(' ')), | ||
Android::Enter => (Ruffle::Return, Some(13 as char)), | ||
Android::Del => (Ruffle::Backspace, Some(8 as char)), | ||
Android::Grave => (Ruffle::Grave, Some('`')), | ||
Android::Minus => (Ruffle::Minus, Some('-')), | ||
Android::Equals => (Ruffle::Equals, Some('=')), | ||
Android::LeftBracket => (Ruffle::LBracket, Some('(')), | ||
Android::RightBracket => (Ruffle::RBracket, Some(')')), | ||
Android::Backslash => (Ruffle::Backslash, Some('\\')), | ||
Android::Semicolon => (Ruffle::Semicolon, Some(';')), | ||
Android::Apostrophe => (Ruffle::Apostrophe, Some('\'')), | ||
Android::Slash => (Ruffle::Slash, Some('/')), | ||
Android::Plus => (Ruffle::Plus, Some('+')), | ||
Android::PageUp => (Ruffle::PgUp, None), | ||
Android::PageDown => (Ruffle::PgDown, None), | ||
Android::Escape => (Ruffle::Escape, None), | ||
Android::ForwardDel => (Ruffle::Delete, Some(127 as char)), | ||
Android::CapsLock => (Ruffle::CapsLock, None), | ||
Android::ScrollLock => (Ruffle::ScrollLock, None), | ||
Android::MoveHome => (Ruffle::Home, None), | ||
Android::MoveEnd => (Ruffle::End, None), | ||
Android::Insert => (Ruffle::Insert, None), | ||
Android::F1 => (Ruffle::F1, None), | ||
Android::F2 => (Ruffle::F2, None), | ||
Android::F3 => (Ruffle::F3, None), | ||
Android::F4 => (Ruffle::F4, None), | ||
Android::F5 => (Ruffle::F5, None), | ||
Android::F6 => (Ruffle::F6, None), | ||
Android::F7 => (Ruffle::F7, None), | ||
Android::F8 => (Ruffle::F8, None), | ||
Android::F9 => (Ruffle::F9, None), | ||
Android::F10 => (Ruffle::F10, None), | ||
Android::F11 => (Ruffle::F11, None), | ||
Android::F12 => (Ruffle::F12, None), | ||
Android::Numpad0 => (Ruffle::Numpad0, Some('0')), | ||
Android::Numpad1 => (Ruffle::Numpad1, Some('1')), | ||
Android::Numpad2 => (Ruffle::Numpad2, Some('2')), | ||
Android::Numpad3 => (Ruffle::Numpad3, Some('3')), | ||
Android::Numpad4 => (Ruffle::Numpad4, Some('4')), | ||
Android::Numpad5 => (Ruffle::Numpad5, Some('5')), | ||
Android::Numpad6 => (Ruffle::Numpad6, Some('6')), | ||
Android::Numpad7 => (Ruffle::Numpad7, Some('7')), | ||
Android::Numpad8 => (Ruffle::Numpad8, Some('8')), | ||
Android::Numpad9 => (Ruffle::Numpad9, Some('9')), | ||
Android::NumpadDivide => (Ruffle::NumpadSlash, Some('/')), | ||
Android::NumpadSubtract => (Ruffle::NumpadMinus, Some('-')), | ||
Android::NumpadDot => (Ruffle::NumpadPeriod, Some('.')), | ||
Android::NumpadEnter => (Ruffle::NumpadEnter, Some(13 as char)), | ||
_ => return None, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters