fix: remove smoke-tests

This is rather useless in the current form since it doesn't actually update the fixtures so the tests don't do anything useful yet. Will reintroduce it at a later point.
This commit is contained in:
Harsh Shandilya
2026-07-14 12:51:23 +05:30
committed by GitHub
parent 194ccb540a
commit 1001bbc386
9 changed files with 0 additions and 349 deletions
-23
View File
@@ -1,23 +0,0 @@
name: Smoke tests
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
smoke-tests:
runs-on: macos-26
steps:
- name: Setup build environment
uses: msfjarvis/compose-lobsters/.github/reusable-workflows/setup-gradle@main
with:
fetch-depth: 0
cache-read-only: true
- name: Run smoke probe
run: ./gradlew --no-configuration-cache --stacktrace :smoke-tests:run
-1
View File
@@ -162,6 +162,5 @@ include(
"database:core",
"database:impl",
"model",
"smoke-tests",
"zipline-parser",
)
-31
View File
@@ -1,31 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
plugins {
java
id("dev.msfjarvis.claw.kotlin-jvm")
alias(libs.plugins.dependencyAnalysis)
alias(libs.plugins.metro)
}
val smokeTestsMainClass = "dev.msfjarvis.claw.smoketests.MainKt"
tasks.register<JavaExec>("run") {
group = "application"
description = "Runs the smoke tests application."
classpath = sourceSets.main.get().runtimeClasspath
mainClass.set(smokeTestsMainClass)
}
dependencies {
implementation(projects.api)
implementation(projects.core)
implementation(projects.ziplineParser)
implementation(libs.eithernet.integration.retrofit)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.okhttp.core)
implementation(libs.retrofit)
}
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 9.4.0-alpha03" type="baseline" client="gradle" dependencies="true" name="AGP (9.4.0-alpha03)" variant="all" version="9.4.0-alpha03">
</issues>
@@ -1,23 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.smoketests
import dev.msfjarvis.claw.api.LobstersParserClient
import dev.msfjarvis.claw.parser.LobstersParserService
import dev.msfjarvis.claw.parser.LobstersParserServiceImpl
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject
import dev.zacsweers.metro.binding
@Inject
@ContributesBinding(AppScope::class, binding = binding<LobstersParserClient>())
class JvmParserClient : LobstersParserClient {
private val service = LobstersParserServiceImpl()
override suspend fun service(): LobstersParserService = service
}
@@ -1,22 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.smoketests
import kotlin.system.exitProcess
import kotlinx.coroutines.runBlocking
fun main() {
val graph = createSmokeTestsGraph()
val result = runBlocking { graph.smokeProbeRunner.run() }
if (!result.isSuccess) {
System.err.println("Smoke probe failed")
result.errors().forEach { System.err.println(it) }
exitProcess(1)
}
println("Smoke probe passed")
exitProcess(0)
}
@@ -1,155 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.smoketests
import com.slack.eithernet.ApiResult
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.Tag
import dev.zacsweers.metro.Inject
class SmokeProbeResult(private val errors: List<String>) {
val isSuccess: Boolean
get() = errors.isEmpty()
fun errors(): List<String> = errors
}
@Inject
class SmokeProbeRunner(private val api: LobstersApi) {
suspend fun run(): SmokeProbeResult {
val failures = mutableListOf<String>()
val hottest = probe("getHottestPosts(1)", failures) { api.getHottestPosts(1) }
val hottestPosts = hottest?.also { validatePosts("getHottestPosts(1)", it, failures) }.orEmpty()
probe("getNewestPosts(1)", failures) { api.getNewestPosts(1) }
?.also { validatePosts("getNewestPosts(1)", it, failures) }
probe("getTags()", failures) { api.getTags() }?.also { validateTags(it, failures) }
probe("getCSRFToken()", failures) { api.getCSRFToken() }
?.also { token -> if (token.value.isBlank()) failures += "getCSRFToken(): blank token" }
val discoveredPost = hottestPosts.firstOrNull {
it.shortId.isNotBlank() && it.submitter.isNotBlank()
}
if (discoveredPost == null) {
failures += "discovery: no post with usable id and username"
return SmokeProbeResult(failures)
}
probe("getUser(${discoveredPost.submitter})", failures) {
api.getUser(discoveredPost.submitter)
}
?.also { user -> validateUser(discoveredPost.submitter, user.username, failures) }
probe("getPostDetails(${discoveredPost.shortId})", failures) {
api.getPostDetails(discoveredPost.shortId)
}
?.also { details ->
validatePostDetails(discoveredPost.shortId, discoveredPost.submitter, details, failures)
}
return SmokeProbeResult(failures)
}
private suspend fun <T : Any> probe(
name: String,
failures: MutableList<String>,
block: suspend () -> ApiResult<T, Unit>,
): T? {
return when (val result = block()) {
is ApiResult.Success -> {
println("PASS $name")
result.value
}
is ApiResult.Failure -> {
val message = "FAIL $name: $result"
println(message)
failures += message
null
}
}
}
}
private fun validatePosts(name: String, posts: List<LobstersPost>, failures: MutableList<String>) {
if (posts.isEmpty()) {
failures += "$name: empty posts"
return
}
posts.forEachIndexed { index, post ->
if (post.shortId.isBlank()) failures += "$name: post[$index] blank id"
if (post.title.isBlank()) failures += "$name: post[$index] blank title"
if (post.url.isBlank()) failures += "$name: post[$index] blank url"
if (post.tags.isEmpty()) failures += "$name: post[$index] empty tags"
post.tags.forEachIndexed { tagIndex, tag ->
if (tag.isBlank()) failures += "$name: post[$index] tag[$tagIndex] blank name"
}
}
}
private fun validateTags(tags: List<Tag>, failures: MutableList<String>) {
if (tags.isEmpty()) {
failures += "getTags(): empty tags"
return
}
tags.forEachIndexed { index, tag ->
if (tag.tag.isBlank()) failures += "getTags(): tag[$index] blank name"
}
}
private fun validateUser(
expectedUsername: String,
actualUsername: String,
failures: MutableList<String>,
) {
if (actualUsername.isBlank()) failures += "getUser($expectedUsername): blank username"
if (actualUsername.isNotBlank() && actualUsername != expectedUsername) {
failures += "getUser($expectedUsername): returned username '$actualUsername'"
}
}
private fun validatePostDetails(
expectedShortId: String,
expectedSubmitter: String,
details: LobstersPostDetails,
failures: MutableList<String>,
) {
if (details.shortId.isBlank()) failures += "getPostDetails($expectedShortId): blank id"
if (details.shortId.isNotBlank() && details.shortId != expectedShortId) {
failures += "getPostDetails($expectedShortId): returned id '${details.shortId}'"
}
if (details.title.isBlank()) failures += "getPostDetails($expectedShortId): blank title"
if (details.submitter.isNotBlank() && details.submitter != expectedSubmitter) {
failures += "getPostDetails($expectedShortId): returned submitter '${details.submitter}'"
}
if (details.tags.isEmpty()) failures += "getPostDetails($expectedShortId): empty tags"
details.tags.forEachIndexed { index, tag ->
if (tag.isBlank()) failures += "getPostDetails($expectedShortId): tag[$index] blank name"
}
details.comments.forEachIndexed { index, comment ->
validateComment(expectedShortId, comment, index, failures)
}
}
private fun validateComment(
expectedShortId: String,
comment: Comment,
index: Int,
failures: MutableList<String>,
) {
if (comment.shortId.isBlank())
failures += "getPostDetails($expectedShortId): comment[$index] blank id"
if (comment.user.isBlank())
failures += "getPostDetails($expectedShortId): comment[$index] blank username"
if (comment.score < 0)
failures += "getPostDetails($expectedShortId): comment[$index] invalid score ${comment.score}"
}
@@ -1,64 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.smoketests
import dev.msfjarvis.claw.core.network.OkHttpClientConfigurator
import dev.msfjarvis.claw.core.network.SessionCookieStore
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.BindingContainer
import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides
import java.io.File
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import okhttp3.logging.HttpLoggingInterceptor
@BindingContainer
@ContributesTo(AppScope::class)
object SmokeTestsBindings {
@Provides
fun provideCacheDir(): File =
File(System.getProperty("java.io.tmpdir"), "claw-smoke-tests").apply {
mkdirs()
}
@Provides fun provideSessionCookieStore(): SessionCookieStore = InMemorySessionCookieStore
@Provides fun provideOkHttpClientConfigurator(): Set<OkHttpClientConfigurator> = emptySet()
@Provides
fun provideLogger(): HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger { _ -> }
}
private object InMemorySessionCookieStore : SessionCookieStore {
private var cookie: String? = null
private var usernameValue: String? = null
private val loggedIn = MutableStateFlow(false)
private val usernameFlow = MutableStateFlow<String?>(null)
override fun get(): String? = cookie
override fun getUsername(): String? = usernameValue
override fun set(cookie: String, username: String) {
this.cookie = cookie
usernameValue = username
loggedIn.value = true
usernameFlow.value = username
}
override fun clear() {
cookie = null
usernameValue = null
loggedIn.value = false
usernameFlow.value = null
}
override fun isLoggedIn(): Flow<Boolean> = loggedIn
override fun username(): Flow<String?> = usernameFlow
}
@@ -1,26 +0,0 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.smoketests
import dev.msfjarvis.claw.api.LobstersApi
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.DependencyGraph
import dev.zacsweers.metro.createGraphFactory
@DependencyGraph(AppScope::class)
interface SmokeTestsGraph {
val lobstersApi: LobstersApi
val smokeProbeRunner: SmokeProbeRunner
@DependencyGraph.Factory
fun interface Factory {
fun create(): SmokeTestsGraph
}
}
fun createSmokeTestsGraph(): SmokeTestsGraph =
createGraphFactory<SmokeTestsGraph.Factory>().create()