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');