Add skipped rounds info
This commit is contained in:
19
test.sh
19
test.sh
@@ -1,19 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
curl -s --header "Accept: application/json" --header "Content-Type: application/json" \
|
||||
--request POST \
|
||||
--data '{ "type":"INDIVIDUAL","name":"Mon Tournoi", "shortName": "mon-tournoi", "startDate": "2023-05-10", "endDate": "2023-05-12", "country": "FR", "location": "Marseille", "online": false, "timeSystem": { "type": "fisher", "mainTime": "1200", "increment": "10" }, "pairing": { "type": "ROUNDROBIN" } }' \
|
||||
http://localhost:8080/api/tour
|
||||
|
||||
curl -s --header "Accept: application/json" http://localhost:8080/api/tour
|
||||
|
||||
curl -s --header "Accept: application/json" http://localhost:8080/api/tour/1
|
||||
|
||||
curl -s --header "Accept: application/json" --header "Content-Type: application/json" \
|
||||
--request POST \
|
||||
--data '{ "name": "Burma", "firstname": "Nestor", "rating": 1600, "rank": -2, "country": "FR", "club": "13Ma" }' \
|
||||
http://localhost:8080/api/tour/1/part
|
||||
|
||||
curl -s --header "Accept: application/json" http://localhost:8080/api/tour/1/part
|
||||
|
||||
|
||||
#mvn -Dorg.slf4j.simpleLogger.log.test=trace package verify
|
||||
mvn package verify
|
||||
|
@@ -97,6 +97,11 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<classpathDependencyExcludes>
|
||||
<classpathDependencyExclude>com.republicate:webapp-slf4j-logger</classpathDependencyExclude>
|
||||
</classpathDependencyExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
@@ -169,6 +174,12 @@
|
||||
<version>3.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@@ -8,7 +8,7 @@ import kotlin.math.roundToInt
|
||||
|
||||
// Pairable
|
||||
|
||||
sealed class Pairable(val id: Int, val name: String, open val rating: Double, open val rank: Int) {
|
||||
sealed class Pairable(val id: Int, val name: String, open val rating: Int, open val rank: Int) {
|
||||
abstract fun toJson(): Json.Object
|
||||
val skip = mutableSetOf<Int>() // skipped rounds
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class Player(
|
||||
id: Int,
|
||||
name: String,
|
||||
var firstname: String,
|
||||
rating: Double,
|
||||
rating: Int,
|
||||
rank: Int,
|
||||
var country: String,
|
||||
var club: String
|
||||
@@ -48,7 +48,7 @@ class Player(
|
||||
companion object
|
||||
// used to store external IDs ("FFG" => FFG ID, "EGF" => EGF PIN, "AGA" => AGA ID ...)
|
||||
val externalIds = mutableMapOf<String, String>()
|
||||
override fun toJson() = Json.Object(
|
||||
override fun toJson(): Json.Object = Json.MutableObject(
|
||||
"id" to id,
|
||||
"name" to name,
|
||||
"firstname" to firstname,
|
||||
@@ -56,25 +56,32 @@ class Player(
|
||||
"rank" to rank,
|
||||
"country" to country,
|
||||
"club" to club
|
||||
)
|
||||
).also {
|
||||
if (skip.isNotEmpty()) it["skip"] = Json.Array(skip)
|
||||
}
|
||||
}
|
||||
|
||||
fun Player.Companion.fromJson(json: Json.Object, default: Player? = null) = Player(
|
||||
id = json.getInt("id") ?: default?.id ?: Store.nextPlayerId,
|
||||
name = json.getString("name") ?: default?.name ?: badRequest("missing name"),
|
||||
firstname = json.getString("firstname") ?: default?.firstname ?: badRequest("missing firstname"),
|
||||
rating = json.getDouble("rating") ?: default?.rating ?: badRequest("missing rating"),
|
||||
rating = json.getInt("rating") ?: default?.rating ?: badRequest("missing rating"),
|
||||
rank = json.getInt("rank") ?: default?.rank ?: badRequest("missing rank"),
|
||||
country = json.getString("country") ?: default?.country ?: badRequest("missing country"),
|
||||
club = json.getString("club") ?: default?.club ?: badRequest("missing club")
|
||||
)
|
||||
).also { player ->
|
||||
player.skip.clear()
|
||||
json.getArray("skip")?.let {
|
||||
if (it.isNotEmpty()) player.skip.addAll(it.map { id -> (id as Number).toInt() })
|
||||
}
|
||||
}
|
||||
|
||||
// Team
|
||||
|
||||
class Team(id: Int, name: String): Pairable(id, name, 0.0, 0) {
|
||||
class Team(id: Int, name: String): Pairable(id, name, 0, 0) {
|
||||
companion object {}
|
||||
val players = mutableSetOf<Player>()
|
||||
override val rating: Double get() = if (players.isEmpty()) super.rating else players.sumOf { player -> player.rating } / players.size
|
||||
override val rating: Int get() = if (players.isEmpty()) super.rating else (players.sumOf { player -> player.rating.toDouble() } / players.size).roundToInt()
|
||||
override val rank: Int get() = if (players.isEmpty()) super.rank else (players.sumOf { player -> player.rank.toDouble() } / players.size).roundToInt()
|
||||
override fun toJson() = Json.Object(
|
||||
"id" to id,
|
||||
|
@@ -114,9 +114,9 @@ class ApiServlet : HttpServlet() {
|
||||
builder.append(response.status).append(' ')
|
||||
.append(reason)
|
||||
if (response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
|
||||
logger.info(red(">> {}"), builder.toString())
|
||||
logger.trace(red(">> {}"), builder.toString())
|
||||
} else {
|
||||
logger.info(green(">> {}"), builder.toString())
|
||||
logger.trace(green(">> {}"), builder.toString())
|
||||
}
|
||||
|
||||
// CB TODO - should be bufferized and asynchronously written in synchronous chunks
|
||||
|
@@ -25,7 +25,7 @@ fun Logger.logRequest(req: HttpServletRequest, logHeaders: Boolean = false) {
|
||||
}
|
||||
// builder.append(' ').append(req.getProtocol());
|
||||
info(blue("<< {}"), builder.toString())
|
||||
if (logHeaders) {
|
||||
if (isTraceEnabled && logHeaders) {
|
||||
// CB TODO - should be bufferized and asynchronously written in synchronous chunks
|
||||
// so that header lines from parallel requests are not mixed up in the logs ;
|
||||
// synchronizing the whole request log is not desirable
|
||||
@@ -33,7 +33,7 @@ fun Logger.logRequest(req: HttpServletRequest, logHeaders: Boolean = false) {
|
||||
while (headerNames.hasMoreElements()) {
|
||||
val name = headerNames.nextElement()
|
||||
val value = req.getHeader(name)
|
||||
info(blue("<< {}: {}"), name, value)
|
||||
trace(blue("<< {}: {}"), name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ import kotlin.test.assertTrue
|
||||
|
||||
@TestMethodOrder(Alphanumeric::class)
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class BasicTests() {
|
||||
class BasicTests: TestBase() {
|
||||
|
||||
val aTournament = Json.Object(
|
||||
"type" to "INDIVIDUAL",
|
||||
@@ -32,20 +32,47 @@ class BasicTests() {
|
||||
)
|
||||
)
|
||||
|
||||
val aPlayer = Json.Object(
|
||||
"name" to "Burma",
|
||||
"firstname" to "Nestor",
|
||||
"rating" to 1600,
|
||||
"rank" to -2,
|
||||
"country" to "FR",
|
||||
"club" to "13Ma"
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `001 create tournament`() {
|
||||
val resp = TestAPI.post("/api/tour", aTournament)
|
||||
assertTrue(resp.isObject, "Json object expected")
|
||||
assertTrue(resp.asObject().getBoolean("success") == true, "expecting success")
|
||||
val resp = TestAPI.post("/api/tour", aTournament) as Json.Object
|
||||
assertTrue(resp.getBoolean("success") == true, "expecting success")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `002 get tournament`() {
|
||||
val resp = TestAPI.get("/api/tour/1")
|
||||
assertTrue(resp.isObject, "Json object expected")
|
||||
assertEquals(1, resp.asObject().getInt("id"), "First tournament should have id #1")
|
||||
val resp = TestAPI.get("/api/tour/1") as Json.Object
|
||||
assertEquals(1, resp.getInt("id"), "First tournament should have id #1")
|
||||
// filter out "id", and also "komi", "rules" and "gobanSize" which were provided by default
|
||||
val cmp = Json.Object(*resp.asObject().entries.filter { it.key !in listOf("id", "komi", "rules", "gobanSize") }.map { Pair(it.key, it.value) }.toTypedArray())
|
||||
val cmp = Json.Object(*resp.entries.filter { it.key !in listOf("id", "komi", "rules", "gobanSize") }.map { Pair(it.key, it.value) }.toTypedArray())
|
||||
assertEquals(aTournament.toString(), cmp.toString(), "tournament differs")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `003 register user`() {
|
||||
val resp = TestAPI.post("/api/tour/1/part", aPlayer) as Json.Object
|
||||
assertTrue(resp.getBoolean("success") == true, "expecting success")
|
||||
val players = TestAPI.get("/api/tour/1/part") as Json.Array
|
||||
val player = players[0] as Json.Object
|
||||
assertEquals(1, player.getInt("id"), "First player should have id #1")
|
||||
// filter out "id"
|
||||
val cmp = Json.Object(*player.entries.filter { it.key != "id" }.map { Pair(it.key, it.value) }.toTypedArray())
|
||||
assertEquals(aPlayer.toString(), cmp.toString(), "player differs")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `004 modify user`() {
|
||||
val resp = TestAPI.put("/api/tour/1/part/1", Json.Object("skip" to Json.Array(1))) as Json.Object
|
||||
assertTrue(resp.getBoolean("success") == true, "expecting success")
|
||||
val player = TestAPI.get("/api/tour/1/part/1") as Json.Object
|
||||
assertEquals("[1]", player.getArray("skip").toString(), "First player should have id #1")
|
||||
}
|
||||
}
|
||||
|
25
webapp/src/test/kotlin/TestBase.kt
Normal file
25
webapp/src/test/kotlin/TestBase.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package org.jeudego.pairgoth.test
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.TestInfo
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
abstract class TestBase {
|
||||
companion object {
|
||||
val logger = LoggerFactory.getLogger("test")
|
||||
private var testClassName: String? = null
|
||||
|
||||
@BeforeAll
|
||||
@JvmStatic
|
||||
fun prepare() {
|
||||
testClassName = this::class.simpleName
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun before(testInfo: TestInfo) {
|
||||
val testName = testInfo.displayName.removeSuffix("()")
|
||||
logger.info("===== Running $testClassName.$testName =====")
|
||||
}
|
||||
}
|
@@ -40,9 +40,9 @@ object TestAPI {
|
||||
on { setAttribute(eq(ApiHandler.SELECTOR_KEY), selector.capture()) } doAnswer {}
|
||||
on { setAttribute(eq(ApiHandler.SUBSELECTOR_KEY), subSelector.capture()) } doAnswer {}
|
||||
on { setAttribute(eq(ApiHandler.PAYLOAD_KEY), reqPayload.capture()) } doAnswer {}
|
||||
on { getAttribute(ApiHandler.SELECTOR_KEY) } doAnswer { selector.lastValue }
|
||||
on { getAttribute(ApiHandler.SUBSELECTOR_KEY) } doAnswer { subSelector.lastValue }
|
||||
on { getAttribute(ApiHandler.PAYLOAD_KEY) } doAnswer { reqPayload.lastValue }
|
||||
on { getAttribute(ApiHandler.SELECTOR_KEY) } doAnswer { selector.allValues.lastOrNull() }
|
||||
on { getAttribute(ApiHandler.SUBSELECTOR_KEY) } doAnswer { subSelector.allValues.lastOrNull() }
|
||||
on { getAttribute(ApiHandler.PAYLOAD_KEY) } doAnswer { reqPayload.allValues.lastOrNull() }
|
||||
on { reader } doReturn myReader
|
||||
on { scheme } doReturn "http"
|
||||
on { localName } doReturn "pairgoth"
|
||||
|
Reference in New Issue
Block a user