/*
* 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 scratch;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderBase;
import org.junit.Test;
import scratch.filesystem.FileSystem;
import scratch.ide.Ide;
import scratch.ide.ScratchLog;
import java.util.ArrayList;
import java.util.List;
import static com.intellij.util.containers.ContainerUtil.list;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static scratch.Answer.no;
import static scratch.Answer.yes;
import static scratch.ScratchConfig.AppendType;
import static scratch.ScratchConfig.DefaultScratchMeaning.LAST_OPENED;
import static scratch.ScratchConfig.DefaultScratchMeaning.TOPMOST;
@SuppressWarnings("Duplicates")
public class MrScratchManagerTest {
private static final UserDataHolder someUserData = new UserDataHolderBase();
private final ScratchLog log = mock(ScratchLog.class);
private final Ide ide = mock(Ide.class);
private final FileSystem fileSystem = mock(FileSystem.class);
private final ScratchConfig defaultConfig = ScratchConfig.DEFAULT_CONFIG;
private MrScratchManager mrScratchManager;
@Test public void shouldLog_when_successfullyMigratedScratchesToFiles() {
mrScratchManager = scratchManagerWith(defaultConfig.needsMigration(true));
when(fileSystem.createFile(anyString(), anyString())).thenReturn(true);
List<String> scratchTexts = list("text1", "text2", "text3", "text4", "text5");
mrScratchManager.migrate(scratchTexts);
verify(fileSystem).createFile("scratch.txt", "text1");
verify(fileSystem).createFile("scratch2.txt", "text2");
verify(fileSystem).createFile("scratch3.txt", "text3");
verify(fileSystem).createFile("scratch4.txt", "text4");
verify(fileSystem).createFile("scratch5.txt", "text5");
verify(log).migratedScratchesToFiles();
}
@Test public void shouldNotMigrate_when_thereAreFilesInScratchFolder() {
mrScratchManager = scratchManagerWith(defaultConfig.needsMigration(true));
when(fileSystem.listScratchFiles()).thenReturn(list("scratch.txt"));
List<String> scratchTexts = list("text1", "text2", "text3", "text4", "text5");
mrScratchManager.migrate(scratchTexts);
verify(fileSystem).listScratchFiles();
verifyNoMoreInteractions(fileSystem);
verify(log).willNotMigrateBecauseTargetFolderIsNotEmpty();
}
@Test public void shouldSendNewConfigToIde_when_successfullyMigratedScratchesToFiles() {
mrScratchManager = scratchManagerWith(defaultConfig.needsMigration(true));
when(fileSystem.createFile(anyString(), anyString())).thenReturn(true);
List<String> scratches = list("text1", "text2", "text3", "text4", "text5");
mrScratchManager.migrate(scratches);
verify(ide).persistConfig(eq(defaultConfig
.with(list(
scratch("&scratch.txt"),
scratch("scratch&2.txt"),
scratch("scratch&3.txt"),
scratch("scratch&4.txt"),
scratch("scratch&5.txt")))
.needsMigration(false)
));
}
@Test public void shouldLog_when_failedToMigrateSomeOfTheFiles() {
mrScratchManager = scratchManagerWith(defaultConfig.needsMigration(true));
when(fileSystem.createFile(anyString(), anyString())).thenReturn(true);
when(fileSystem.createFile(eq("scratch3.txt"), anyString())).thenReturn(false);
when(fileSystem.createFile(eq("scratch4.txt"), anyString())).thenReturn(false);
List<String> scratches = list("text1", "text2", "text3", "text4", "text5");
mrScratchManager.migrate(scratches);
verify(fileSystem).createFile("scratch.txt", "text1");
verify(fileSystem).createFile("scratch2.txt", "text2");
verify(fileSystem).createFile("scratch3.txt", "text3");
verify(fileSystem).createFile("scratch4.txt", "text4");
verify(fileSystem).createFile("scratch5.txt", "text5");
verify(log).failedToMigrateScratchesToFiles(list(3, 4));
}
@Test public void shouldSendNewConfigToIde_when_failedToMigrateSomeOfTheFiles() {
mrScratchManager = scratchManagerWith(defaultConfig.needsMigration(true));
when(fileSystem.createFile(anyString(), anyString())).thenReturn(true);
when(fileSystem.createFile(eq("scratch3.txt"), anyString())).thenReturn(false);
when(fileSystem.createFile(eq("scratch4.txt"), anyString())).thenReturn(false);
List<String> scratches = list("text1", "text2", "text3", "text4", "text5");
mrScratchManager.migrate(scratches);
verify(ide).persistConfig(eq(defaultConfig
.with(list(
scratch("&scratch.txt"),
scratch("scratch&2.txt"),
scratch("scratch&5.txt")
))
.needsMigration(false)
));
}
@Test public void displayingScratchesList_when_configAndFiles_MatchExactly() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch.txt"),
scratch("scratch2.java"),
scratch("scratch3.html")
)));
when(fileSystem.listScratchFiles()).thenReturn(list("scratch.txt", "scratch2.java", "scratch3.html"));
mrScratchManager.userWantsToSeeScratchesList(someUserData);
verify(fileSystem).listScratchFiles();
verify(ide).displayScratchesListPopup(eq(list(
scratch("scratch.txt"),
scratch("scratch2.java"),
scratch("scratch3.html")
)), same(someUserData));
verifyNoMoreInteractions(fileSystem, ide);
}
@Test public void displayingScratchesList_when_configAndFiles_Match_ButHaveDifferentOrder() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch.txt"),
scratch("scratch2.java"),
scratch("scratch3.html")
)));
when(fileSystem.listScratchFiles()).thenReturn(list("scratch2.java", "scratch3.html", "scratch.txt"));
mrScratchManager.userWantsToSeeScratchesList(someUserData);
verify(fileSystem).listScratchFiles();
verify(ide).displayScratchesListPopup(eq(list(
scratch("scratch.txt"),
scratch("scratch2.java"),
scratch("scratch3.html")
)), same(someUserData));
verifyNoMoreInteractions(fileSystem, ide);
}
@Test public void displayingScratchesList_when_fileSystemHasNewFiles() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch.txt")
)));
when(fileSystem.listScratchFiles()).thenReturn(list("scratch2.java", "scratch.txt"));
mrScratchManager.userWantsToSeeScratchesList(someUserData);
verify(fileSystem).listScratchFiles();
verify(ide).persistConfig(eq(defaultConfig.with(list(
scratch("scratch.txt"),
scratch("scratch2.java")
))));
verify(ide).displayScratchesListPopup(eq(list(
scratch("scratch.txt"),
scratch("scratch2.java")
)), same(someUserData));
verifyNoMoreInteractions(fileSystem, ide);
}
@Test public void openingScratch_when_scratchFileExists() {
Scratch scratch = scratch("scratch.txt");
ScratchConfig config = defaultConfig.with(list(scratch));
mrScratchManager = scratchManagerWith(config);
when(fileSystem.scratchFileExists("scratch.txt")).thenReturn(true);
mrScratchManager.userWantsToOpenScratch(scratch, someUserData);
verify(fileSystem).scratchFileExists(eq("scratch.txt"));
verify(ide).openScratch(eq(scratch), same(someUserData));
}
@Test public void openingScratch_when_scratchFileDoesNotExist() {
Scratch scratch = scratch("scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.scratchFileExists("scratch.txt")).thenReturn(false);
mrScratchManager.userWantsToOpenScratch(scratch, someUserData);
verify(fileSystem).scratchFileExists(eq("scratch.txt"));
verify(log).failedToOpen(eq(scratch));
verifyNoMoreInteractions(fileSystem, ide, log);
}
@Test public void openingDefaultScratch_when_itCanBeOpened_and_configuredAs_topmost() {
Scratch scratch1 = scratch("scratch1.txt");
Scratch scratch2 = scratch("scratch2.txt");
ScratchConfig config = defaultConfig
.with(list(scratch1, scratch2))
.withDefaultScratchMeaning(TOPMOST)
.withLastOpenedScratch(scratch2);
mrScratchManager = scratchManagerWith(config);
when(fileSystem.listScratchFiles()).thenReturn(list(scratch1.asFileName(), scratch2.asFileName()));
when(fileSystem.scratchFileExists(anyString())).thenReturn(true);
mrScratchManager.userWantsToOpenDefaultScratch(someUserData);
verify(ide).openScratch(eq(scratch1), same(someUserData));
}
@Test public void openingDefaultScratch_when_itCanBeOpened_and_configured_asLastOpened() {
Scratch scratch1 = scratch("scratch1.txt");
Scratch scratch2 = scratch("scratch2.txt");
ScratchConfig config = defaultConfig
.with(list(scratch1, scratch2))
.withDefaultScratchMeaning(LAST_OPENED)
.withLastOpenedScratch(scratch2);
mrScratchManager = scratchManagerWith(config);
when(fileSystem.listScratchFiles()).thenReturn(list(scratch1.asFileName(), scratch2.asFileName()));
when(fileSystem.scratchFileExists(anyString())).thenReturn(true);
mrScratchManager.userWantsToOpenDefaultScratch(someUserData);
verify(ide).openScratch(eq(scratch2), same(someUserData));
verifyNoMoreInteractions(ide);
}
@Test public void openingDefaultScratch_when_itIsLastOpened_but_doesNotExist() {
Scratch scratch1 = scratch("scratch1.txt");
Scratch scratch2 = scratch("scratch2.txt");
ScratchConfig config = defaultConfig
.with(list(scratch1, scratch2))
.withDefaultScratchMeaning(LAST_OPENED)
.withLastOpenedScratch(scratch2);
mrScratchManager = scratchManagerWith(config);
when(fileSystem.listScratchFiles()).thenReturn(list(scratch1.asFileName()));
when(fileSystem.scratchFileExists(scratch1.asFileName())).thenReturn(true);
mrScratchManager.userWantsToOpenDefaultScratch(someUserData);
verify(ide).openScratch(eq(scratch1), same(someUserData));
}
@Test public void openingDefaultScratch_when_scratchFileDoesNotExist() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch("scratch.txt"))));
when(fileSystem.listScratchFiles()).thenReturn(new ArrayList<>());
mrScratchManager.userWantsToOpenDefaultScratch(someUserData);
verify(ide).persistConfig(defaultConfig);
verify(ide).openNewScratchDialog(anyString(), same(someUserData));
verifyNoMoreInteractions(ide, log);
}
@Test public void openingDefaultScratch_when_scratchListIsEmpty() {
mrScratchManager = scratchManagerWith(defaultConfig);
when(fileSystem.listScratchFiles()).thenReturn(new ArrayList<>());
mrScratchManager.userWantsToOpenDefaultScratch(someUserData);
verify(ide).openNewScratchDialog(anyString(), same(someUserData));
verifyNoMoreInteractions(ide, log);
}
@Test public void shouldUpdateConfig_when_scratchIsOpened() {
ScratchConfig config = defaultConfig.with(list(scratch("scratch&1.txt"), scratch("scratch&2.txt")));
mrScratchManager = scratchManagerWith(config);
mrScratchManager.userOpenedScratch("scratch2.txt");
verify(ide).persistConfig(config.withLastOpenedScratch(scratch("scratch&2.txt")));
}
@Test public void appendingClipboardTextTo_TopmostScratch() {
Scratch scratch1 = scratch("scratch1.txt");
Scratch scratch2 = scratch("scratch2.txt");
mrScratchManager = scratchManagerWith(defaultConfig
.with(list(scratch1, scratch2))
.withDefaultScratchMeaning(TOPMOST));
when(fileSystem.scratchFileExists(anyString())).thenReturn(true);
mrScratchManager.clipboardListenerWantsToAddTextToScratch("clipboard text");
verify(ide).addTextTo(eq(scratch1), eq("clipboard text"), any(AppendType.class));
}
@Test public void appendingClipboardTextTo_LastOpenedScratch() {
Scratch scratch1 = scratch("scratch1.txt");
Scratch scratch2 = scratch("scratch2.txt");
mrScratchManager = scratchManagerWith(defaultConfig
.with(list(scratch1, scratch2))
.withDefaultScratchMeaning(LAST_OPENED)
.withLastOpenedScratch(scratch2));
when(fileSystem.scratchFileExists(anyString())).thenReturn(true);
mrScratchManager.clipboardListenerWantsToAddTextToScratch("clipboard text");
verify(ide).addTextTo(eq(scratch2), eq("clipboard text"), any(AppendType.class));
}
@Test public void appendingClipboardTextToDefaultScratch_when_scratchListIsEmpty() {
mrScratchManager = scratchManagerWith(defaultConfig);
mrScratchManager.clipboardListenerWantsToAddTextToScratch("clipboard text");
verify(log).failedToOpenDefaultScratch();
}
@Test public void shouldSendNewConfigToIde_when_userTurnsOnListeningToClipboard() {
mrScratchManager = scratchManagerWith(defaultConfig.listenToClipboard(false));
mrScratchManager.userWantsToListenToClipboard(true);
verify(ide).persistConfig(defaultConfig.listenToClipboard(true));
verify(log).listeningToClipboard(true);
}
@Test public void canRenameScratch_when_nameIsUnique() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch("scratch.txt"))));
when(fileSystem.isValidScratchName(anyString())).thenReturn(yes());
Answer answer = mrScratchManager.checkIfUserCanRename(scratch("scratch.txt"), "renamed&Scratch.txt");
assertTrue(answer.isYes);
verify(fileSystem).isValidScratchName("renamedScratch.txt");
verifyZeroInteractions(ide, fileSystem);
}
@Test public void canRenameScratch_when_thereIsScratchWithSameName() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch.txt"),
scratch("&renamedScratch.txt")
)));
Answer answer = mrScratchManager.checkIfUserCanRename(scratch("scratch.txt"), "renamed&Scratch.txt");
assertTrue(answer.isNo);
verifyZeroInteractions(ide, fileSystem);
}
@Test public void canRenameScratch_when_fileNameIsIncorrect() {
Scratch scratch = scratch("scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.isValidScratchName(anyString())).thenReturn(no("for a reason"));
assertThat(mrScratchManager.checkIfUserCanRename(scratch, "renamedScratch.txt"), equalTo(no("for a reason")));
verify(fileSystem).isValidScratchName(eq("renamedScratch.txt"));
verifyNoMoreInteractions(fileSystem, ide);
}
@Test public void renamingScratch_when_fileRenameIsSuccessful() {
Scratch scratch = scratch("scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.renameFile(anyString(), anyString())).thenReturn(true);
mrScratchManager.userWantsToRename(scratch, "&renamedScratch.txt");
verify(fileSystem).renameFile("scratch.txt", "renamedScratch.txt");
verify(ide).persistConfig(defaultConfig.with(list(
scratch("&renamedScratch.txt")
)));
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void renamingScratch_when_fileRenameFails() {
Scratch scratch = scratch("scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.renameFile(anyString(), anyString())).thenReturn(false);
mrScratchManager.userWantsToRename(scratch, "renamedScratch.txt");
verify(fileSystem).renameFile("scratch.txt", "renamedScratch.txt");
verify(log).failedToRename(scratch);
verifyNoMoreInteractions(ide, log, fileSystem);
}
@Test public void renamingScratch_when_newNameIsSameAsTheOldOne() {
Scratch scratch = scratch("scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.renameFile(anyString(), anyString())).thenReturn(false);
mrScratchManager.userWantsToRename(scratch, "scratch.txt");
verifyZeroInteractions(ide, log, fileSystem);
}
@Test public void enteringNewScratchName_when_noScratchesExist() {
mrScratchManager = scratchManagerWith(defaultConfig);
mrScratchManager.userWantsToEnterNewScratchName(someUserData);
verify(ide).openNewScratchDialog(eq("scratch.txt"), eq(someUserData));
}
@Test public void enteringNewScratchName_when_thereAreExistingScratches() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch1.txt"),
scratch("scratch.txt")
)));
mrScratchManager.userWantsToEnterNewScratchName(someUserData);
verify(ide).openNewScratchDialog(eq("scratch2.txt"), eq(someUserData));
}
@Test public void enteringNewScratchName_when_thereAreExistingNonTxtScratches() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch3.js"),
scratch("scratch2.xml"),
scratch("scratch1.xml"),
scratch("scratch1.java"),
scratch("scratch.java")
)));
mrScratchManager.userWantsToEnterNewScratchName(someUserData);
verify(ide).openNewScratchDialog(eq("scratch4.txt"), eq(someUserData));
}
@Test public void canCreateNewScratch_when_nameIsUnique() {
mrScratchManager = scratchManagerWith(defaultConfig);
when(fileSystem.isValidScratchName(anyString())).thenReturn(yes());
Answer answer = mrScratchManager.checkIfUserCanCreateScratchWithName("&scratch.txt");
assertTrue(answer.isYes);
verify(fileSystem).isValidScratchName("scratch.txt");
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void canCreateNewScratch_when_thereIsScratchWithSameNameAndExtension() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch("scratch.txt"))));
Answer answer = mrScratchManager.checkIfUserCanCreateScratchWithName("&scratch.txt");
assertTrue(answer.isNo);
verifyZeroInteractions(ide, fileSystem);
}
@Test public void canCreateNewScratch_when_thereIsScratchWithSameNameButDifferentExtension() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch("scratch.txt"))));
when(fileSystem.isValidScratchName(anyString())).thenReturn(yes());
Answer answer = mrScratchManager.checkIfUserCanCreateScratchWithName("&scratch.js");
assertTrue(answer.isYes);
verify(fileSystem).isValidScratchName("scratch.js");
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void canCreateNewScratch_when_fileNameIsIncorrect() {
mrScratchManager = scratchManagerWith(defaultConfig);
when(fileSystem.isValidScratchName(anyString())).thenReturn(no("for a reason"));
Answer answer = mrScratchManager.checkIfUserCanCreateScratchWithName("&scratch.txt");
assertTrue(answer.isNo);
verify(fileSystem).isValidScratchName("scratch.txt");
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void creatingNewScratch_when_scratchIsCreatedSuccessfully() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch0.txt")
)));
when(fileSystem.createEmptyFile(anyString())).thenReturn(true);
mrScratchManager.userWantsToAddNewScratch("&scratch.txt", someUserData);
verify(fileSystem).createEmptyFile("scratch.txt");
verify(ide).persistConfig(eq(defaultConfig.with(list(
scratch("scratch0.txt"),
scratch("&scratch.txt")
))));
verify(ide).openScratch(eq(scratch("&scratch.txt")), eq(someUserData));
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void creatingNewScratch_when_scratchIsCreatedSuccessfully_andShouldBePrependedToListOfScratches() {
ScratchConfig config = defaultConfig.with(list(
scratch("scratch0.txt")
)).withNewScratch(AppendType.PREPEND);
mrScratchManager = scratchManagerWith(config);
when(fileSystem.createEmptyFile(anyString())).thenReturn(true);
mrScratchManager.userWantsToAddNewScratch("&scratch.txt", someUserData);
verify(fileSystem).createEmptyFile("scratch.txt");
verify(ide).persistConfig(eq(config.with(list(
scratch("&scratch.txt"),
scratch("scratch0.txt")
))));
verify(ide).openScratch(eq(scratch("&scratch.txt")), eq(someUserData));
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void creatingNewScratch_when_fileCreationFails() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch("&scratch.txt"))));
when(fileSystem.createEmptyFile(anyString())).thenReturn(false);
mrScratchManager.userWantsToAddNewScratch("&scratch.txt", someUserData);
verify(fileSystem).createEmptyFile("scratch.txt");
verify(log).failedToCreate(scratch("&scratch.txt"));
}
@Test public void deleteScratch_whenFileCanBeRemoved() {
Scratch scratch = scratch("&scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.removeFile(anyString())).thenReturn(true);
mrScratchManager.userWantsToDeleteScratch(scratch);
verify(fileSystem).removeFile("scratch.txt");
verify(ide).persistConfig(defaultConfig);
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void deleteScratch_whenFileCouldNotBeRemoved() {
Scratch scratch = scratch("&scratch.txt");
mrScratchManager = scratchManagerWith(defaultConfig.with(list(scratch)));
when(fileSystem.removeFile(anyString())).thenReturn(false);
mrScratchManager.userWantsToDeleteScratch(scratch);
verify(fileSystem).removeFile("scratch.txt");
verify(log).failedToDelete(scratch);
verifyNoMoreInteractions(ide, fileSystem);
}
@Test public void movingScratchUpInScratchesList() {
mrScratchManager = scratchManagerWith(defaultConfig.with(list(
scratch("scratch1.txt"),
scratch("scratch2.txt"),
scratch("scratch3.txt")
)));
int shiftUp = -1;
mrScratchManager.userMovedScratch(scratch("scratch2.txt"), shiftUp);
verify(ide).persistConfig(defaultConfig.with(list(
scratch("scratch2.txt"),
scratch("scratch1.txt"),
scratch("scratch3.txt")
)));
}
private static Scratch scratch(String fullNameWithMnemonics) {
return Scratch.create(fullNameWithMnemonics);
}
private MrScratchManager scratchManagerWith(ScratchConfig config) {
return new MrScratchManager(ide, fileSystem, config, log);
}
}