Skip to content
Merged

@ #38

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@

dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ data class GenerationRequest(
val packageName: String? = null,
val className: String,
val outputNotes: String?,
val dependentMethodSignatures: String = ""
val dependentMethodSignatures: String = "",
val environmentContext: String = ""
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ object PromptBuilder {
Target: Java unit/integration tests for the provided Java source.
Requirements:
- Generate a single JUnit 5 test class: {{qualifiedClassName}}.
- Include one executable helper method (for local run) that can run this class's tests.
- Do NOT add a main() method or any manual JUnit Platform launcher/runner; the IDE and Maven/Gradle run the tests.
- Only import packages that are available on a standard JUnit 5 test classpath (org.junit.jupiter.*) plus the project's own classes; do not import org.junit.platform.launcher.* or invent dependencies.
- Use only the test libraries listed under "Test Environment" below; do not import assertion/mock libraries that are not listed (e.g. do not assume AssertJ or Mockito unless they appear there).
- Focus only on methods present in the provided source; do not invent methods.
- Prioritize the method referenced by user notes when provided.
- For each tested method, include meaningful assertions for behavior and edge cases.
Expand Down Expand Up @@ -94,14 +96,18 @@ object PromptBuilder {
))
} else ""

val environmentBlock = if (req.environmentContext.isNotBlank()) {
"\n" + req.environmentContext.trim()
} else ""

return render(template.wrapper, mapOf(
"contractType" to when (req.contractType) {
ContractType.OPENAPI -> "OpenAPI/REST API"
ContractType.JAVA -> "Java Source Methods"
},
"baseUrlHint" to (req.baseUrl ?: "not provided"),
"outputNotes" to (req.outputNotes ?: "(none)"),
"frameworkRules" to frameworkRules + dependentMethodsBlock,
"frameworkRules" to frameworkRules + environmentBlock + dependentMethodsBlock,
"contractText" to req.contractText
))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.openprojectx.ai.plugin.core

import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class PromptBuilderTest {

private fun javaRequest(environmentContext: String) = GenerationRequest(
contractText = "public class Foo { public int bar() { return 1; } }",
framework = Framework.REST_ASSURED,
contractType = ContractType.JAVA,
packageName = "com.example",
className = "FooTest",
outputNotes = null,
environmentContext = environmentContext
)

@Test
fun `injects environment context block into the java prompt`() {
val env = "## Test Environment (use ONLY what is listed here)\n" +
"- Java language level: 17\n" +
"- Test libraries available: JUnit 5, AssertJ"

val prompt = PromptBuilder.build(javaRequest(env))

assertTrue(
prompt.contains("## Test Environment (use ONLY what is listed here)"),
"prompt should contain the environment heading"
)
assertTrue(prompt.contains("Java language level: 17"), "prompt should contain detected language level")
assertTrue(prompt.contains("JUnit 5, AssertJ"), "prompt should contain detected test libraries")
}

@Test
fun `omits environment block when context is blank`() {
val prompt = PromptBuilder.build(javaRequest(""))

assertFalse(prompt.contains("## Test Environment"), "no environment heading when nothing was detected")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.openprojectx.ai.plugin.llm

import com.github.jknack.handlebars.EscapingStrategy
import com.github.jknack.handlebars.Handlebars
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class TemplateRequestHandlebarsTest {

private val bodyTemplate = """{"username": "{{username}}", "password": "{{password}}"}"""

@Test
fun `password with double-quote is corrupted by default HTML escaping`() {
val handlebars = Handlebars()
val template = handlebars.compileInline(bodyTemplate)
val rendered = template.apply(mapOf("username" to "user1", "password" to """pass"123"""))

assertEquals(
"""{"username": "user1", "password": "pass"123"}""",
rendered
)
}

@Test
fun `password with ampersand is corrupted by default HTML escaping`() {
val handlebars = Handlebars()
val template = handlebars.compileInline(bodyTemplate)
val rendered = template.apply(mapOf("username" to "user1", "password" to "pass&123"))

assertEquals(
"""{"username": "user1", "password": "pass&123"}""",
rendered
)
}

@Test
fun `password with special chars is preserved with no-op escaping strategy`() {
val handlebars = Handlebars().with(EscapingStrategy { it })
val template = handlebars.compileInline(bodyTemplate)

val passwordsToTest = listOf(
"""pass"123""",
"pass&123",
"pass<456",
"pass>456",
"pass'456",
"normal_password",
"P@ssw0rd!@#$%^"
)

for (password in passwordsToTest) {
val rendered = template.apply(mapOf("username" to "user1", "password" to password))
assertEquals(
"""{"username": "user1", "password": "$password"}""",
rendered,
"Password '$password' should be preserved verbatim in rendered output"
)
}
}
}
6 changes: 3 additions & 3 deletions plugin-idea/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ plugins {
signing
}

val restrictedNetworkMode = providers.gradleProperty("restrictedNetworkMode")
.map(String::toBooleanStrictOrNull)
val restrictedNetworkMode: Boolean = providers.gradleProperty("restrictedNetworkMode")
.map { it.toBooleanStrictOrNull() ?: false }
.orElse(
providers.environmentVariable("RESTRICTED_NETWORK_MODE")
.map(String::toBooleanStrictOrNull)
.map { it.toBooleanStrictOrNull() ?: false }
)
.getOrElse(false)
val localIntellijPlatformPath = providers.gradleProperty("intellijPlatformLocalPath")
Expand Down
Loading
Loading