Skip to content
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
15 changes: 15 additions & 0 deletions .github/workflows/ci.main.kts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ workflow(
)
}

job(
id = "web-e2e",
runsOn = UbuntuLatest,
) {
uses(name = "Check out", action = Checkout())
uses(
name = "Set up JDK 17",
action = SetupJava(
javaVersion = "17",
distribution = SetupJava.Distribution.Temurin,
),
)
run(name = "E2E smoke test", command = "./gradlew :web-e2e:test")
}

job(
id = "web",
runsOn = UbuntuLatest,
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,23 @@ jobs:
- id: 'step-3'
name: 'Upload coverage to Codecov'
uses: 'codecov/codecov-action@v4'
web-e2e:
runs-on: 'ubuntu-latest'
needs:
- 'check_yaml_consistency'
steps:
- id: 'step-0'
name: 'Check out'
uses: 'actions/checkout@v4'
- id: 'step-1'
name: 'Set up JDK 17'
uses: 'actions/setup-java@v4'
with:
java-version: '17'
distribution: 'temurin'
- id: 'step-2'
name: 'E2E smoke test'
run: './gradlew :web-e2e:test'
web:
runs-on: 'ubuntu-latest'
permissions:
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ pluginManagement {

rootProject.name = "fsynth"

include("core", "cli", "web", ":web:worker", ":web:serviceworker", "android")
include("core", "cli", "web", ":web:worker", ":web:serviceworker", "android", "web-e2e")
19 changes: 19 additions & 0 deletions web-e2e/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
kotlin("jvm")
}

val kotlinVersion: String by rootProject.extra

dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("junit:junit:4.13.2")
testImplementation("org.seleniumhq.selenium:selenium-java:4.15.0")
testImplementation("io.github.bonigarcia:webdrivermanager:5.6.2")
}

tasks.test {
dependsOn(":web:build")
systemProperty("web.dist", rootProject.projectDir.resolve("web/build/distributions").absolutePath)
}
71 changes: 71 additions & 0 deletions web-e2e/src/test/kotlin/it/krzeminski/fsynth/SmokeTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package it.krzeminski.fsynth

import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpServer
import io.github.bonigarcia.wdm.WebDriverManager
import java.io.File
import java.net.InetSocketAddress
import java.nio.file.Files
import org.junit.AfterClass
import org.junit.Assert.assertTrue
import org.junit.BeforeClass
import org.junit.Test
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions

class SmokeTest {
companion object {
private lateinit var server: HttpServer
private lateinit var driver: ChromeDriver
private const val PORT = 8765

@BeforeClass
@JvmStatic
fun setup() {
val webDist = System.getProperty("web.dist")!!
server = HttpServer.create(InetSocketAddress(PORT), 0).apply {
createContext("/") { exchange: HttpExchange ->
val file = File(webDist, exchange.requestURI.path).normalize()
if (file.absolutePath.startsWith(File(webDist).absolutePath) && file.isFile) {
exchange.sendResponseHeaders(200, file.length())
Files.copy(file.toPath(), exchange.responseBody)
} else {
exchange.sendResponseHeaders(404, -1)
}
exchange.close()
}
executor = null
}
server.start()
println("HTTP server started on port $PORT, serving $webDist")

WebDriverManager.chromedriver().setup()
val options = ChromeOptions().apply {
addArguments("--headless")
addArguments("--no-sandbox")
addArguments("--disable-dev-shm-usage")
}
driver = ChromeDriver(options)
println("ChromeDriver started")
}

@AfterClass
@JvmStatic
fun teardown() {
driver.quit()
server.stop(0)
println("Cleanup done")
}
}

@Test
fun titleAndSongListAreDisplayed() {
driver.get("http://localhost:$PORT/index.html")

val bodyText = driver.findElement(By.tagName("body")).text
assertTrue("Page should contain app title", bodyText.contains("fsynth"))
assertTrue("Page should contain at least one song name", bodyText.contains("Simple demo song"))
assertTrue("Page should contain playback customization section", bodyText.contains("Playback customization"))
}
}
Loading