/* * WebOSTVServiceTest * Connect SDK * * Copyright (c) 2015 LG Electronics. * Created by Oleksii Frolov on 27 May 2015 * * 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.connectsdk.service; import com.connectsdk.core.ChannelInfo; import com.connectsdk.core.MediaInfo; import com.connectsdk.core.SubtitleInfo; import com.connectsdk.device.ConnectableDevice; import com.connectsdk.discovery.DiscoveryManager; import com.connectsdk.service.capability.Launcher; import com.connectsdk.service.capability.MediaPlayer; import com.connectsdk.service.capability.ToastControl; import com.connectsdk.service.capability.listeners.ResponseListener; import com.connectsdk.service.command.NotSupportedServiceCommandError; import com.connectsdk.service.command.ServiceCommand; import com.connectsdk.service.command.ServiceCommandError; import com.connectsdk.service.config.ServiceConfig; import com.connectsdk.service.config.ServiceDescription; import com.connectsdk.service.sessions.LaunchSession; import com.connectsdk.service.sessions.WebOSWebAppSession; import com.connectsdk.service.webos.WebOSTVServiceSocketClient; import junit.framework.Assert; import org.json.JSONException; import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @RunWith(RobolectricTestRunner.class) @Config(manifest=Config.NONE) public class WebOSTVServiceTest { private WebOSTVService service; private ServiceDescription serviceDescription; private WebOSTVServiceSocketClient socket; @Before public void setUp() { serviceDescription = Mockito.mock(ServiceDescription.class); Map<String, List<String>> headers = new HashMap<String, List<String>>(); Mockito.when(serviceDescription.getVersion()).thenReturn("5.0.0"); Mockito.when(serviceDescription.getResponseHeaders()).thenReturn(headers); service = new WebOSTVService(serviceDescription, Mockito.mock(ServiceConfig.class)); this.socket = Mockito.mock(WebOSTVServiceSocketClient.class); service.socket = this.socket; Mockito.when(socket.isConnected()).thenReturn(Boolean.TRUE); } @After public void tearDown() { DiscoveryManager.getInstance().getAllDevices().clear(); } @Test public void testCapabilitiesShouldContainToastControlWhenPairingOn() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.ON); service.updateCapabilities(); Assert.assertTrue(service.hasCapabilities(ToastControl.Capabilities)); } @Test public void testCapabilitiesShouldNotContainToastControlWhenPairingOff() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.OFF); service.updateCapabilities(); Assert.assertFalse(service.hasCapabilities(ToastControl.Capabilities)); } @Test public void testCapabilitiesShouldContainSubtitlesForWebOsWithWebAppSupport() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.OFF); setWebOSVersion("5.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldContainOnlySrtSubtitlesForWebOsWithDLNA() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.OFF); injectDLNAService(); setWebOSVersion("4.0.0"); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldNotContainSubtitlesForWebOsV4() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.OFF); setWebOSVersion("4.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldContainSubtitlesForWebOsWithWebAppSupportAndPairingOn() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.ON); setWebOSVersion("5.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldContainOnlySrtSubtitlesForWebOsWithDLNAAndPairingOn() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.ON); injectDLNAService(); setWebOSVersion("4.0.0"); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldNotContainSubtitlesForWebOsV4AndPairingOn() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.ON); setWebOSVersion("4.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldContainSubtitlesForWebOsWithWebAppSupportAndDLNA() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.OFF); injectDLNAService(); setWebOSVersion("5.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testCapabilitiesShouldContainSubtitlesForWebOsWithWebAppSupportAndDLNAPairingOn() { DiscoveryManager.getInstance().setPairingLevel(DiscoveryManager.PairingLevel.ON); injectDLNAService(); setWebOSVersion("5.0.0"); Assert.assertFalse(service.hasCapabilities(MediaPlayer.Subtitle_SRT)); Assert.assertTrue(service.hasCapabilities(MediaPlayer.Subtitle_WebVTT)); } @Test public void testJumpToTrack() { ResponseListener<Object> listener = Mockito.mock(ResponseListener.class); service.jumpToTrack(1, listener); Mockito.verify(listener).onError(Mockito.isA(NotSupportedServiceCommandError.class)); } @Test public void testNext() { ResponseListener<Object> listener = Mockito.mock(ResponseListener.class); service.next(listener); Mockito.verify(listener).onError(Mockito.isA(NotSupportedServiceCommandError.class)); } @Test public void testPrevious() { ResponseListener<Object> listener = Mockito.mock(ResponseListener.class); service.previous(listener); Mockito.verify(listener).onError(Mockito.isA(NotSupportedServiceCommandError.class)); } @Test public void testLaunchInputPickerForOldTV() throws JSONException { Launcher.AppLaunchListener listener = Mockito.mock(Launcher.AppLaunchListener.class); service.launchInputPicker(listener); ArgumentCaptor<ServiceCommand> argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket).sendCommand(argCommand.capture()); ServiceCommand command = argCommand.getValue(); command.getResponseListener().onSuccess(new JSONObject()); Mockito.verify(listener).onSuccess(Mockito.any(LaunchSession.class)); JSONObject payload = (JSONObject)command.getPayload(); Assert.assertEquals("com.webos.app.inputpicker", payload.getString("id")); } @Test public void testLaunchInputPickerForNewTV() throws JSONException { Launcher.AppLaunchListener listener = Mockito.mock(Launcher.AppLaunchListener.class); service.launchInputPicker(listener); ArgumentCaptor<ServiceCommand> argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket).sendCommand(argCommand.capture()); ServiceCommand command = argCommand.getValue(); command.getResponseListener().onError(new ServiceCommandError()); argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket, Mockito.times(2)).sendCommand(argCommand.capture()); command = argCommand.getValue(); command.getResponseListener().onSuccess(new JSONObject()); Mockito.verify(listener).onSuccess(Mockito.any(LaunchSession.class)); JSONObject payload = (JSONObject)command.getPayload(); Assert.assertEquals("com.webos.app.inputmgr", payload.getString("id")); } @Test public void testLaunchInputPickerForNewTVFailure() throws JSONException { Launcher.AppLaunchListener listener = Mockito.mock(Launcher.AppLaunchListener.class); service.launchInputPicker(listener); ArgumentCaptor<ServiceCommand> argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket).sendCommand(argCommand.capture()); ServiceCommand command = argCommand.getValue(); command.getResponseListener().onError(new ServiceCommandError()); argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket, Mockito.times(2)).sendCommand(argCommand.capture()); command = argCommand.getValue(); command.getResponseListener().onError(new ServiceCommandError()); Mockito.verify(listener).onError(Mockito.any(ServiceCommandError.class)); } @Test public void testPlayMediaDeprecatedWithRequiredParametersOnTheLatestWebOS() { MediaPlayer.LaunchListener listener = Mockito.mock(MediaPlayer.LaunchListener.class); WebOSWebAppSession webAppSession = Mockito.mock(WebOSWebAppSession.class); service.mWebAppSessions.put("MediaPlayer", webAppSession); MediaInfo mediaInfo = new MediaInfo.Builder("url", "mimetype").build(); boolean shouldLoop = true; service.playMedia(mediaInfo.getUrl(), mediaInfo.getMimeType(), null, null, null, shouldLoop, listener); verifyPlayMediaOnTheLatestWebOS(mediaInfo, shouldLoop, listener, webAppSession); } @Test public void testPlayMediaDeprecatedWithAllParametersOnTheLatestWebOS() { MediaPlayer.LaunchListener listener = Mockito.mock(MediaPlayer.LaunchListener.class); WebOSWebAppSession webAppSession = Mockito.mock(WebOSWebAppSession.class); service.mWebAppSessions.put("MediaPlayer", webAppSession); MediaInfo mediaInfo = new MediaInfo.Builder("url", "mimetype") .setTitle("title") .setDescription("description") .setIcon("icon") .build(); boolean shouldLoop = true; service.playMedia(mediaInfo.getUrl(), mediaInfo.getMimeType(), mediaInfo.getTitle(), mediaInfo.getDescription(), mediaInfo.getImages().get(0).getUrl(), shouldLoop, listener); verifyPlayMediaOnTheLatestWebOS(mediaInfo, shouldLoop, listener, webAppSession); } @Test public void testPlayMediaWithRequiredParametersOnTheLatestWebOS() { MediaInfo mediaInfo = createBasicMediaInfo(); callAndVerifyPlayMediaOnTheLatestWebOS(mediaInfo, false); } @Test public void testPlayMediaWithSubtitlesOnTheLatestWebOS() { MediaInfo mediaInfo = createMediaInfoWithSubtitles(); callAndVerifyPlayMediaOnTheLatestWebOS(mediaInfo, true); } @Test public void testPlayMediaWithRequiredParametersOnTheWebOSV4AndDlna() { MediaInfo mediaInfo = createBasicMediaInfo(); verifyPlayMediaOnTheWebOSV4(mediaInfo, false); } @Test public void testPlayMediaWithSubtitlesOnTheWebOSV4AndDlna() { MediaInfo mediaInfo = createMediaInfoWithSubtitles(); verifyPlayMediaOnTheWebOSV4(mediaInfo, false); } @Test public void testPlayMediaWithRequiredParametersOnTheWebOSV4WithoutDlna() throws JSONException { MediaInfo mediaInfo = createMediaInfoWithSubtitles(); verifyPlayMediaOnTheWebOSV4WithoutDlna(mediaInfo, false); } @Test public void testSetChannelWithIdArgument() throws JSONException { ChannelInfo channelInfo = new ChannelInfo(); channelInfo.setId("id"); JSONObject payload = verifySetChannel(channelInfo); Assert.assertEquals("id", payload.getString("channelId")); Assert.assertFalse(payload.has("channelNumber")); } @Test public void testSetChannelWithNumberArgument() throws JSONException { ChannelInfo channelInfo = new ChannelInfo(); channelInfo.setNumber("number"); JSONObject payload = verifySetChannel(channelInfo); Assert.assertEquals("number", payload.getString("channelNumber")); Assert.assertFalse(payload.has("channelId")); } @Test public void testSetChannelWithIdAndNumberArguments() throws JSONException { ChannelInfo channelInfo = new ChannelInfo(); channelInfo.setNumber("number"); channelInfo.setId("id"); JSONObject payload = verifySetChannel(channelInfo); Assert.assertEquals("number", payload.getString("channelNumber")); Assert.assertEquals("id", payload.getString("channelId")); } @Test public void testSetChannelWithEmptyArguments() throws JSONException { ChannelInfo channelInfo = new ChannelInfo(); JSONObject payload = verifySetChannel(channelInfo); Assert.assertEquals(0, payload.length()); } @Test(expected = NullPointerException.class) public void testSetChannelWithNullChannelInfo() throws JSONException { JSONObject payload = verifySetChannel(null); Assert.assertEquals(0, payload.length()); } private JSONObject verifySetChannel(ChannelInfo channelInfo) { ResponseListener<Object> response = Mockito.mock(ResponseListener.class); ArgumentCaptor<ServiceCommand> argCommand = ArgumentCaptor.forClass(ServiceCommand.class); service.setChannel(channelInfo, response); Mockito.verify(socket).sendCommand(argCommand.capture()); ServiceCommand command = argCommand.getValue(); JSONObject payload = (JSONObject) command.getPayload(); Assert.assertEquals("ssap://tv/openChannel", command.getTarget()); return payload; } private MediaInfo createBasicMediaInfo() { return new MediaInfo.Builder("http://media", "video/mp4").build(); } private MediaInfo createMediaInfoWithSubtitles() { SubtitleInfo subtitle = new SubtitleInfo.Builder("http://subtitle") .build(); return new MediaInfo.Builder("http://media", "video/mp4") .setTitle("title") .setDescription("description") .setIcon("icon") .setSubtitleInfo(subtitle) .build(); } private void verifyPlayMediaOnTheWebOSV4WithoutDlna(MediaInfo mediaInfo, boolean shouldLoop) throws JSONException { Mockito.when(serviceDescription.getVersion()).thenReturn("4.0.0"); MediaPlayer.LaunchListener listener = Mockito.mock(MediaPlayer.LaunchListener.class); service.playMedia(mediaInfo, shouldLoop, listener); ArgumentCaptor<ServiceCommand> argCommand = ArgumentCaptor.forClass(ServiceCommand.class); Mockito.verify(socket).sendCommand(argCommand.capture()); ServiceCommand command = argCommand.getValue(); JSONObject payload = (JSONObject) command.getPayload(); Assert.assertEquals("ssap://media.viewer/open", command.getTarget()); Assert.assertEquals(mediaInfo.getUrl(), payload.getString("target")); Assert.assertEquals(mediaInfo.getTitle(), payload.getString("title")); Assert.assertEquals(mediaInfo.getDescription(), payload.getString("description")); Assert.assertEquals(mediaInfo.getMimeType(), payload.getString("mimeType")); Assert.assertEquals(shouldLoop, payload.getBoolean("loop")); Assert.assertEquals(mediaInfo.getImages().get(0).getUrl(), payload.getString("iconSrc")); } private void verifyPlayMediaOnTheWebOSV4(MediaInfo mediaInfo, boolean shouldLoop) { Mockito.when(serviceDescription.getVersion()).thenReturn("4.0.0"); MediaPlayer.LaunchListener listener = Mockito.mock(MediaPlayer.LaunchListener.class); DLNAService dlnaService = injectDLNAService(); MediaPlayer mediaPlayer = Mockito.mock(MediaPlayer.class); Mockito.when(dlnaService.getAPI(MediaPlayer.class)).thenReturn(mediaPlayer); service.playMedia(mediaInfo, shouldLoop, listener); ArgumentCaptor<MediaInfo> argMediaInfo = ArgumentCaptor.forClass(MediaInfo.class); ArgumentCaptor<Boolean> argShouldLoop = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(mediaPlayer).playMedia(argMediaInfo.capture(), argShouldLoop.capture(), Mockito.same(listener)); MediaInfo capturedMediaInfo = argMediaInfo.getValue(); Assert.assertEquals(mediaInfo.getDescription(), capturedMediaInfo.getDescription()); Assert.assertEquals(mediaInfo.getMimeType(), capturedMediaInfo.getMimeType()); Assert.assertEquals(mediaInfo.getTitle(), capturedMediaInfo.getTitle()); Assert.assertEquals(mediaInfo.getUrl(), capturedMediaInfo.getUrl()); Assert.assertEquals(mediaInfo.getImages(), capturedMediaInfo.getImages()); Assert.assertEquals(mediaInfo.getSubtitleInfo(), capturedMediaInfo.getSubtitleInfo()); Assert.assertEquals(shouldLoop, argShouldLoop.getValue().booleanValue()); } private void callAndVerifyPlayMediaOnTheLatestWebOS(final MediaInfo mediaInfo, boolean shouldLoop) { MediaPlayer.LaunchListener listener = Mockito.mock(MediaPlayer.LaunchListener.class); WebOSWebAppSession webAppSession = Mockito.mock(WebOSWebAppSession.class); service.mWebAppSessions.put("MediaPlayer", webAppSession); service.playMedia(mediaInfo, shouldLoop, listener); verifyPlayMediaOnTheLatestWebOS(mediaInfo, shouldLoop, listener, webAppSession); } private void verifyPlayMediaOnTheLatestWebOS(MediaInfo mediaInfo, boolean shouldLoop, MediaPlayer.LaunchListener listener, WebOSWebAppSession webAppSession) { // should try to join to the web app ArgumentCaptor<ResponseListener> argListener = ArgumentCaptor.forClass(ResponseListener .class); Mockito.verify(webAppSession).join(argListener.capture()); // run join success ResponseListener webAppListener = argListener.getValue(); webAppListener.onSuccess(null); Robolectric.runUiThreadTasksIncludingDelayedTasks(); // should delegate playing media to the WebAppSession ArgumentCaptor<MediaInfo> argMediaInfo = ArgumentCaptor.forClass(MediaInfo.class); ArgumentCaptor<Boolean> argShouldLoop = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(webAppSession).playMedia(argMediaInfo.capture(), argShouldLoop.capture(), Mockito.same(listener)); MediaInfo capturedMediaInfo = argMediaInfo.getValue(); Assert.assertEquals(mediaInfo.getDescription(), capturedMediaInfo.getDescription()); Assert.assertEquals(mediaInfo.getMimeType(), capturedMediaInfo.getMimeType()); Assert.assertEquals(mediaInfo.getTitle(), capturedMediaInfo.getTitle()); Assert.assertEquals(mediaInfo.getUrl(), capturedMediaInfo.getUrl()); Assert.assertEquals(mediaInfo.getImages(), capturedMediaInfo.getImages()); Assert.assertEquals(mediaInfo.getSubtitleInfo(), capturedMediaInfo.getSubtitleInfo()); Assert.assertEquals(shouldLoop, argShouldLoop.getValue().booleanValue()); } private DLNAService injectDLNAService() { DLNAService dlnaService = Mockito.mock(DLNAService.class); ConnectableDevice dlnaDevice = Mockito.mock(ConnectableDevice.class); Mockito.when(dlnaDevice.getServiceByName(DLNAService.ID)).thenReturn(dlnaService); String ipAddress = "127.0.0.1"; DiscoveryManager.getInstance().getAllDevices().put(ipAddress, dlnaDevice); Mockito.when(serviceDescription.getIpAddress()).thenReturn(ipAddress); return dlnaService; } private void setWebOSVersion(String version) { Map<String, List<String>> headers = new HashMap<String, List<String>>(); headers.put("Server", Arrays.asList("server/" + version + " server")); ServiceDescription serviceDescription = new ServiceDescription(); serviceDescription.setIpAddress("127.0.0.1"); serviceDescription.setResponseHeaders(headers); service.setServiceDescription(serviceDescription); } }