diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 445c3fc..024bd5f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: # Free GitHub Actions Environment Disk Space - name: Maximize Build Space - uses: jlumbroso/free-disk-space@main + uses: jlumbroso/free-disk-space@v2 with: tool-cache: false large-packages: false @@ -50,11 +50,11 @@ jobs: # Validate wrapper - name: Gradle Wrapper Validation - uses: gradle/actions/wrapper-validation@v3 + uses: gradle/actions/wrapper-validation@v4 # Set up Java environment for the next steps - name: Setup Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: zulu java-version: 17 @@ -110,7 +110,7 @@ jobs: # Free GitHub Actions Environment Disk Space - name: Maximize Build Space - uses: jlumbroso/free-disk-space@main + uses: jlumbroso/free-disk-space@v2 with: tool-cache: false large-packages: false @@ -121,7 +121,7 @@ jobs: # Set up Java environment for the next steps - name: Setup Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: zulu java-version: 17 @@ -144,7 +144,7 @@ jobs: # Upload the Kover report to CodeCov - name: Upload Code Coverage Report - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: ${{ github.workspace }}/build/reports/kover/report.xml @@ -158,7 +158,7 @@ jobs: # Free GitHub Actions Environment Disk Space - name: Maximize Build Space - uses: jlumbroso/free-disk-space@main + uses: jlumbroso/free-disk-space@v2 with: tool-cache: false large-packages: false @@ -169,7 +169,7 @@ jobs: # Set up Java environment for the next steps - name: Setup Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: zulu java-version: 17 @@ -207,7 +207,7 @@ jobs: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v4 # Remove old release drafts by using the curl request for the available releases with draft flag - name: Remove Old Release Drafts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dee78bf..28212e7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: # Free GitHub Actions Environment Disk Space - name: Maximize Build Space - uses: jlumbroso/free-disk-space@main + uses: jlumbroso/free-disk-space@v2 with: tool-cache: false large-packages: false @@ -33,7 +33,7 @@ jobs: # Set up Java environment for the next steps - name: Setup Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: zulu java-version: 17 diff --git a/.github/workflows/run-ui-tests.yml b/.github/workflows/run-ui-tests.yml index 3108cf1..6e2a017 100644 --- a/.github/workflows/run-ui-tests.yml +++ b/.github/workflows/run-ui-tests.yml @@ -33,15 +33,14 @@ jobs: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v4 - # Setup Java 11 environment for the next steps + # Setup Java environment for the next steps - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v5 with: distribution: zulu - java-version: 11 - cache: gradle + java-version: 17 # Run IDEA prepared for UI testing - name: Run IDE @@ -49,11 +48,11 @@ jobs: # Wait for IDEA to be started - name: Health Check - uses: jtalk/url-health-check-action@v2 + uses: jtalk/url-health-check-action@v3 with: url: http://127.0.0.1:8082 max-attempts: 15 - retry-delay: 30s + retry-delay: 30 # Run tests - name: Tests diff --git a/.gitignore b/.gitignore index 9df7ba5..364b4f3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .qodana build local +.intellijPlatform +.kotlin diff --git a/build.gradle.kts b/build.gradle.kts index 8022364..9c54bc9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { intellijPlatform { pluginConfiguration { ideaVersion { - sinceBuild = "242.*" + sinceBuild = "242" } } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 2181fb4..6835281 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -3,6 +3,7 @@ com.github.serverfrog.bitburnerplugin Bitburner-Connector Serverfrog + IntelliJ plugin for Bitburner game integration, enabling file synchronization and project actions. com.intellij.modules.platform diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroupTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroupTest.kt new file mode 100644 index 0000000..4278288 --- /dev/null +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroupTest.kt @@ -0,0 +1,76 @@ +package com.github.serverfrog.bitburnerplugin.action + +import com.intellij.openapi.actionSystem.AnAction +import org.junit.Before +import org.junit.Test +import org.junit.Assert.* + +class BitburnerActionGroupTest { + + private lateinit var actionGroup: BitburnerActionGroup + + @Before + fun setUp() { + actionGroup = BitburnerActionGroup() + } + + @Test + fun testExtensionsContainsSupportedFiles() { + assertTrue("js should be supported", extensions.contains("js")) + assertTrue("script should be supported", extensions.contains("script")) + assertTrue("ns should be supported", extensions.contains("ns")) + assertTrue("txt should be supported", extensions.contains("txt")) + } + + @Test + fun testExtensionsDoesNotContainUnsupportedFiles() { + assertFalse("java should not be supported", extensions.contains("java")) + assertFalse("py should not be supported", extensions.contains("py")) + assertFalse("kt should not be supported", extensions.contains("kt")) + } + + @Test + fun testGetChildrenReturnsEmptyForNullEvent() { + // Act + val actions = actionGroup.getChildren(null) + + // Assert + assertEquals(0, actions.size) + } + + @Test + fun testAppendAddsElementToArray() { + // Arrange + val emptyArray = emptyArray() + val action = BitburnerPushAction() + + // Act + val result = actionGroup.append(emptyArray, action) + + // Assert + assertEquals(1, result.size) + assertTrue(result[0] is BitburnerPushAction) + } + + @Test + fun testAppendToNonEmptyArray() { + // Arrange + val existing: Array = arrayOf(BitburnerPushAction()) + val action = BitburnerPushAction() + + // Act + val result = actionGroup.append(existing, action) + + // Assert + assertEquals(2, result.size) + } + + @Test + fun testActionGroupInstantiation() { + // Act + val group = BitburnerActionGroup() + + // Assert + assertNotNull(group) + } +} diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushActionTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushActionTest.kt new file mode 100644 index 0000000..60b89d7 --- /dev/null +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushActionTest.kt @@ -0,0 +1,34 @@ +package com.github.serverfrog.bitburnerplugin.action + +import org.junit.Test +import org.junit.Assert.* + +class BitburnerPushActionTest { + + @Test + fun testPushActionInstantiation() { + // Act + val action = BitburnerPushAction() + + // Assert + assertNotNull(action) + } + + @Test + fun testPushActionHasTemplatePresentation() { + // Act + val action = BitburnerPushAction() + + // Assert + assertNotNull(action.templatePresentation) + } + + @Test + fun testPushActionTemplateName() { + // Act + val action = BitburnerPushAction() + + // Assert - the action should have a non-null template presentation text + assertNotNull(action.templatePresentation.text) + } +} diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburnerTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburnerTest.kt new file mode 100644 index 0000000..70061ef --- /dev/null +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburnerTest.kt @@ -0,0 +1,145 @@ +package com.github.serverfrog.bitburnerplugin.bitburner + +import org.junit.Test +import org.junit.Assert.* +import java.nio.file.Paths +import java.util.* + +class PushToBitburnerTest { + + @Test + fun testBase64EncodeDecodeRoundTrip() { + // Arrange + val content = "const x = 42; // test" + + // Act + val encoded = String(Base64.getEncoder().encode(content.toByteArray())) + val decoded = String(Base64.getDecoder().decode(encoded)) + + // Assert + assertEquals(content, decoded) + } + + @Test + fun testBase64EncodeEmptyString() { + // Arrange + val content = "" + + // Act + val encoded = String(Base64.getEncoder().encode(content.toByteArray())) + val decoded = String(Base64.getDecoder().decode(encoded)) + + // Assert + assertEquals(content, decoded) + } + + @Test + fun testBase64EncodeUnicodeContent() { + // Arrange + val content = "你好世界 🌍" + + // Act + val encoded = String(Base64.getEncoder().encode(content.toByteArray())) + val decoded = String(Base64.getDecoder().decode(encoded)) + + // Assert + assertEquals(content, decoded) + } + + @Test + fun testPathNormalization() { + // Arrange + val projectPath = "/home/user/project" + val filePath = Paths.get(projectPath).resolve("src/test/example.js").toString() + + // Act + val relativePath = Paths.get(projectPath).relativize(Paths.get(filePath)) + val normalizedPath = relativePath.toString().replace("[\\\\|/]+".toRegex(), "/") + + // Assert + assertEquals("src/test/example.js", normalizedPath) + } + + @Test + fun testPathNormalizationWithBackslashes() { + // Arrange + val projectPath = "/home/user/project" + // On Linux, Paths.get normalizes backslashes, so test the regex replacement directly + val pathWithBackslashes = "src\\test\\example.js" + + // Act + val normalizedPath = pathWithBackslashes.replace("[\\\\|/]+".toRegex(), "/") + + // Assert - backslashes should be normalized to forward slashes + assertFalse(normalizedPath.contains("\\")) + assertEquals("src/test/example.js", normalizedPath) + } + + @Test + fun testPathNormalizationWithMixedSeparators() { + // Arrange + val projectPath = "/home/user/project" + val mixedPath = Paths.get(projectPath).resolve("src/test/example.js").toString() + + // Act + val relativePath = Paths.get(projectPath).relativize(Paths.get(mixedPath)) + val normalizedPath = relativePath.toString().replace("[\\\\|/]+".toRegex(), "/") + + // Assert + assertEquals("src/test/example.js", normalizedPath) + } + + @Test + fun testRelativePathFromNestedDirectory() { + // Arrange + val projectPath = "/home/user/project" + val nestedPath = Paths.get(projectPath).resolve("a/b/c/d/file.js").toString() + + // Act + val relativePath = Paths.get(projectPath).relativize(Paths.get(nestedPath)) + val normalizedPath = relativePath.toString().replace("[\\\\|/]+".toRegex(), "/") + + // Assert + assertEquals("a/b/c/d/file.js", normalizedPath) + } + + @Test + fun testFileContentFromResource() { + // Arrange & Act + val inputStream = javaClass.classLoader.getResourceAsStream("testData/test.js") + + // Assert + assertNotNull("test.js should be on classpath", inputStream) + val content = inputStream.bufferedReader().use { it.readText() } + assertTrue(content.contains("console.log")) + } + + @Test + fun testFileContentPreservesNewlines() { + // Arrange & Act + val inputStream = javaClass.classLoader.getResourceAsStream("testData/special.js") + + // Assert + assertNotNull("special.js should be on classpath", inputStream) + val content = inputStream.bufferedReader().use { it.readText() } + assertTrue(content.contains("\n")) + val lines = content.split("\n") + assertTrue(lines.size > 1) + } + + @Test + fun testBase64EncodingMatchesExpectedFormat() { + // Arrange + val content = "console.log('hello');\n" + + // Act + val encoded = String(Base64.getEncoder().encode(content.toByteArray())) + + // Assert + assertNotNull(encoded) + assertTrue(encoded.length > 0) + // Verify decoding matches original + val decoded = String(Base64.getDecoder().decode(encoded)) + assertEquals(content, decoded) + } +} diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettingsTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettingsTest.kt new file mode 100644 index 0000000..ec8597c --- /dev/null +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettingsTest.kt @@ -0,0 +1,50 @@ +package com.github.serverfrog.bitburnerplugin.config + +import org.junit.Test +import org.junit.Assert.* + +class BitburnerSettingsTest { + + @Test + fun testSettingsInstantiation() { + // Act + val settings = BitburnerSettings() + + // Assert + assertNotNull(settings) + } + + @Test + fun testSettingsExtendsConfigurableBase() { + // Arrange & Act + val settings = BitburnerSettings() + + // Assert - verify it extends ConfigurableBase + assertNotNull(settings) + // ConfigurableBase implements Configurable interface + val configurable: com.intellij.openapi.options.Configurable = settings + assertNotNull(configurable) + } + + @Test + fun testSettingsUiInstantiation() { + // Act + val ui = BitBurnerSettingsUi() + + // Assert + assertNotNull(ui) + } + + @Test + fun testSettingsUiGetComponentReturnsPanel() { + // Arrange + val ui = BitBurnerSettingsUi() + + // Act + val component = ui.getComponent() + + // Assert + assertNotNull(component) + assertTrue(component is javax.swing.JPanel) + } +} diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/listener/FileWatcherTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/listener/FileWatcherTest.kt new file mode 100644 index 0000000..b8c0b60 --- /dev/null +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/listener/FileWatcherTest.kt @@ -0,0 +1,51 @@ +package com.github.serverfrog.bitburnerplugin.listener + +import com.github.serverfrog.bitburnerplugin.action.extensions +import org.junit.Test +import org.junit.Assert.* + +class FileWatcherTest { + + @Test + fun testFileWatcherInstantiation() { + // Act + val watcher = FileWatcher() + + // Assert + assertNotNull(watcher) + } + + @Test + fun testFileWatcherImplementsBulkFileListener() { + // Act + val watcher = FileWatcher() + + // Assert - assign to interface type to verify it implements BulkFileListener + val listener: com.intellij.openapi.vfs.newvfs.BulkFileListener = watcher + assertNotNull(listener) + } + + @Test + fun testExtensionsListUsedByWatcher() { + // The FileWatcher uses the `extensions` list from the action package + assertTrue(extensions.contains("js")) + assertTrue(extensions.contains("script")) + assertTrue(extensions.contains("ns")) + assertTrue(extensions.contains("txt")) + } + + @Test + fun testExtensionsListDoesNotContainJava() { + assertFalse(extensions.contains("java")) + } + + @Test + fun testExtensionsListDoesNotContainKotlin() { + assertFalse(extensions.contains("kt")) + } + + @Test + fun testExtensionsListDoesNotContainPython() { + assertFalse(extensions.contains("py")) + } +} diff --git a/src/test/resources/testData/special.js b/src/test/resources/testData/special.js new file mode 100644 index 0000000..858e2af --- /dev/null +++ b/src/test/resources/testData/special.js @@ -0,0 +1,5 @@ +const name = "test"; +const special = "with 'quotes' and \"double quotes\""; +const unicode = "你好世界"; +const newline = "line1\nline2"; +console.log(name, special, unicode, newline); diff --git a/src/test/resources/testData/test.js b/src/test/resources/testData/test.js new file mode 100644 index 0000000..e921523 --- /dev/null +++ b/src/test/resources/testData/test.js @@ -0,0 +1 @@ +console.log('hello'); diff --git a/src/test/testData/special.js b/src/test/testData/special.js new file mode 100644 index 0000000..858e2af --- /dev/null +++ b/src/test/testData/special.js @@ -0,0 +1,5 @@ +const name = "test"; +const special = "with 'quotes' and \"double quotes\""; +const unicode = "你好世界"; +const newline = "line1\nline2"; +console.log(name, special, unicode, newline); diff --git a/src/test/testData/test.js b/src/test/testData/test.js new file mode 100644 index 0000000..e921523 --- /dev/null +++ b/src/test/testData/test.js @@ -0,0 +1 @@ +console.log('hello');