package net.bible.android.control.page.window; import android.support.annotation.NonNull; import android.view.Menu; import android.view.MenuItem; import net.bible.android.TestBibleApplication; import net.bible.android.activity.BuildConfig; import net.bible.android.activity.R; import net.bible.android.control.event.EventManager; import net.bible.android.control.event.window.NumberOfWindowsChangedEvent; import net.bible.android.control.page.CurrentBiblePage; import net.bible.android.control.page.CurrentPageManager; import net.bible.android.control.page.window.WindowLayout.WindowState; import net.bible.service.sword.SwordDocumentFacade; import net.bible.test.PassageTestData; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.Books; import org.crosswire.jsword.passage.Key; import org.crosswire.jsword.passage.Verse; import org.crosswire.jsword.versification.BibleBook; import org.crosswire.jsword.versification.system.Versifications; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.fakes.RoboMenu; import javax.inject.Provider; import robolectric.MyRobolectricTestRunner; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.isA; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @RunWith(MyRobolectricTestRunner.class) @Config(constants = BuildConfig.class, application = TestBibleApplication.class) public class WindowControlTest { private static final Book BOOK_KJV = Books.installed().getBook("KJV"); private static final Verse PS_139_3 = new Verse(Versifications.instance().getVersification("KJV"), BibleBook.PS, 139, 3); private EventManager eventManager; private WindowRepository windowRepository; private WindowControl windowControl; @Before public void setUp() throws Exception { eventManager = mock(EventManager.class); Provider<CurrentPageManager> mockCurrentPageManagerProvider = new Provider<CurrentPageManager>() { @Override public CurrentPageManager get() { return new CurrentPageManager(null, new SwordDocumentFacade(null), null, null); } }; windowRepository = new WindowRepository(mockCurrentPageManagerProvider); windowControl = new WindowControl(windowRepository, eventManager); reset(eventManager); } @Test public void testGetActiveWindow() throws Exception { // should always be one default window that is active by default assertThat(windowControl.getActiveWindow().getScreenNo(), equalTo(1)); } @Test public void testSetActiveWindow() throws Exception { Window window1 = windowControl.getActiveWindow(); Window newWindow = windowControl.addNewWindow(); assertThat(window1, equalTo(windowControl.getActiveWindow())); windowControl.setActiveWindow(newWindow); assertThat(newWindow, equalTo(windowControl.getActiveWindow())); } @Test public void testIsCurrentActiveWindow() throws Exception { Window activeWindow = windowControl.getActiveWindow(); assertThat(windowControl.isActiveWindow(activeWindow), is(true)); } @Test public void testShowLink() throws Exception { windowControl.showLink(BOOK_KJV, PS_139_3); Window linksWindow = windowRepository.getDedicatedLinksWindow(); assertThat(linksWindow.getPageManager().getCurrentBible().getCurrentDocument(), equalTo(BOOK_KJV)); assertThat(linksWindow.getPageManager().getCurrentBible().getSingleKey(), equalTo((Key)PS_139_3)); assertThat(linksWindow.getWindowLayout().getState(), equalTo(WindowLayout.WindowState.SPLIT)); assertThat(windowRepository.isMultiWindow(), is(true)); } @Test public void testShowLinkUsingDefaultBible() throws Exception { Window window1 = windowRepository.getActiveWindow(); window1.getPageManager().setCurrentDocument(BOOK_KJV); windowControl.showLinkUsingDefaultBible(PS_139_3); Window linksWindow = windowRepository.getDedicatedLinksWindow(); assertThat(linksWindow.getPageManager().getCurrentBible().getCurrentDocument(), equalTo(BOOK_KJV)); assertThat(linksWindow.getPageManager().getCurrentBible().getSingleKey(), equalTo((Key)PS_139_3)); assertThat(linksWindow.getWindowLayout().getState(), equalTo(WindowLayout.WindowState.SPLIT)); assertThat(windowRepository.isMultiWindow(), is(true)); assertThat(windowControl.isActiveWindow(linksWindow), is(true)); windowControl.setActiveWindow(window1); window1.getPageManager().setCurrentDocument(PassageTestData.ESV); windowControl.showLinkUsingDefaultBible(PS_139_3); // since links window has not been closed the Bible should not be changed assertThat(linksWindow.getPageManager().getCurrentBible().getCurrentDocument(), equalTo(BOOK_KJV)); } @Test public void testAddNewWindow() throws Exception { Window activeWindow = windowControl.getActiveWindow(); activeWindow.getPageManager().getCurrentBible().setCurrentDocumentAndKey(PassageTestData.ESV, PassageTestData.PS_139_2); Window newWindow = windowControl.addNewWindow(); assertThat(windowRepository.getWindows(), hasItem(newWindow)); // documents should be defaulted from active window CurrentBiblePage biblePage = newWindow.getPageManager().getCurrentBible(); assertThat(biblePage.getCurrentDocument(), equalTo(PassageTestData.ESV)); assertThat(biblePage.getSingleKey().getName(), equalTo(PassageTestData.PS_139_2.getName())); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testGetMinimisedWindows() throws Exception { Window activeWindow = windowControl.getActiveWindow(); Window newWindow1 = windowControl.addNewWindow(); Window newWindow2 = windowControl.addNewWindow(); // simple state - just 1 window is minimised windowControl.minimiseWindow(newWindow2); assertThat(windowRepository.getMinimisedScreens(), contains(newWindow2)); // 1 window is minimised, but because a window is maximised no windows should be returned windowControl.maximiseWindow(activeWindow); assertThat(windowRepository.getMinimisedScreens(), containsInAnyOrder()); } @Test public void testMinimiseWindow() throws Exception { Window newWindow = windowControl.addNewWindow(); reset(eventManager); windowControl.minimiseWindow(newWindow); assertThat(windowRepository.getVisibleWindows(), not(hasItem(newWindow))); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testMinimiseOnlyWindowPrevented() throws Exception { Window onlyWindow = windowControl.getActiveWindow(); windowControl.minimiseWindow(onlyWindow); assertThat(windowRepository.getVisibleWindows(), hasItem(onlyWindow)); verifyZeroInteractions(eventManager); // test still prevented if links window is visible windowRepository.getDedicatedLinksWindow().getWindowLayout().setState(WindowState.SPLIT); windowControl.minimiseWindow(onlyWindow); assertThat(windowRepository.getVisibleWindows(), hasItem(onlyWindow)); verifyZeroInteractions(eventManager); } @Test public void testMaximiseWindow() throws Exception { Window newWindow = windowControl.addNewWindow(); windowControl.setActiveWindow(newWindow); reset(eventManager); windowControl.maximiseWindow(newWindow); assertThat(windowRepository.getVisibleWindows(), hasItem(newWindow)); assertThat(windowRepository.getVisibleWindows(), hasSize(1)); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testMaximiseAndLinksWindow() throws Exception { Window activeWindow = windowControl.getActiveWindow(); windowControl.addNewWindow(); // add an extra window for good measure windowControl.showLinkUsingDefaultBible(PS_139_3); windowControl.setActiveWindow(activeWindow); assertThat(windowRepository.getVisibleWindows(), hasSize(3)); reset(eventManager); // making window active should remove links window windowControl.maximiseWindow(activeWindow); assertThat(windowRepository.getVisibleWindows(), contains(activeWindow)); // showing link should re-display links window despite window being maximised windowControl.showLinkUsingDefaultBible(PS_139_3); assertThat(windowRepository.getVisibleWindows(), contains(activeWindow, windowRepository.getDedicatedLinksWindow())); // maximise links window should be possible Window linksWindow = windowRepository.getDedicatedLinksWindow(); windowControl.maximiseWindow(linksWindow); assertThat(windowRepository.getVisibleWindows(), contains(linksWindow)); } @Test public void testCloseWindow() throws Exception { Window newWindow = windowControl.addNewWindow(); reset(eventManager); windowControl.closeWindow(newWindow); assertThat(windowRepository.getWindows(), not(hasItem(newWindow))); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testCloseOnlyWindowPrevented() throws Exception { Window onlyWindow = windowRepository.getActiveWindow(); windowControl.closeWindow(onlyWindow); assertThat(windowRepository.getWindows(), hasItem(onlyWindow)); verifyZeroInteractions(eventManager); } @Test public void testCloseWindowPreventedIfOnlyOtherIsLinks() throws Exception { windowRepository.getDedicatedLinksWindow().getWindowLayout().setState(WindowState.SPLIT); Window onlyNormalWindow = windowRepository.getActiveWindow(); windowControl.closeWindow(onlyNormalWindow); assertThat(windowRepository.getWindows(), hasItem(onlyNormalWindow)); verifyZeroInteractions(eventManager); } @Test public void testCloseActiveWindow() throws Exception { Window activeWindow = windowControl.getActiveWindow(); Window newWindow = windowControl.addNewWindow(); reset(eventManager); windowControl.closeWindow(activeWindow); assertThat(windowRepository.getActiveWindow(), equalTo(newWindow)); } @Test public void testRestoreWindow() throws Exception { Window activeWindow = windowControl.getActiveWindow(); Window newWindow = windowControl.addNewWindow(); windowControl.minimiseWindow(newWindow); assertThat(windowRepository.getVisibleWindows(), contains(activeWindow)); reset(eventManager); windowControl.restoreWindow(newWindow); assertThat(windowRepository.getVisibleWindows(), containsInAnyOrder(activeWindow, newWindow)); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testOrientationChange() throws Exception { windowControl.orientationChange(); verify(eventManager, times(1)).post(argThat(isA(NumberOfWindowsChangedEvent.class))); } @Test public void testIsMultiWindow() throws Exception { assertThat(windowControl.isMultiWindow(), equalTo(false)); Window newWindow = windowControl.addNewWindow(); assertThat(windowControl.isMultiWindow(), equalTo(true)); windowControl.closeWindow(newWindow); assertThat(windowControl.isMultiWindow(), equalTo(false)); } @Test public void testUpdateSynchronisedMenuItem() { Menu menu = createWindowsMenu(); windowControl.updateOptionsMenu(menu); MenuItem synchronisedMenuItem = menu.findItem(R.id.windowSynchronise); assertThat(synchronisedMenuItem.isChecked(), equalTo(true)); windowControl.getActiveWindow().setSynchronised(false); windowControl.updateOptionsMenu(menu); assertThat(synchronisedMenuItem.isChecked(), equalTo(false)); } @Test public void testDisableMenuItemsIfLinksWindowActive() { Window normalWindow = windowControl.getActiveWindow(); windowControl.addNewWindow(); Menu menu = createWindowsMenu(); windowControl.updateOptionsMenu(menu); MenuItem synchronisedMenuItem = menu.findItem(R.id.windowSynchronise); MenuItem moveFirstMenuItem = menu.findItem(R.id.windowMoveFirst); MenuItem minimiseMenuItem = menu.findItem(R.id.windowMinimise); assertThat(synchronisedMenuItem.isEnabled(), equalTo(true)); Window linksWindow = windowRepository.getDedicatedLinksWindow(); windowControl.setActiveWindow(linksWindow); windowControl.updateOptionsMenu(menu); assertThat(synchronisedMenuItem.isEnabled(), equalTo(false)); assertThat(moveFirstMenuItem.isEnabled(), equalTo(false)); assertThat(minimiseMenuItem.isEnabled(), equalTo(false)); // check menu items are re-enabled when a normal window becomes active windowControl.setActiveWindow(normalWindow); windowControl.updateOptionsMenu(menu); assertThat(synchronisedMenuItem.isEnabled(), equalTo(true)); } @Test public void testDisableMenuItemsIfOnlyOneWindow() { // the links window should not allow minimise or close to work if only 1 other window windowRepository.getDedicatedLinksWindow().getWindowLayout().setState(WindowState.SPLIT); Menu menu = createWindowsMenu(); windowControl.updateOptionsMenu(menu); MenuItem minimiseMenuItem = menu.findItem(R.id.windowMinimise); MenuItem closeMenuItem = menu.findItem(R.id.windowClose); assertThat(minimiseMenuItem.isEnabled(), equalTo(false)); assertThat(closeMenuItem.isEnabled(), equalTo(false)); } @Test public void testCannotMoveFirstWindowFirst() { windowControl.addNewWindow(); Menu menu = createWindowsMenu(); windowControl.updateOptionsMenu(menu); MenuItem moveFirstMenuItem = menu.findItem(R.id.windowMoveFirst); assertThat(moveFirstMenuItem.isEnabled(), equalTo(false)); } @NonNull public Menu createWindowsMenu() { Menu menu = new RoboMenu(RuntimeEnvironment.application); menu.add(0, R.id.windowSynchronise, 0, "Synchronise"); menu.add(0, R.id.windowMoveFirst, 0, "First"); menu.add(0, R.id.windowMinimise, 0, "Minimise"); menu.add(0, R.id.windowMaximise, 0, "Maximise"); menu.add(0, R.id.windowClose, 0, "Close"); return menu; } }