/***************************************************************************
* Copyright 2006-2016 by Christian Ihle *
* contact@kouchat.net *
* *
* This file is part of KouChat. *
* *
* KouChat is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* KouChat is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with KouChat. *
* If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
package net.usikkert.kouchat.android.controller;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.File;
import java.net.URL;
import java.util.Locale;
import net.usikkert.kouchat.android.R;
import net.usikkert.kouchat.android.chatwindow.AndroidUserInterface;
import net.usikkert.kouchat.android.filetransfer.AndroidFileUtils;
import net.usikkert.kouchat.android.service.ChatService;
import net.usikkert.kouchat.android.service.ChatServiceBinder;
import net.usikkert.kouchat.misc.SortedUserList;
import net.usikkert.kouchat.misc.User;
import net.usikkert.kouchat.util.TestUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowIntent;
import org.robolectric.util.ActivityController;
import android.content.Intent;
import android.net.Uri;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
/**
* Test of {@link SendFileController}.
*
* @author Christian Ihle
*/
@RunWith(RobolectricTestRunner.class)
public class SendFileControllerTest {
private SendFileController controller;
private ActivityController<SendFileController> activityController;
private AndroidUserInterface ui;
private SortedUserList userList;
private AndroidFileUtils androidFileUtils;
@Before
public void setUp() {
Locale.setDefault(Locale.US); // To avoid issues with "." and "," in asserts containing file sizes
activityController = Robolectric.buildActivity(SendFileController.class);
controller = activityController.get();
androidFileUtils = TestUtils.setFieldValueWithMock(controller, "androidFileUtils", AndroidFileUtils.class);
ui = mock(AndroidUserInterface.class);
final ChatServiceBinder serviceBinder = mock(ChatServiceBinder.class);
Robolectric.getShadowApplication().setComponentNameAndServiceForBindService(null, serviceBinder);
final User me = new User("Me", 123);
me.setMe(true);
userList = new SortedUserList();
userList.add(me);
when(ui.getUserList()).thenReturn(userList);
when(ui.getMe()).thenReturn(me);
when(serviceBinder.getAndroidUserInterface()).thenReturn(ui);
}
@Test
public void onCreateShouldRegisterClickEventOnCancelButtonToFinishActivity() {
activityController.create();
assertFalse(controller.isFinishing());
final Button cancelButton = (Button) controller.findViewById(R.id.sendFileCancelButton);
cancelButton.performClick();
assertTrue(controller.isFinishing());
}
@Test
public void onCreateWithoutFileShouldHideInfoLine2AndNotStartService() {
activityController.create();
final TextView line1TextView = (TextView) controller.findViewById(R.id.sendFileLine1TextView);
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
assertEquals("Unable to locate the file to send.", line1TextView.getText());
assertEquals("", line2TextView.getText());
assertEquals(View.GONE, line2TextView.getVisibility());
assertNull(Robolectric.getShadowApplication().getNextStartedService());
}
@Test
public void onCreateWithUnknownFileShouldSetPathInLine2AndNotStartService() {
setupControllerWithUnknownFile();
activityController.create();
final TextView line1TextView = (TextView) controller.findViewById(R.id.sendFileLine1TextView);
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
assertEquals("Unable to locate the file to send.", line1TextView.getText());
assertEquals("ftp:google.com#search", line2TextView.getText());
assertEquals(View.VISIBLE, line2TextView.getVisibility());
assertNull(Robolectric.getShadowApplication().getNextStartedService());
}
@Test
public void onCreateWithRecognizedFileAndNoUsersShouldSetFileDetailsAndNoUsersInfo() {
setupControllerIntentWithValidFile();
activityController.create();
final TextView line1TextView = (TextView) controller.findViewById(R.id.sendFileLine1TextView);
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
assertEquals("File name: kouchat-1600x1600.png \\nFile size: 67.16KB", line1TextView.getText());
assertEquals("-- No connected users.", line2TextView.getText());
assertEquals(View.VISIBLE, line2TextView.getVisibility());
}
@Test
public void onCreateWithRecognizedFileAndUsersShouldSetFileDetailsAndSelectUserInfo() {
userList.add(new User("SomeOne", 124));
setupControllerIntentWithValidFile();
activityController.create();
final TextView line1TextView = (TextView) controller.findViewById(R.id.sendFileLine1TextView);
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
assertEquals("File name: kouchat-1600x1600.png \\nFile size: 67.16KB", line1TextView.getText());
assertEquals("Please select the user to send the file to.", line2TextView.getText());
assertEquals(View.VISIBLE, line2TextView.getVisibility());
}
@Test
public void onCreateWithRecognizedFileShouldStartService() {
setupControllerIntentWithValidFile();
activityController.create();
final ShadowIntent startedServiceIntent =
Robolectric.shadowOf(Robolectric.getShadowApplication().getNextStartedService());
assertEquals(ChatService.class, startedServiceIntent.getIntentClass());
}
@Test
public void onCreateWithRecognizedFileShouldRegisterControllerAsUserListListener() {
assertEquals(0, userList.getListeners().size());
setupControllerIntentWithValidFile();
activityController.create();
assertEquals(1, userList.getListeners().size());
assertTrue(userList.getListeners().contains(controller));
}
@Test
public void onCreateWithRecognizedFileShouldRegisterOnClickListenerThatSendsTheFileAndFinishes() {
userList.add(new User("One", 124));
final User two = new User("Two", 125);
userList.add(two);
final File file = setupControllerIntentWithValidFile();
activityController.create();
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final AdapterView.OnItemClickListener listener = userListView.getOnItemClickListener();
listener.onItemClick(userListView, null, 1, 100);
verify(ui).sendFile(two, file);
assertTrue(controller.isFinishing());
}
@Test
public void onDestroyShouldUnregister() {
userList.add(new User("SomeOne", 124));
setupControllerIntentWithValidFile();
activityController.create();
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final ListAdapter adapter = userListView.getAdapter();
assertEquals(0, Robolectric.getShadowApplication().getUnboundServiceConnections().size());
assertEquals(1, userList.getListeners().size());
assertEquals(1, adapter.getCount());
activityController.destroy();
assertEquals(1, Robolectric.getShadowApplication().getUnboundServiceConnections().size());
assertEquals(0, userList.getListeners().size());
assertEquals(-1, adapter.getCount()); // -1 because it's empty and expects "me" to be present.
}
@Test
public void onDestroyShouldSetAllFieldsToNull() {
setupControllerIntentWithValidFile();
activityController.create();
assertTrue(TestUtils.allFieldsHaveValue(controller));
activityController.destroy();
assertTrue(TestUtils.allFieldsAreNull(controller));
}
@Test
public void onDestroyShouldNotFailIfServiceHasNotBeenBound() {
activityController.create();
assertTrue(TestUtils.fieldValueIsNull(controller, "userList"));
activityController.destroy();
assertEquals(0, Robolectric.getShadowApplication().getUnboundServiceConnections().size());
}
@Test
public void userAddedShouldAddUserToAdapterAndUpdateLine2() {
setupControllerIntentWithValidFile();
activityController.create();
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final ListAdapter adapter = userListView.getAdapter();
assertEquals("-- No connected users.", line2TextView.getText());
assertEquals(0, adapter.getCount());
controller.userAdded(0, new User("Lilly", 125)); // Position is not used
assertEquals("Please select the user to send the file to.", line2TextView.getText());
assertEquals(1, adapter.getCount());
}
@Test
public void userAddedShouldSortUsers() {
final User xing = new User("Xing", 127);
final User cecilia = new User("Cecilia", 128);
userList.add(xing);
userList.add(cecilia);
setupControllerIntentWithValidFile();
activityController.create();
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final ListAdapter adapter = userListView.getAdapter();
assertEquals(2, adapter.getCount());
assertSame(cecilia, adapter.getItem(0));
assertSame(xing, adapter.getItem(1));
final User penny = new User("Penny", 126);
controller.userAdded(0, penny);
assertEquals(3, adapter.getCount());
assertSame(cecilia, adapter.getItem(0));
assertSame(penny, adapter.getItem(1));
assertSame(xing, adapter.getItem(2));
}
@Test
public void userRemovedShouldRemoveUserFromAdapterAndUpdateLine2() {
final User lilly = new User("Lilly", 125);
userList.add(lilly);
setupControllerIntentWithValidFile();
activityController.create();
final TextView line2TextView = (TextView) controller.findViewById(R.id.sendFileLine2TextView);
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final ListAdapter adapter = userListView.getAdapter();
assertEquals("Please select the user to send the file to.", line2TextView.getText());
assertEquals(1, adapter.getCount());
controller.userRemoved(0, lilly); // Position is not used
assertEquals("-- No connected users.", line2TextView.getText());
assertEquals(0, adapter.getCount());
}
@Test
public void userChangedShouldSortAdapter() {
final User penny = new User("Penny", 126);
final User xing = new User("Xing", 127);
final User cecilia = new User("Cecilia", 128);
userList.add(penny);
userList.add(xing);
userList.add(cecilia);
setupControllerIntentWithValidFile();
activityController.create();
final ListView userListView = (ListView) controller.findViewById(R.id.sendFileUserListView);
final ListAdapter adapter = userListView.getAdapter();
assertEquals(3, adapter.getCount());
assertSame(cecilia, adapter.getItem(0));
assertSame(penny, adapter.getItem(1));
assertSame(xing, adapter.getItem(2));
penny.setNick("Amy");
controller.userChanged(0, null); // Doesn't use any of the parameters
assertEquals(3, adapter.getCount());
assertSame(penny, adapter.getItem(0)); // Now Amy
assertSame(cecilia, adapter.getItem(1));
assertSame(xing, adapter.getItem(2));
}
private void setupControllerWithUnknownFile() {
setupControllerWithIntent(Uri.fromParts("ftp", "google.com", "search"));
}
private File setupControllerIntentWithValidFile() {
final Uri uri = Uri.parse("content://contacts/photos/253");
final URL resource = getClass().getClassLoader().getResource("kouchat-1600x1600.png");
assertNotNull("Unable to find kouchat-1600x1600.png", resource);
final File file = new File(resource.getFile());
when(androidFileUtils.getFileFromUri(uri, controller.getContentResolver())).thenReturn(file);
setupControllerWithIntent(uri);
return file;
}
private void setupControllerWithIntent(final Uri uri) {
final Intent intent = new Intent(Robolectric.application, SendFileController.class);
intent.putExtra(Intent.EXTRA_STREAM, uri);
activityController.withIntent(intent);
}
}