Skip to content

test(amazonq): add e2e test for /transform #5402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 21, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.util.tabType
import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.AmazonQTheme
import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.ThemeBrowserAdapter
import software.aws.toolkits.jetbrains.settings.MeetQSettings
import software.aws.toolkits.telemetry.MetricResult
import software.aws.toolkits.telemetry.Telemetry
import java.util.function.Function

Expand Down Expand Up @@ -70,6 +71,7 @@ class BrowserConnector(
Telemetry.toolkit.willOpenModule.use {
it.module(module.asText())
it.source(trigger.asText())
it.result(MetricResult.Succeeded)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.uitests.transformTests

import com.intellij.driver.sdk.waitForProjectOpen
import com.intellij.ide.starter.ci.CIServer
import com.intellij.ide.starter.config.ConfigurationStorage
import com.intellij.ide.starter.di.di
import com.intellij.ide.starter.driver.engine.runIdeWithDriver
import com.intellij.ide.starter.ide.IdeProductProvider
import com.intellij.ide.starter.junit5.hyphenateWithClass
import com.intellij.ide.starter.models.TestCase
import com.intellij.ide.starter.project.LocalProjectInfo
import com.intellij.ide.starter.runner.CurrentTestMethod
import com.intellij.ide.starter.runner.Starter
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.kodein.di.DI
import org.kodein.di.bindSingleton
import software.aws.toolkits.jetbrains.uitests.TestCIServer
import software.aws.toolkits.jetbrains.uitests.clearAwsXmlFile
import software.aws.toolkits.jetbrains.uitests.executePuppeteerScript
import software.aws.toolkits.jetbrains.uitests.setupTestEnvironment
import software.aws.toolkits.jetbrains.uitests.useExistingConnectionForTest
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths

// language=JS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would recommend keeping the scripts separate, in case more need to be added!

val transformHappyPathScript = """
const puppeteer = require('puppeteer');
async function testNavigation() {
const browser = await puppeteer.connect({
browserURL: "http://localhost:9222"
})
try {
const pages = await browser.pages()
for (const page of pages) {
await page.type('.mynah-chat-prompt-input', '/transform')
await page.keyboard.press('Enter')

await page.waitForSelector('.mynah-chat-item-form-items-container', {
timeout: 5000
})
const formInputs = await page.$$('.mynah-form-input-wrapper')

const moduleLabel = await formInputs[0].evaluate(
element => element.querySelector('.mynah-ui-form-item-mandatory-title').textContent
)
console.log('Module selection label:', moduleLabel)

const versionLabel = await formInputs[1].evaluate(
element => element.querySelector('.mynah-ui-form-item-mandatory-title').textContent
)
console.log('Version selection label:', versionLabel)

await page.evaluate(() => {
const button = document.querySelector('button[action-id="codetransform-input-confirm"]')
button.click()
})

const skipTestsForm = await page.waitForSelector('button[action-id="codetransform-input-confirm-skip-tests"]', {
timeout: 5000
})
console.log('Skip tests form appeared:', skipTestsForm !== null)

await page.evaluate(() => {
const button = document.querySelector('button[action-id="codetransform-input-confirm-skip-tests"]')
button.click()
})

const oneOrMultipleDiffsForm = await page.waitForSelector('button[action-id="codetransform-input-confirm-one-or-multiple-diffs"]', {
timeout: 5000
})
console.log('One or multiple diffs form appeared:', oneOrMultipleDiffsForm !== null)

await page.evaluate(() => {
const button = document.querySelector('button[action-id="codetransform-input-confirm-one-or-multiple-diffs"]')
button.click()
})

const errorMessage = await page.waitForSelector('text/Sorry, I couldn\'t run the Maven clean install command', {
timeout: 5000
})
console.log('Error message:', await errorMessage.evaluate(el => el.textContent))
}
} finally {
await browser.close()
}
}
testNavigation().catch(console.error)

""".trimIndent()

class TransformChatTest {

init {
di = DI {
extend(di)
bindSingleton<CIServer>(overrides = true) { TestCIServer }
val defaults = ConfigurationStorage.instance().defaults.toMutableMap().apply {
put("LOG_ENVIRONMENT_VARIABLES", (!System.getenv("CI").toBoolean()).toString())
}

bindSingleton<ConfigurationStorage>(overrides = true) {
ConfigurationStorage(this, defaults)
}
}
}

@BeforeEach
fun setUp() {
setupTestEnvironment()
}

@Test
fun `can run a transformation from the chat`() {
val testCase = TestCase(
IdeProductProvider.IC,
LocalProjectInfo(
Paths.get("tstData", "Hello")
)
).useRelease(System.getProperty("org.gradle.project.ideProfileName"))

// inject connection
useExistingConnectionForTest()

Starter.newContext(CurrentTestMethod.hyphenateWithClass(), testCase).apply {
System.getProperty("ui.test.plugins").split(File.pathSeparator).forEach { path ->
pluginConfigurator.installPluginFromPath(
Path.of(path)
)
}

copyExistingConfig(Paths.get("tstData", "configAmazonQTests"))
updateGeneralSettings()
}.runIdeWithDriver()
.useDriverAndCloseIde {
waitForProjectOpen()
// required wait time for the system to be fully ready
Thread.sleep(30000)
val result = executePuppeteerScript(transformHappyPathScript)
assertTrue(result.contains("Choose a module to transform"))
assertTrue(result.contains("Choose the target code version"))
assertTrue(result.contains("Skip tests form appeared: true"))
assertTrue(result.contains("One or multiple diffs form appeared: true"))
assertTrue(result.contains("couldn't run the Maven clean install command"))
}
}

companion object {
@JvmStatic
@AfterAll
fun clearAwsXml() {
clearAwsXmlFile()
}
}
}
14 changes: 14 additions & 0 deletions ui-tests-starter/tstData/Hello/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- Sample pom.xml for testing /transform in TransformChatTest.kt -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>1.0.0</modelVersion>
<groupId>transform-testing-group-id</groupId>
<artifactId>transform-testing-artifact-id</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
</project>
Loading