Skip to content

New module creation UI test + Refactor and consolidate UI test setup … #2511

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
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
6 changes: 3 additions & 3 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Run automated tests
run: ./gradlew test --no-daemon
run: ./gradlew test -PexcludeTests="**/userInterface/**" --no-daemon

build-windows:
runs-on: windows-latest
Expand All @@ -58,7 +58,7 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Run automated tests
run: ./gradlew test --no-daemon
run: ./gradlew test -PexcludeTests="**/userInterface/**" --no-daemon

build-macos:
runs-on: macos-latest
Expand All @@ -84,7 +84,7 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Run automated tests
run: ./gradlew test --no-daemon
run: ./gradlew test -PexcludeTests="**/userInterface/**" --no-daemon

static-tests:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/uitests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: |
export DISPLAY=:99.0
./gradlew uiTests
./gradlew test -PexcludeTests="**/reference/**,**/linemarker/**,**/inspections/**,**/completion/**,**/actions/**"

# Uncomment if investigation is needed:

Expand Down
18 changes: 9 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ tasks {
}

test {
exclude("**/userInterface/**")
val excludePatterns = project.findProperty("excludeTests") as String?

if (!excludePatterns.isNullOrEmpty()) {
// Split the comma-separated string and apply exclusions
excludePatterns.split(",").forEach {
exclude(it.trim())
}
}

useJUnitPlatform()
}

Expand Down Expand Up @@ -247,11 +255,3 @@ kover {
}
}
}

tasks.register<Test>("uiTests") {
exclude("**/reference/**")
exclude("**/linemarker/**")
exclude("**/inspections/**")
exclude("**/completion/**")
exclude("**/actions/**") // Deprecated, all actions should be reimplemented in the UI tests and this exclude should be removed
}
16 changes: 0 additions & 16 deletions runTests.sh

This file was deleted.

14 changes: 14 additions & 0 deletions runUiTests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

rm -rf intellij-test-project
./gradlew clean
./gradlew runIdeForUiTests &
RUN_IDE_PID=$!

sleep 10

./gradlew test -PexcludeTests="**/reference/**,**/linemarker/**,**/inspections/**,**/completion/**,**/actions/**" --no-daemon

kill $RUN_IDE_PID

wait $RUN_IDE_PID 2>/dev/null
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<xy x="48" y="54" width="746" height="642"/>
<xy x="48" y="54" width="746" height="646"/>
</constraints>
<properties>
<preferredSize width="455" height="600"/>
Expand Down Expand Up @@ -68,6 +68,7 @@
</grid>
</constraints>
<properties>
<name value="Package Name"/>
<text value=""/>
<toolTipText resource-bundle="magento2/validation" key="validator.mustNotBeEmptyShouldContainLettersOrNumbers"/>
</properties>
Expand All @@ -92,6 +93,7 @@
</grid>
</constraints>
<properties>
<name value="Module Name"/>
<text value=""/>
<toolTipText resource-bundle="magento2/validation" key="validator.mustNotBeEmptyShouldContainLettersOrNumbers"/>
</properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.pages

import com.intellij.remoterobot.RemoteRobot
import com.intellij.remoterobot.data.RemoteComponent
import com.intellij.remoterobot.fixtures.CommonContainerFixture
import com.intellij.remoterobot.fixtures.DefaultXpath
import com.intellij.remoterobot.fixtures.FixtureName
import com.intellij.remoterobot.fixtures.JTextFieldFixture
import com.intellij.remoterobot.search.locators.byXpath
import java.time.Duration

fun RemoteRobot.createAModuleDialog(function: CreateAModuleDialogFixture.() -> Unit) {
find<CreateAModuleDialogFixture>(timeout = Duration.ofSeconds(10)).apply(function)
}

@FixtureName("CreateAModuleDialog")
@DefaultXpath("CreateAModuleDialog type", "//div[@class='NewModuleDialog']")
class CreateAModuleDialogFixture(
remoteRobot: RemoteRobot,
remoteComponent: RemoteComponent) : CommonContainerFixture(remoteRobot, remoteComponent) {

val packageName
get() = find<JTextFieldFixture>(byXpath("FilteredComboBox", "//div[@name='Package Name']"))

val moduleName
get() = find<JTextFieldFixture>(byXpath("FilteredComboBox", "//div[@name='Module Name']"))
}
17 changes: 0 additions & 17 deletions src/test/kotlin/com/magento/idea/magento2plugin/pages/IdeaFrame.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import com.intellij.remoterobot.RemoteRobot
import com.intellij.remoterobot.data.RemoteComponent
import com.intellij.remoterobot.fixtures.*
import com.intellij.remoterobot.search.locators.byXpath
import com.intellij.remoterobot.stepsProcessing.step
import com.intellij.remoterobot.utils.waitFor
import java.time.Duration


Expand All @@ -29,21 +27,6 @@ class IdeaFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) :
val projectViewTree
get() = find<ContainerFixture>(byXpath("//div[@class='ProjectViewTree']"))

@JvmOverloads
fun dumbAware(timeout: Duration = Duration.ofMinutes(5), function: () -> Unit) {
step("Wait for smart mode") {
waitFor(duration = timeout, interval = Duration.ofSeconds(5)) {
runCatching { isDumbMode().not() }.getOrDefault(false)
}
function()
step("..wait for smart mode again") {
waitFor(duration = timeout, interval = Duration.ofSeconds(5)) {
isDumbMode().not()
}
}
}
}

fun isProjectViewVisible(): Boolean {
return try {
with(projectViewTree) {
Expand Down
204 changes: 204 additions & 0 deletions src/test/kotlin/com/magento/idea/magento2plugin/steps/SharedSteps.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.steps

import com.intellij.remoterobot.RemoteRobot
import com.intellij.remoterobot.fixtures.ContainerFixture
import com.intellij.remoterobot.fixtures.JTextFieldFixture
import com.intellij.remoterobot.search.locators.byXpath
import com.intellij.remoterobot.steps.CommonSteps
import com.intellij.remoterobot.stepsProcessing.step
import com.intellij.remoterobot.utils.keyboard
import com.intellij.remoterobot.utils.waitFor
import com.magento.idea.magento2plugin.pages.*
import java.awt.Point
import java.awt.event.KeyEvent.*
import java.io.File
import java.io.IOException
import java.nio.file.Paths
import java.time.Duration.ofMinutes
import java.util.*

class SharedSteps(private val remoteRobot: RemoteRobot) {
private lateinit var tempProjectDir: File

fun createOrOpenTestProject(): File {
setupTemporaryMagentoProject()

step("Create Or Open Test Project", Runnable {
try {
remoteRobot.welcomeFrame {
val newProjectButton = remoteRobot.find(
ContainerFixture::class.java,
byXpath("//div[@visible_text='New Project']")
)
newProjectButton.click()
Thread.sleep(2_000)

val jTextFieldFixture = find<JTextFieldFixture>(byXpath("//div[@class='TextFieldWithBrowseButton']"))
jTextFieldFixture.click()
jTextFieldFixture.keyboard {
hotKey(VK_CONTROL, VK_A)
key(VK_DELETE)
enterText(tempProjectDir.absolutePath.toString().replace("\\", "\\\\"))
}
keyboard { key(VK_ENTER) }

dialog("Directory Is Not Empty") {
button("Create from Existing Sources").click()
}

enableMagentoSupport()
}
} catch (exception: Exception) {
// temporary workaround until we get license for CI
activateIde()
// end temporary workaround
try {
val launchedFromScript = remoteRobot.find(
ContainerFixture::class.java,
byXpath("//div[@class='LinkLabel']")
)
launchedFromScript.click()
} catch (e: Exception) {
// Element does not exist, continue without failing the test
}

createProjectFromExistingFiles()
enableMagentoSupport()
}
})

return tempProjectDir;
}

fun closeProject() {
CommonSteps(remoteRobot).closeProject()
}

private fun setupTemporaryMagentoProject() {
// Create a parent directory and a random child directory inside it
val parentDir = Paths.get("intellij-test-project").toFile()
if (parentDir.exists()) {
parentDir.deleteRecursively()
}
parentDir.mkdirs()

// Create a randomly named child directory inside the parent directory
tempProjectDir = File(parentDir, UUID.randomUUID().toString()).apply {
mkdirs()
}

// Define the source directory for the test data
val sourceDir = File("testData/project/magento2")

// Copy the test data to the temporary directory
sourceDir.copyRecursively(
target = tempProjectDir,
overwrite = true
)
}

private fun activateIde() {
if ("true" == System.getenv("GITHUB_ACTIONS")) {
val startTrial =
remoteRobot.find(ContainerFixture::class.java, byXpath("//div[@visible_text='Start trial']"))
startTrial.click()

val startTrialFree = remoteRobot.find(ContainerFixture::class.java, byXpath("//div[@class='s']"))
startTrialFree.click()

val dialog = remoteRobot.find(
DialogFixture::class.java, byXpath("//div[@class='MyDialog']")
)
dialog.button("Close").click()

try {
Thread.sleep(10000)
} catch (e: InterruptedException) {
Thread.currentThread().interrupt()
throw RuntimeException(e)
}

closeBrowser()
} else {
val dialog = remoteRobot.find(
DialogFixture::class.java, byXpath("//div[@class='MyDialog']")
)
dialog.button("Activate").click()
dialog.button("Close").click()
}
}

private fun enableMagentoSupport() {
remoteRobot.idea {
step("Enable Magento Integration") {
waitFor(ofMinutes(1)) { isDumbMode().not() }
Thread.sleep(5_000)
enableSupportLink.click(Point(1, 1))
waitFor(ofMinutes(1)) { isDumbMode().not() }

if (!isProjectViewVisible()) {
keyboard {
hotKey(VK_ALT, VK_1)
}
}
}
}
}

private fun createProjectFromExistingFiles() {
remoteRobot.welcomeFrame {
try {
val launchedFromScript = find<ContainerFixture>(byXpath("//div[@class='LinkLabel']"))
launchedFromScript.click()
} catch (e: Exception) {
// Element does not exist, continue without failing the test
}

createNewProjectFromExistingFilesLink.click()
selectProjectPath()
}
}

private fun WelcomeFrame.selectProjectPath() {
dialog("Open File or Project") {
// Set the path for the copied test data
val comboBox = find<ContainerFixture>(byXpath("//div[@class='BorderlessTextField']"))
comboBox.click() // Focus on the comboBox
comboBox.keyboard {
hotKey(VK_CONTROL, VK_A) // Select all text
key(VK_DELETE) // Delete selected text
enterText(tempProjectDir.absolutePath.toString().replace("\\", "\\\\"))
}

button("OK").click()
trustProjectLink.click()
}
}

/**
* Closes the browser by terminating its process based on the operating system.
*/
fun closeBrowser() {
val os = System.getProperty("os.name").lowercase(Locale.getDefault())

try {
if (os.contains("win")) {
// For Windows: Close common browsers like Chrome, Firefox, etc.
Runtime.getRuntime().exec("taskkill /F /IM edge.exe")
} else if (os.contains("mac")) {
// For macOS: Kill browsers using `pkill`
Runtime.getRuntime().exec("killall -9 safari")
} else if (os.contains("nix") || os.contains("nux")) {
// For Linux-based systems: Kill typical browser processes
Runtime.getRuntime().exec("killall -9 firefox")
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
Loading
Loading