diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 38e4d78920bc5..2e0c0f45a960d 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -24,6 +24,7 @@ import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.media.taptotransfer.MediaTttChipController; +import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper; import com.android.systemui.people.PeopleProvider; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.unfold.SysUIUnfoldComponent; @@ -133,6 +134,7 @@ public interface SysUIComponent { getNaturalRotationUnfoldProgressProvider().ifPresent(o -> o.init()); // No init method needed, just needs to be gotten so that it's created. getMediaTttChipController(); + getMediaTttCommandLineHelper(); } /** @@ -182,6 +184,9 @@ public interface SysUIComponent { /** */ Optional getMediaTttChipController(); + /** */ + Optional getMediaTttCommandLineHelper(); + /** * Member injection into the supplied argument. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java index cf679f070c3a1..a1f8455f9ac8a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java +++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java @@ -25,6 +25,7 @@ import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHost; import com.android.systemui.media.MediaHostStatesManager; import com.android.systemui.media.taptotransfer.MediaTttChipController; +import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper; import com.android.systemui.media.taptotransfer.MediaTttFlags; import com.android.systemui.statusbar.commandline.CommandRegistry; @@ -78,11 +79,23 @@ public interface MediaModule { static Optional providesMediaTttChipController( MediaTttFlags mediaTttFlags, Context context, - CommandRegistry commandRegistry, WindowManager windowManager) { if (!mediaTttFlags.isMediaTttEnabled()) { return Optional.empty(); } - return Optional.of(new MediaTttChipController(commandRegistry, context, windowManager)); + return Optional.of(new MediaTttChipController(context, windowManager)); + } + + /** */ + @Provides + @SysUISingleton + static Optional providesMediaTttCommandLineHelper( + MediaTttFlags mediaTttFlags, + CommandRegistry commandRegistry, + MediaTttChipController mediaTttChipController) { + if (!mediaTttFlags.isMediaTttEnabled()) { + return Optional.empty(); + } + return Optional.of(new MediaTttCommandLineHelper(commandRegistry, mediaTttChipController)); } } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt index af8fc0e3c7f9a..1ec6a39347ca3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt @@ -24,13 +24,8 @@ import android.view.View import android.view.WindowManager import android.widget.LinearLayout import android.widget.TextView -import androidx.annotation.StringRes -import androidx.annotation.VisibleForTesting import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.commandline.Command -import com.android.systemui.statusbar.commandline.CommandRegistry -import java.io.PrintWriter import javax.inject.Inject /** @@ -41,14 +36,9 @@ import javax.inject.Inject */ @SysUISingleton class MediaTttChipController @Inject constructor( - commandRegistry: CommandRegistry, private val context: Context, private val windowManager: WindowManager, ) { - init { - commandRegistry.registerCommand(ADD_CHIP_COMMAND_TAG) { AddChipCommand() } - commandRegistry.registerCommand(REMOVE_CHIP_COMMAND_TAG) { RemoveChipCommand() } - } private val windowLayoutParams = WindowManager.LayoutParams().apply { width = WindowManager.LayoutParams.WRAP_CONTENT @@ -65,7 +55,8 @@ class MediaTttChipController @Inject constructor( /** The chip view currently being displayed. Null if the chip is not being displayed. */ private var chipView: LinearLayout? = null - private fun displayChip(chipType: ChipType, otherDeviceName: String) { + /** Displays the chip view for the given state. */ + fun displayChip(chipState: MediaTttChipState) { val oldChipView = chipView if (chipView == null) { chipView = LayoutInflater @@ -76,16 +67,16 @@ class MediaTttChipController @Inject constructor( // Text currentChipView.requireViewById(R.id.text).apply { - text = context.getString(chipType.chipText, otherDeviceName) + text = context.getString(chipState.chipText, chipState.otherDeviceName) } // Loading - val showLoading = chipType == ChipType.TRANSFER_INITIATED + val showLoading = chipState is TransferInitiated currentChipView.requireViewById(R.id.loading).visibility = if (showLoading) { View.VISIBLE } else { View.GONE } // Undo - val showUndo = chipType == ChipType.TRANSFER_SUCCEEDED + val showUndo = chipState is TransferSucceeded currentChipView.requireViewById(R.id.undo).visibility = if (showUndo) { View.VISIBLE } else { View.GONE } @@ -94,53 +85,10 @@ class MediaTttChipController @Inject constructor( } } - private fun removeChip() { + /** Hides the chip. */ + fun removeChip() { if (chipView == null) { return } windowManager.removeView(chipView) chipView = null } - - @VisibleForTesting - enum class ChipType( - @StringRes internal val chipText: Int - ) { - MOVE_CLOSER_TO_TRANSFER(R.string.media_move_closer_to_transfer), - TRANSFER_INITIATED(R.string.media_transfer_playing), - TRANSFER_SUCCEEDED(R.string.media_transfer_playing), - } - - inner class AddChipCommand : Command { - override fun execute(pw: PrintWriter, args: List) { - val chipTypeArg = args[1] - ChipType.values().forEach { - if (it.name == chipTypeArg) { - displayChip(it, otherDeviceName = args[0]) - return - } - } - - pw.println("Chip type must be one of " + - ChipType.values().map { it.name }.reduce { acc, s -> "$acc, $s" }) - } - - override fun help(pw: PrintWriter) { - pw.println( - "Usage: adb shell cmd statusbar $ADD_CHIP_COMMAND_TAG " - ) - } - } - - inner class RemoveChipCommand : Command { - override fun execute(pw: PrintWriter, args: List) = removeChip() - override fun help(pw: PrintWriter) { - pw.println("Usage: adb shell cmd statusbar $REMOVE_CHIP_COMMAND_TAG") - } - } - - companion object { - @VisibleForTesting - const val ADD_CHIP_COMMAND_TAG = "media-ttt-chip-add" - @VisibleForTesting - const val REMOVE_CHIP_COMMAND_TAG = "media-ttt-chip-remove" - } } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipState.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipState.kt new file mode 100644 index 0000000000000..05b9552a0a713 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipState.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.taptotransfer + +import androidx.annotation.StringRes +import com.android.systemui.R + +/** + * A class that stores all the information necessary to display the media tap-to-transfer chip in + * certain states. + * + * This is a sealed class where each subclass represents a specific chip state. Each subclass can + * contain additional information that is necessary for only that state. + */ +sealed class MediaTttChipState( + /** A string resource for the text that the chip should display. */ + @StringRes internal val chipText: Int, + /** The name of the other device involved in the transfer. */ + internal val otherDeviceName: String +) + +/** + * A state representing that the two devices are close but not close enough to initiate a transfer. + * The chip will instruct the user to move closer in order to initiate the transfer. + */ +class MoveCloserToTransfer( + otherDeviceName: String +) : MediaTttChipState(R.string.media_move_closer_to_transfer, otherDeviceName) + +/** + * A state representing that a transfer has been initiated (but not completed). + */ +class TransferInitiated( + otherDeviceName: String +) : MediaTttChipState(R.string.media_transfer_playing, otherDeviceName) + +/** + * A state representing that a transfer has been successfully completed. + */ +class TransferSucceeded( + otherDeviceName: String +) : MediaTttChipState(R.string.media_transfer_playing, otherDeviceName) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt new file mode 100644 index 0000000000000..9f05c92ff4431 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.taptotransfer + +import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.commandline.Command +import com.android.systemui.statusbar.commandline.CommandRegistry +import java.io.PrintWriter +import javax.inject.Inject + +/** + * A helper class to test the media tap-to-transfer chip via the command line. See inner classes for + * command usages. + */ +@SysUISingleton +class MediaTttCommandLineHelper @Inject constructor( + commandRegistry: CommandRegistry, + private val mediaTttChipController: MediaTttChipController +) { + init { + commandRegistry.registerCommand(ADD_CHIP_COMMAND_TAG) { AddChipCommand() } + commandRegistry.registerCommand(REMOVE_CHIP_COMMAND_TAG) { RemoveChipCommand() } + } + + inner class AddChipCommand : Command { + override fun execute(pw: PrintWriter, args: List) { + val otherDeviceName = args[0] + when (args[1]) { + MOVE_CLOSER_TO_TRANSFER_COMMAND_NAME -> { + mediaTttChipController.displayChip(MoveCloserToTransfer(otherDeviceName)) + } + TRANSFER_INITIATED_COMMAND_NAME -> { + mediaTttChipController.displayChip(TransferInitiated(otherDeviceName)) + } + TRANSFER_SUCCEEDED_COMMAND_NAME -> { + mediaTttChipController.displayChip(TransferSucceeded(otherDeviceName)) + } + else -> { + pw.println("Chip type must be one of " + + "$MOVE_CLOSER_TO_TRANSFER_COMMAND_NAME, " + + "$TRANSFER_INITIATED_COMMAND_NAME, " + + TRANSFER_SUCCEEDED_COMMAND_NAME + ) + } + } + } + + override fun help(pw: PrintWriter) { + pw.println( + "Usage: adb shell cmd statusbar $ADD_CHIP_COMMAND_TAG " + ) + } + } + + inner class RemoveChipCommand : Command { + override fun execute(pw: PrintWriter, args: List) { + mediaTttChipController.removeChip() + } + override fun help(pw: PrintWriter) { + pw.println("Usage: adb shell cmd statusbar $REMOVE_CHIP_COMMAND_TAG") + } + } +} + +@VisibleForTesting +const val ADD_CHIP_COMMAND_TAG = "media-ttt-chip-add" +@VisibleForTesting +const val REMOVE_CHIP_COMMAND_TAG = "media-ttt-chip-remove" +@VisibleForTesting +val MOVE_CLOSER_TO_TRANSFER_COMMAND_NAME = MoveCloserToTransfer::class.simpleName!! +@VisibleForTesting +val TRANSFER_INITIATED_COMMAND_NAME = TransferInitiated::class.simpleName!! +@VisibleForTesting +val TRANSFER_SUCCEEDED_COMMAND_NAME = TransferSucceeded::class.simpleName!! diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt index 923f018f8bcdc..50d94dd6ca5f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt @@ -23,8 +23,6 @@ import android.widget.TextView import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase -import com.android.systemui.statusbar.commandline.Command -import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -35,83 +33,58 @@ import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import java.io.PrintWriter -import java.io.StringWriter -import java.util.concurrent.Executor @SmallTest class MediaTttChipControllerTest : SysuiTestCase() { private lateinit var mediaTttChipController: MediaTttChipController - private val inlineExecutor = Executor { command -> command.run() } - private val commandRegistry = CommandRegistry(context, inlineExecutor) - private val pw = PrintWriter(StringWriter()) - @Mock private lateinit var windowManager: WindowManager @Before fun setUp() { MockitoAnnotations.initMocks(this) - mediaTttChipController = MediaTttChipController(commandRegistry, context, windowManager) - } - - @Test(expected = IllegalStateException::class) - fun constructor_addCommmandAlreadyRegistered() { - // Since creating the chip controller should automatically register the add command, it - // should throw when registering it again. - commandRegistry.registerCommand( - MediaTttChipController.ADD_CHIP_COMMAND_TAG - ) { EmptyCommand() } - } - - @Test(expected = IllegalStateException::class) - fun constructor_removeCommmandAlreadyRegistered() { - // Since creating the chip controller should automatically register the remove command, it - // should throw when registering it again. - commandRegistry.registerCommand( - MediaTttChipController.REMOVE_CHIP_COMMAND_TAG - ) { EmptyCommand() } + mediaTttChipController = MediaTttChipController(context, windowManager) } @Test - fun addChipCommand_chipAdded() { - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + fun displayChip_chipAdded() { + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) verify(windowManager).addView(any(), any()) } @Test - fun addChipCommand_twice_chipNotAddedTwice() { - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + fun displayChip_twice_chipNotAddedTwice() { + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) reset(windowManager) - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) verify(windowManager, never()).addView(any(), any()) } @Test - fun removeChipCommand_chipRemoved() { + fun removeChip_chipRemoved() { // First, add the chip - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) // Then, remove it - commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.REMOVE_CHIP_COMMAND_TAG)) + mediaTttChipController.removeChip() verify(windowManager).removeView(any()) } @Test - fun removeChipCommand_noAdd_viewNotRemoved() { - commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.REMOVE_CHIP_COMMAND_TAG)) + fun removeChip_noAdd_viewNotRemoved() { + mediaTttChipController.removeChip() verify(windowManager, never()).removeView(any()) } @Test fun moveCloserToTransfer_chipTextContainsDeviceName_noLoadingIcon_noUndo() { - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) val chipView = getChipView() assertThat(chipView.getChipText()).contains(DEVICE_NAME) @@ -121,7 +94,7 @@ class MediaTttChipControllerTest : SysuiTestCase() { @Test fun transferInitiated_chipTextContainsDeviceName_loadingIcon_noUndo() { - commandRegistry.onShellCommand(pw, getTransferInitiatedCommand()) + mediaTttChipController.displayChip(TransferInitiated(DEVICE_NAME)) val chipView = getChipView() assertThat(chipView.getChipText()).contains(DEVICE_NAME) @@ -131,7 +104,7 @@ class MediaTttChipControllerTest : SysuiTestCase() { @Test fun transferSucceeded_chipTextContainsDeviceName_noLoadingIcon_undo() { - commandRegistry.onShellCommand(pw, getTransferSucceededCommand()) + mediaTttChipController.displayChip(TransferSucceeded(DEVICE_NAME)) val chipView = getChipView() assertThat(chipView.getChipText()).contains(DEVICE_NAME) @@ -141,57 +114,36 @@ class MediaTttChipControllerTest : SysuiTestCase() { @Test fun changeFromCloserToTransferToTransferInitiated_loadingIconAppears() { - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) - commandRegistry.onShellCommand(pw, getTransferInitiatedCommand()) + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) + mediaTttChipController.displayChip(TransferInitiated(DEVICE_NAME)) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE) } @Test fun changeFromTransferInitiatedToTransferSucceeded_loadingIconDisappears() { - commandRegistry.onShellCommand(pw, getTransferInitiatedCommand()) - commandRegistry.onShellCommand(pw, getTransferSucceededCommand()) + mediaTttChipController.displayChip(TransferInitiated(DEVICE_NAME)) + mediaTttChipController.displayChip(TransferSucceeded(DEVICE_NAME)) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE) } @Test fun changeFromTransferInitiatedToTransferSucceeded_undoButtonAppears() { - commandRegistry.onShellCommand(pw, getTransferInitiatedCommand()) - commandRegistry.onShellCommand(pw, getTransferSucceededCommand()) + mediaTttChipController.displayChip(TransferInitiated(DEVICE_NAME)) + mediaTttChipController.displayChip(TransferSucceeded(DEVICE_NAME)) assertThat(getChipView().getUndoButtonVisibility()).isEqualTo(View.VISIBLE) } @Test fun changeFromTransferSucceededToMoveCloser_undoButtonDisappears() { - commandRegistry.onShellCommand(pw, getTransferSucceededCommand()) - commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + mediaTttChipController.displayChip(TransferSucceeded(DEVICE_NAME)) + mediaTttChipController.displayChip(MoveCloserToTransfer(DEVICE_NAME)) assertThat(getChipView().getUndoButtonVisibility()).isEqualTo(View.GONE) } - private fun getMoveCloserToTransferCommand(): Array = - arrayOf( - MediaTttChipController.ADD_CHIP_COMMAND_TAG, - DEVICE_NAME, - MediaTttChipController.ChipType.MOVE_CLOSER_TO_TRANSFER.name - ) - - private fun getTransferInitiatedCommand(): Array = - arrayOf( - MediaTttChipController.ADD_CHIP_COMMAND_TAG, - DEVICE_NAME, - MediaTttChipController.ChipType.TRANSFER_INITIATED.name - ) - - private fun getTransferSucceededCommand(): Array = - arrayOf( - MediaTttChipController.ADD_CHIP_COMMAND_TAG, - DEVICE_NAME, - MediaTttChipController.ChipType.TRANSFER_SUCCEEDED.name - ) - private fun LinearLayout.getChipText(): String = (this.requireViewById(R.id.text)).text as String @@ -206,14 +158,6 @@ class MediaTttChipControllerTest : SysuiTestCase() { verify(windowManager).addView(viewCaptor.capture(), any()) return viewCaptor.value as LinearLayout } - - class EmptyCommand : Command { - override fun execute(pw: PrintWriter, args: List) { - } - - override fun help(pw: PrintWriter) { - } - } } private const val DEVICE_NAME = "My Tablet" diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt new file mode 100644 index 0000000000000..4b85fa9fb75cf --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.taptotransfer + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.commandline.Command +import com.android.systemui.statusbar.commandline.CommandRegistry +import com.android.systemui.util.mockito.any +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations +import java.io.PrintWriter +import java.io.StringWriter +import java.util.concurrent.Executor + +@SmallTest +class MediaTttCommandLineHelperTest : SysuiTestCase() { + + private val inlineExecutor = Executor { command -> command.run() } + private val commandRegistry = CommandRegistry(context, inlineExecutor) + private val pw = PrintWriter(StringWriter()) + + private lateinit var mediaTttCommandLineHelper: MediaTttCommandLineHelper + + @Mock + private lateinit var mediaTttChipController: MediaTttChipController + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + mediaTttCommandLineHelper = + MediaTttCommandLineHelper(commandRegistry, mediaTttChipController) + } + + @Test(expected = IllegalStateException::class) + fun constructor_addCommandAlreadyRegistered() { + // Since creating the chip controller should automatically register the add command, it + // should throw when registering it again. + commandRegistry.registerCommand( + ADD_CHIP_COMMAND_TAG + ) { EmptyCommand() } + } + + @Test(expected = IllegalStateException::class) + fun constructor_removeCommandAlreadyRegistered() { + // Since creating the chip controller should automatically register the remove command, it + // should throw when registering it again. + commandRegistry.registerCommand( + REMOVE_CHIP_COMMAND_TAG + ) { EmptyCommand() } + } + + @Test + fun moveCloserToTransfer_chipDisplayWithCorrectState() { + commandRegistry.onShellCommand(pw, getMoveCloserToTransferCommand()) + + verify(mediaTttChipController).displayChip(any(MoveCloserToTransfer::class.java)) + } + + @Test + fun transferInitiated_chipDisplayWithCorrectState() { + commandRegistry.onShellCommand(pw, getTransferInitiatedCommand()) + + verify(mediaTttChipController).displayChip(any(TransferInitiated::class.java)) + } + + @Test + fun transferSucceeded_chipDisplayWithCorrectState() { + commandRegistry.onShellCommand(pw, getTransferSucceededCommand()) + + verify(mediaTttChipController).displayChip(any(TransferSucceeded::class.java)) + } + + @Test + fun removeCommand_chipRemoved() { + commandRegistry.onShellCommand(pw, arrayOf(REMOVE_CHIP_COMMAND_TAG)) + + verify(mediaTttChipController).removeChip() + } + + private fun getMoveCloserToTransferCommand(): Array = + arrayOf( + ADD_CHIP_COMMAND_TAG, + DEVICE_NAME, + MOVE_CLOSER_TO_TRANSFER_COMMAND_NAME + ) + + private fun getTransferInitiatedCommand(): Array = + arrayOf( + ADD_CHIP_COMMAND_TAG, + DEVICE_NAME, + TRANSFER_INITIATED_COMMAND_NAME + ) + + private fun getTransferSucceededCommand(): Array = + arrayOf( + ADD_CHIP_COMMAND_TAG, + DEVICE_NAME, + TRANSFER_SUCCEEDED_COMMAND_NAME + ) + + class EmptyCommand : Command { + override fun execute(pw: PrintWriter, args: List) { + } + + override fun help(pw: PrintWriter) { + } + } +} + +private const val DEVICE_NAME = "My Tablet"