Skip to content

Commit

Permalink
Add action tests and release docs
Browse files Browse the repository at this point in the history
  • Loading branch information
opwvhk committed Sep 5, 2024
1 parent aba1b82 commit affd7f3
Show file tree
Hide file tree
Showing 19 changed files with 521 additions and 2 deletions.
6 changes: 5 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ tasks {
//language=HTML
var changeLog = """
<p>Version 223.3.2:</p><ul>
<li>Wrap actions in 'commands' for undo (fixed #160, #161)</li>
<li>Debug refactoring actions (fixes #168, #169)</li>
<li>Add workaround for JetBrains SDK bug (hopefully mitigates #127)</li>
<li>Use newline instead of platform linefeed when generating content (fixes #163)</li>
<li>Add better error message to IDL conversion (issue #167)</li>
<li>Wrap actions in 'commands' for undo (fixes #160, #161)</li>
<li>Refactored hardcoded texts into a resource bundle</li>
</ul>
<p>Version 223.3.1:</p><ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ protected void convertFile(@NotNull Project project, @NotNull ConsoleView consol
console.print("\n", NORMAL_OUTPUT);
WriteCommandAction.runWriteCommandAction(project, actionTitle, "AvroIDL", () -> {
try {
VfsUtil.saveText(virtualFile, protocol.toString(true));
VfsUtil.saveText(virtualFile, protocol.toString(true) + "\n");
console.print("Wrote Avro Protocol \"" + protocol.getName() + "\" to ", NORMAL_OUTPUT);
console.printHyperlink(virtualFile.getName(),
new OpenFileHyperlinkInfo(project, virtualFile, 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.intellij.ide.IdeBundle;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.*;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.*;
Expand All @@ -27,6 +28,7 @@
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

import javax.swing.*;
import java.awt.*;
Expand Down Expand Up @@ -74,11 +76,18 @@ protected void convertFiles(@NotNull Project project, @NotNull ConsoleView conso
console.print("\nAction complete.\n", ConsoleViewContentType.SYSTEM_OUTPUT);
}

@TestOnly
public static VirtualFile targetDirectory = null;

@SuppressWarnings("SameParameterValue")
@Nullable
protected VirtualFile askForTargetDirectory(@NotNull Project project, @Nullable String title,
@Nullable String description,
@Nullable VirtualFile suggestedTargetDirectory) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
// Tests have no UI, and we don't want to manually fill in a dialog during tests anyway.
return targetDirectory;
}
final String nonNullTitle = title == null ? UIBundle.message("file.chooser.default.title") : title;
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor()
.withTitle(nonNullTitle);
Expand All @@ -88,12 +97,19 @@ protected VirtualFile askForTargetDirectory(@NotNull Project project, @Nullable
return FileChooser.chooseFile(descriptor, project, suggestedTargetDirectory);
}

@TestOnly
public static VirtualFileWrapper targetFile = null;

@Nullable
protected VirtualFileWrapper askForTargetFile(@NotNull Project project, @Nullable String title,
@Nullable String description,
@NotNull FileType fileType,
@Nullable VirtualFile suggestedTargetDirectory,
@NotNull String suggestedBaseName) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
// Tests have no UI, and we don't want to manually fill in a dialog during tests anyway.
return targetFile;
}
// False positive: reuse of platform text
//noinspection DialogTitleCapitalization
final String nonNullTitle = title == null ? IdeBundle.message("dialog.title.save.as") : title;
Expand Down
148 changes: 148 additions & 0 deletions src/test/java/opwvhk/intellij/avro_idl/actions/AvroIdlActionsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package opwvhk.intellij.avro_idl.actions;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.testFramework.HeavyPlatformTestCase;
import com.intellij.testFramework.MapDataContext;
import com.intellij.testFramework.TestActionEvent;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import com.intellij.testFramework.fixtures.TempDirTestFixture;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;

public class AvroIdlActionsTest extends
//HeavyPlatformTestCase {
BasePlatformTestCase {

private Path inputDirectory;
private Path outputDirectory;
private Path resultDirectory;

@Override
public void setUp() throws Exception {
super.setUp();

Path testDirectory = Path.of(getTestDataPath(), getTestDirectoryName());
inputDirectory = testDirectory.resolve("input");
outputDirectory = testDirectory.resolve("output");

TempDirTestFixture tempDirFixture = myFixture.getTempDirFixture();
String tempDirPath = tempDirFixture.getTempDirPath();
VirtualFile testFilesDirectory = tempDirFixture.copyAll(getTestDirectoryName(), getTestDirectoryName());
VirtualFile resultVDirectory = tempDirFixture.findOrCreateDir(getTestDirectoryName() + "/results");
//VirtualFile resultVDirectory = getTempDir().createVirtualDir(getTestDirectoryName());
ConversionActionBase.targetDirectory = resultVDirectory;
resultDirectory = resultVDirectory.toNioPath();

Path[] array = list(outputDirectory, s -> s.sorted(Comparator.comparing(Path::toString)).toArray(Path[]::new));
if (array.length == 1) {
Path relative = outputDirectory.relativize(array[0]);
Path expectedResultFile = resultDirectory.resolve(relative);
ConversionActionBase.targetFile = new VirtualFileWrapper(expectedResultFile.toFile());
}
}

@Override
public void tearDown() throws Exception {
ConversionActionBase.targetDirectory = null;
ConversionActionBase.targetFile = null;
super.tearDown();
}

protected String getTestDataPath() {
return "src/test/testData/actions";
}

public void testNoFiles() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.IdlToProtocol");
executeTest(action, false);
}

public void testNoSuitableFiles() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.IdlToProtocol");
executeTest(action, false);
}

public void testIdlToProtocol() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.IdlToProtocol");
executeTest(action, true);
}

public void testIdlToSchema() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.IdlToSchema");
executeTest(action, true);
}

public void testProtocolToIdl() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.ProtocolToIdl");
executeTest(action, true);
}

public void testSchemaToIdl() throws IOException {
AnAction action = ActionManager.getInstance().getAction("AvroIdl.SchemaToIdl");
executeTest(action, true);
}

private void executeTest(AnAction action, boolean shouldExecute) throws IOException {
MapDataContext dataContext = new MapDataContext();
LocalFileSystem vfs = LocalFileSystem.getInstance();
dataContext.put(LangDataKeys.VIRTUAL_FILE_ARRAY,
list(inputDirectory, s -> s.map(vfs::refreshAndFindFileByNioFile).toArray(VirtualFile[]::new)));
dataContext.put(CommonDataKeys.PROJECT, getProject());

TestActionEvent event = new TestActionEvent(dataContext, action);
action.update(event);
Presentation p = event.getPresentation();
assertThat(p.isEnabled()).as("event %s", p.isEnabled() ? "enabled" : "disabled").isEqualTo(shouldExecute);
assertThat(p.isVisible()).as("event %s", p.isVisible() ? "visible" : "hidden").isEqualTo(shouldExecute);

action.actionPerformed(event); // Outside if statement to verify it correctly handles null invocations
if (shouldExecute) {
assertSameTextContentRecursive(resultDirectory, outputDirectory);
} else {
try (Stream<Path> resultFiles = Files.list(resultDirectory)) {
assertThat(resultFiles.count()).isEqualTo(0);
}
}
}

private void assertSameTextContentRecursive(Path actualPath, Path expectedPath) throws IOException {
if (Files.isDirectory(expectedPath)) {
assertThat(actualPath).isDirectory();
List<Path> actualPaths = list(actualPath, s -> s.map(actualPath::relativize).toList());
List<Path> expectedPaths = list(expectedPath, s -> s.map(expectedPath::relativize).toList());
assertThat(actualPaths).isEqualTo(expectedPaths);
for (Path p : expectedPaths) {
assertSameTextContentRecursive(actualPath.resolve(p), expectedPath.resolve(p));
}
} else {
assertThat(actualPath).isRegularFile().hasFileName(expectedPath.getFileName().toString());
String actualContent = Files.readString(actualPath);
String expectedContent = Files.readString(expectedPath);
assertThat(actualContent).as("content of %s", actualPath.getFileName().toString())
.isEqualTo(expectedContent);
}
}

private static <T> T list(Path path, Function<Stream<Path>, T> function) throws IOException {
try (Stream<Path> stream = Files.list(path)) {
return function.apply(stream);
}
}

private static List<Path> list(Stream<Path> stream) throws IOException {
try (Stream<Path> s = stream) {
return s.toList();
}
}
}
29 changes: 29 additions & 0 deletions src/test/testData/actions/idlToProtocol/input/SimpleProtocol.avdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Doc comment.
*/
@namespace("tests")
protocol SimpleProtocol {

record SampleNode {
int count = 0;
array<SamplePair> subNodes;
}

record SamplePair {
Method method;
SampleNode node;
}

record Method {
string name;
string purpose;
}

record SelfRef {
string something;
array<SelfRef> subNodes = [];
}

SampleNode buildNodeTree(string declaration);
SelfRef buildRefTree(string declaration);
}
70 changes: 70 additions & 0 deletions src/test/testData/actions/idlToProtocol/output/SimpleProtocol.avpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"protocol" : "SimpleProtocol",
"namespace" : "tests",
"doc" : "Doc comment.",
"types" : [ {
"type" : "record",
"name" : "SampleNode",
"fields" : [ {
"name" : "count",
"type" : "int",
"default" : 0
}, {
"name" : "subNodes",
"type" : {
"type" : "array",
"items" : {
"type" : "record",
"name" : "SamplePair",
"fields" : [ {
"name" : "method",
"type" : {
"type" : "record",
"name" : "Method",
"fields" : [ {
"name" : "name",
"type" : "string"
}, {
"name" : "purpose",
"type" : "string"
} ]
}
}, {
"name" : "node",
"type" : "SampleNode"
} ]
}
}
} ]
}, {
"type" : "record",
"name" : "SelfRef",
"fields" : [ {
"name" : "something",
"type" : "string"
}, {
"name" : "subNodes",
"type" : {
"type" : "array",
"items" : "SelfRef"
},
"default" : [ ]
} ]
} ],
"messages" : {
"buildNodeTree" : {
"request" : [ {
"name" : "declaration",
"type" : "string"
} ],
"response" : "SampleNode"
},
"buildRefTree" : {
"request" : [ {
"name" : "declaration",
"type" : "string"
} ],
"response" : "SelfRef"
}
}
}
21 changes: 21 additions & 0 deletions src/test/testData/actions/idlToSchema/input/SchemaCycles.avdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace tests;

record SelfRef {
string something;
array<SelfRef> subNodes = [];
}

record SampleNode {
int count = 0;
array<SamplePair> subNodes;
}

record SamplePair {
Method method;
SampleNode node;
}

record Method {
string name;
string purpose;
}
36 changes: 36 additions & 0 deletions src/test/testData/actions/idlToSchema/output/SampleNode.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"type" : "record",
"name" : "SampleNode",
"namespace" : "tests",
"fields" : [ {
"name" : "count",
"type" : "int",
"default" : 0
}, {
"name" : "subNodes",
"type" : {
"type" : "array",
"items" : {
"type" : "record",
"name" : "SamplePair",
"fields" : [ {
"name" : "method",
"type" : {
"type" : "record",
"name" : "Method",
"fields" : [ {
"name" : "name",
"type" : "string"
}, {
"name" : "purpose",
"type" : "string"
} ]
}
}, {
"name" : "node",
"type" : "SampleNode"
} ]
}
}
} ]
}
Loading

0 comments on commit affd7f3

Please sign in to comment.