From 16a783146c46916c341eb5e4e8e65cbc7fe457a7 Mon Sep 17 00:00:00 2001 From: sanao1006 Date: Fri, 19 Jan 2024 17:24:13 +0900 Subject: [PATCH 01/13] refactor: migrating from the `org.json` Library to `Gson` Fixed #236 --- gradle/libs.versions.toml | 4 +- include-build/roborazzi-core/build.gradle | 4 +- .../takahirom/roborazzi/CaptureResult.kt | 68 +++++++++---------- .../takahirom/roborazzi/CaptureResults.kt | 32 ++++----- .../takahirom/roborazzi/ResultSummary.kt | 28 ++++---- .../takahirom/roborazzi/CaptureResultTest.kt | 43 ++++++------ .../roborazzi-gradle-plugin/build.gradle | 2 +- roborazzi-compose-desktop/build.gradle | 2 +- 8 files changed, 92 insertions(+), 91 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c6c8fae6..2e27d71e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ androidx-test-ext-junit = "1.1.5" dropbox-differ = "0.0.1" google-android-material = "1.5.0" -json = "20231013" +gson = "2.10.1" junit = "4.13.2" ktor-serialization-kotlinx-xml = "2.3.0" squareup-okhttp = "5.0.0-alpha.11" @@ -77,7 +77,7 @@ compose-ui-graphics-desktop = { module = "org.jetbrains.compose.ui:ui-graphics-d compose-ui-test-junit4-desktop = { module = "org.jetbrains.compose.ui:ui-test-junit4-desktop", version.ref = "composeDesktop" } dropbox-differ = { module = "com.dropbox.differ:differ", version.ref = "dropbox-differ" } google-android-material = { module = "com.google.android.material:material", version.ref = "google-android-material" } -json = { module = "org.json:json", version.ref = "json" } +gson = { module = "com.google.code.gson:gson", version.ref = "gson"} junit = { module = "junit:junit", version.ref = "junit" } ktor-serialization-kotlinx-xml = { module = "io.ktor:ktor-serialization-kotlinx-xml", version.ref = "ktor-serialization-kotlinx-xml" } squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "squareup-okhttp" } diff --git a/include-build/roborazzi-core/build.gradle b/include-build/roborazzi-core/build.gradle index 5dd4152f..3216d0c7 100644 --- a/include-build/roborazzi-core/build.gradle +++ b/include-build/roborazzi-core/build.gradle @@ -32,7 +32,7 @@ kotlin { } commonJvmMain { dependencies { - compileOnly libs.json + compileOnly libs.gson api libs.dropbox.differ implementation libs.junit } @@ -46,7 +46,7 @@ kotlin { } jvmMain { dependencies { - implementation libs.json + implementation libs.gson } } jvmTest { diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index 0a8380ec..3170d81e 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -1,11 +1,12 @@ package com.github.takahirom.roborazzi +import com.google.gson.Gson +import com.google.gson.JsonObject import java.io.File import java.io.FileReader -import org.json.JSONObject sealed interface CaptureResult { - fun toJson(): JSONObject + fun toJson(): JsonObject val timestampNs: Long val compareFile: File? val actualFile: File? @@ -20,11 +21,11 @@ sealed interface CaptureResult { override val compareFile: File? get() = null - override fun toJson(): JSONObject { - val json = JSONObject() - json.put("type", "recorded") - json.put("golden_file_path", goldenFile.absolutePath) - json.put("timestamp", timestampNs) + override fun toJson(): JsonObject { + val json = JsonObject() + json.addProperty("type", "recorded") + json.addProperty("golden_file_path", goldenFile.absolutePath) + json.addProperty("timestamp", timestampNs) return json } } @@ -35,13 +36,13 @@ sealed interface CaptureResult { override val goldenFile: File, override val timestampNs: Long, ) : CaptureResult { - override fun toJson(): JSONObject { - val json = JSONObject() - json.put("type", "added") - json.put("compare_file_path", compareFile.absolutePath) - json.put("actual_file_path", actualFile.absolutePath) - json.put("golden_file_path", goldenFile.absolutePath) - json.put("timestamp", timestampNs) + override fun toJson(): JsonObject { + val json = JsonObject() + json.addProperty("type", "added") + json.addProperty("compare_file_path", compareFile.absolutePath) + json.addProperty("actual_file_path", actualFile.absolutePath) + json.addProperty("golden_file_path", goldenFile.absolutePath) + json.addProperty("timestamp", timestampNs) return json } } @@ -52,13 +53,13 @@ sealed interface CaptureResult { override val actualFile: File, override val timestampNs: Long ) : CaptureResult { - override fun toJson(): JSONObject { - val json = JSONObject() - json.put("type", "changed") - json.put("compare_file_path", compareFile.absolutePath) - json.put("actual_file_path", actualFile.absolutePath) - json.put("golden_file_path", goldenFile.absolutePath) - json.put("timestamp", timestampNs) + override fun toJson(): JsonObject { + val json = JsonObject() + json.addProperty("type", "changed") + json.addProperty("compare_file_path", compareFile.absolutePath) + json.addProperty("actual_file_path", actualFile.absolutePath) + json.addProperty("golden_file_path", goldenFile.absolutePath) + json.addProperty("timestamp", timestampNs) return json } } @@ -72,27 +73,26 @@ sealed interface CaptureResult { override val compareFile: File? get() = null - override fun toJson(): JSONObject { - val json = JSONObject() - json.put("type", "unchanged") - json.put("golden_file_path", goldenFile.absolutePath) - json.put("timestamp", timestampNs) + override fun toJson(): JsonObject { + val json = JsonObject() + json.addProperty("type", "unchanged") + json.addProperty("golden_file_path", goldenFile.absolutePath) + json.addProperty("timestamp", timestampNs) return json } } companion object { fun fromJsonFile(inputPath: String): CaptureResult { - val json = JSONObject(FileReader(inputPath).readText()) - return fromJson(json) + return Gson().fromJson(FileReader(inputPath).readText(), CaptureResult::class.java) } - fun fromJson(json: JSONObject): CaptureResult { - val type = json.getString("type") - val compareFile = json.optString("compare_file_path")?.let { File(it) } - val goldenFile = json.optString("golden_file_path")?.let { File(it) } - val actualFile = json.optString("actual_file_path")?.let { File(it) } - val timestampNs = json.getLong("timestamp") + fun fromJson(json: JsonObject): CaptureResult { + val type = json.get("type").asString + val compareFile = json.get("compare_file_path")?.asString?.let{ File(it) } + val goldenFile = json.get("golden_file_path")?.asString?.let{ File(it) } + val actualFile = json.get("actual_file_path")?.asString?.let{ File(it) } + val timestampNs = json.get("timestamp").asLong return when (type) { "recorded" -> Recorded( diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index bb265c53..0b3fbea9 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -1,21 +1,23 @@ package com.github.takahirom.roborazzi -import org.json.JSONArray -import org.json.JSONObject +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonObject import java.io.File +import java.io.FileReader data class CaptureResults( val summary: ResultSummary, val captureResults: List ) { - fun toJson(): JSONObject { - val json = JSONObject() - json.put("summary", summary.toJson()) - val resultsArray = JSONArray() + fun toJson(): JsonObject { + val json = JsonObject() + json.add("summary", summary.toJson()) + val resultsArray = JsonArray() captureResults.forEach { result -> - resultsArray.put(result.toJson()) + resultsArray.add(result.toJson()) } - json.put("results", resultsArray) + json.add("results", resultsArray) return json } @@ -88,17 +90,15 @@ data class CaptureResults( companion object { fun fromJsonFile(inputPath: String): CaptureResults { - val fileContents = File(inputPath).readText() - val jsonObject = JSONObject(fileContents) - return fromJson(jsonObject) + return Gson().fromJson(FileReader(inputPath).readText(), CaptureResults::class.java) } - fun fromJson(jsonObject: JSONObject): CaptureResults { - val summary = ResultSummary.fromJson(jsonObject.getJSONObject("summary")) - val resultsArray = jsonObject.getJSONArray("results") + fun fromJson(jsonObject: JsonObject): CaptureResults { + val summary = ResultSummary.fromJson(jsonObject.get("summary").asJsonObject) + val resultsArray = jsonObject.get("results").asJsonArray val captureResults = mutableListOf() - for (i in 0 until resultsArray.length()) { - val resultJson = resultsArray.getJSONObject(i) + for (i in 0 until resultsArray.size()) { + val resultJson = resultsArray.get(i).asJsonObject captureResults.add(CaptureResult.fromJson(resultJson)) } return CaptureResults(summary, captureResults) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt index 7e1d1bed..ea4c7483 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt @@ -1,6 +1,6 @@ package com.github.takahirom.roborazzi -import org.json.JSONObject +import com.google.gson.JsonObject data class ResultSummary( val total: Int, @@ -9,13 +9,13 @@ data class ResultSummary( val changed: Int, val unchanged: Int ) { - fun toJson(): JSONObject { - val json = JSONObject() - json.put("total", total) - json.put("recorded", recorded) - json.put("added", added) - json.put("changed", changed) - json.put("unchanged", unchanged) + fun toJson(): JsonObject { + val json = JsonObject() + json.addProperty("total", total) + json.addProperty("recorded", recorded) + json.addProperty("added", added) + json.addProperty("changed", changed) + json.addProperty("unchanged", unchanged) return json } @@ -46,12 +46,12 @@ data class ResultSummary( } companion object { - fun fromJson(jsonObject: JSONObject): ResultSummary { - val total = jsonObject.getInt("total") - val recorded = jsonObject.getInt("recorded") - val added = jsonObject.getInt("added") - val changed = jsonObject.getInt("changed") - val unchanged = jsonObject.getInt("unchanged") + fun fromJson(jsonObject: JsonObject): ResultSummary { + val total = jsonObject.get("total").asInt + val recorded = jsonObject.get("recorded").asInt + val added = jsonObject.get("added").asInt + val changed = jsonObject.get("changed").asInt + val unchanged = jsonObject.get("unchanged").asInt return ResultSummary( total = total, recorded = recorded, diff --git a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt index b552bae7..222a35e5 100644 --- a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt +++ b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt @@ -3,7 +3,7 @@ package io.github.takahirom.roborazzi import com.github.takahirom.roborazzi.CaptureResult import com.github.takahirom.roborazzi.CaptureResults import com.github.takahirom.roborazzi.ResultSummary -import org.json.JSONObject +import com.google.gson.JsonParser import org.junit.Assert.assertEquals import org.junit.Test import java.io.File @@ -39,35 +39,35 @@ class CaptureResultTest { val compareReportResult = CaptureResults(summary, captureResults) val json = compareReportResult.toJson() - val jsonSummary = json.getJSONObject("summary") - val jsonResults = json.getJSONArray("results") + val jsonSummary = json.get("summary").asJsonObject + val jsonResults = json.get("results").asJsonArray // Test summary - assertEquals(summary.total, jsonSummary.getInt("total")) - assertEquals(summary.recorded, jsonSummary.getInt("recorded")) - assertEquals(summary.added, jsonSummary.getInt("added")) - assertEquals(summary.changed, jsonSummary.getInt("changed")) - assertEquals(summary.unchanged, jsonSummary.getInt("unchanged")) + assertEquals(summary.total, jsonSummary.get("total").asInt) + assertEquals(summary.recorded, jsonSummary.get("recorded").asInt) + assertEquals(summary.added, jsonSummary.get("added").asInt) + assertEquals(summary.changed, jsonSummary.get("changed").asInt) + assertEquals(summary.unchanged, jsonSummary.get("unchanged").asInt) // Test capture results - assertEquals(captureResults.size, jsonResults.length()) + assertEquals(captureResults.size, jsonResults.size()) - for (i in 0 until jsonResults.length()) { - val jsonResult = jsonResults.getJSONObject(i) + for (i in 0 until jsonResults.size()) { + val jsonResult = jsonResults.get(i).asJsonObject val captureResult = captureResults[i] assertEquals( - captureResult.compareFile?.absolutePath, jsonResult.optString("compare_file_path", null) + captureResult.compareFile?.absolutePath, jsonResult.get("compare_file_path")?.asString ) assertEquals( captureResult.goldenFile?.absolutePath, - jsonResult.optString("golden_file_path", null) + jsonResult.get("golden_file_path")?.asString ) assertEquals( captureResult.actualFile?.absolutePath, - jsonResult.optString("actual_file_path", null) + jsonResult.get("actual_file_path")?.asString ) - assertEquals(captureResult.timestampNs, jsonResult.getLong("timestamp")) + assertEquals(captureResult.timestampNs, jsonResult.get("timestamp").asLong) } } @@ -86,31 +86,32 @@ class CaptureResultTest { { "type": "recorded", "golden_file_path": "golden_file", - "timestamp": 123456789, + "timestamp": 123456789 }, { "type": "added", "compare_file_path": "compare_file", "actual_file_path": "actual_file", - "timestamp": 123456789, + "golden_file_path": "golden_file", + "timestamp": 123456789 }, { "type": "changed", "compare_file_path": "compare_file", "actual_file_path": "actual_file", "golden_file_path": "golden_file", - "timestamp": 123456789, + "timestamp": 123456789 }, { "type": "unchanged", "golden_file_path": "golden_file", - "timestamp": 123456789, + "timestamp": 123456789 } ] } """.trimIndent() - - val compareReportResult = CaptureResults.fromJson(JSONObject(jsonString)) + val jsonObject = JsonParser.parseString(jsonString).asJsonObject + val compareReportResult = CaptureResults.fromJson(jsonObject) val summary = compareReportResult.summary val captureResults = compareReportResult.captureResults diff --git a/include-build/roborazzi-gradle-plugin/build.gradle b/include-build/roborazzi-gradle-plugin/build.gradle index 34e6aed6..3105dbe6 100644 --- a/include-build/roborazzi-gradle-plugin/build.gradle +++ b/include-build/roborazzi-gradle-plugin/build.gradle @@ -24,7 +24,7 @@ dependencies { // We don't use junit for plugin exclude group: 'junit', module: 'junit' } - implementation libs.json + implementation libs.gson integrationTestDepImplementation libs.android.tools.build.gradle integrationTestDepImplementation libs.kotlin.gradle.plugin integrationTestDepImplementation libs.compose.gradle.plugin diff --git a/roborazzi-compose-desktop/build.gradle b/roborazzi-compose-desktop/build.gradle index 63c1f1cd..8aad831c 100644 --- a/roborazzi-compose-desktop/build.gradle +++ b/roborazzi-compose-desktop/build.gradle @@ -21,7 +21,7 @@ kotlin { dependencies { // Please see settings.gradle api "io.github.takahirom.roborazzi:roborazzi-core:$VERSION_NAME" - implementation libs.json + implementation libs.gson implementation(compose.runtime) implementation(compose.desktop.currentOs) From de07c601fd41e6257be7bf0d825ac60758e9509e Mon Sep 17 00:00:00 2001 From: sanao1006 Date: Mon, 22 Jan 2024 13:19:42 +0900 Subject: [PATCH 02/13] fix: Change `toJson()` to use auto mapping Fixed #236 --- .../takahirom/roborazzi/CaptureResult.kt | 49 ++++++++++--------- .../takahirom/roborazzi/CaptureResults.kt | 19 +++---- .../takahirom/roborazzi/ResultSummary.kt | 10 ++-- .../takahirom/roborazzi/CaptureResultTest.kt | 2 +- .../roborazzi/RoborazziGradleProject.kt | 16 +++--- 5 files changed, 45 insertions(+), 51 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index 3170d81e..e4b2f725 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -2,6 +2,7 @@ package com.github.takahirom.roborazzi import com.google.gson.Gson import com.google.gson.JsonObject +import com.google.gson.JsonParser import java.io.File import java.io.FileReader @@ -22,11 +23,11 @@ sealed interface CaptureResult { get() = null override fun toJson(): JsonObject { - val json = JsonObject() - json.addProperty("type", "recorded") - json.addProperty("golden_file_path", goldenFile.absolutePath) - json.addProperty("timestamp", timestampNs) - return json + val recorded = object { + val golden_file_path = goldenFile.absolutePath + val timestamp = timestampNs + } + return JsonParser.parseString(Gson().toJson(recorded)).asJsonObject } } @@ -37,13 +38,13 @@ sealed interface CaptureResult { override val timestampNs: Long, ) : CaptureResult { override fun toJson(): JsonObject { - val json = JsonObject() - json.addProperty("type", "added") - json.addProperty("compare_file_path", compareFile.absolutePath) - json.addProperty("actual_file_path", actualFile.absolutePath) - json.addProperty("golden_file_path", goldenFile.absolutePath) - json.addProperty("timestamp", timestampNs) - return json + val added = object { + val compare_file_path: String = compareFile.absolutePath + val actual_file_path: String = actualFile.absolutePath + val golden_file_path: String = goldenFile.absolutePath + val timestamp: Long = timestampNs + } + return JsonParser.parseString(Gson().toJson(added)).asJsonObject } } @@ -54,13 +55,13 @@ sealed interface CaptureResult { override val timestampNs: Long ) : CaptureResult { override fun toJson(): JsonObject { - val json = JsonObject() - json.addProperty("type", "changed") - json.addProperty("compare_file_path", compareFile.absolutePath) - json.addProperty("actual_file_path", actualFile.absolutePath) - json.addProperty("golden_file_path", goldenFile.absolutePath) - json.addProperty("timestamp", timestampNs) - return json + val changed = object { + val compare_file_path: String = compareFile.absolutePath + val actual_file_path: String = actualFile.absolutePath + val golden_file_path: String = goldenFile.absolutePath + val timestamp: Long = timestampNs + } + return JsonParser.parseString(Gson().toJson(changed)).asJsonObject } } @@ -74,11 +75,11 @@ sealed interface CaptureResult { get() = null override fun toJson(): JsonObject { - val json = JsonObject() - json.addProperty("type", "unchanged") - json.addProperty("golden_file_path", goldenFile.absolutePath) - json.addProperty("timestamp", timestampNs) - return json + val unChanged = object { + val golden_file_path: String = goldenFile.absolutePath + val timestamp: Long = timestampNs + } + return JsonParser.parseString(Gson().toJson(unChanged)).asJsonObject } } diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 0b3fbea9..25aaded0 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -1,24 +1,21 @@ package com.github.takahirom.roborazzi import com.google.gson.Gson -import com.google.gson.JsonArray import com.google.gson.JsonObject +import com.google.gson.JsonParser import java.io.File import java.io.FileReader data class CaptureResults( - val summary: ResultSummary, + val resultSummary: ResultSummary, val captureResults: List ) { fun toJson(): JsonObject { - val json = JsonObject() - json.add("summary", summary.toJson()) - val resultsArray = JsonArray() - captureResults.forEach { result -> - resultsArray.add(result.toJson()) + val captureResultsObject = object { + val summary = resultSummary + val results = captureResults.map { it.toJson() } } - json.add("results", resultsArray) - return json + return JsonParser.parseString(Gson().toJson(captureResultsObject)).asJsonObject } fun toHtml(reportDirectoryPath: String): String { @@ -80,7 +77,7 @@ data class CaptureResults( } } return buildString { - append(summary.toHtml()) + append(resultSummary.toHtml()) append(buildTable("Recorded images", "recorded", recordedImages)) append(buildTable("Added images", "added", addedImages)) append(buildTable("Changed images", "changed", changedImages)) @@ -106,7 +103,7 @@ data class CaptureResults( fun from(results: List): CaptureResults { return CaptureResults( - summary = ResultSummary( + resultSummary = ResultSummary( total = results.size, recorded = results.count { it is CaptureResult.Recorded }, added = results.count { it is CaptureResult.Added }, diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt index ea4c7483..5548e180 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt @@ -1,6 +1,8 @@ package com.github.takahirom.roborazzi +import com.google.gson.Gson import com.google.gson.JsonObject +import com.google.gson.JsonParser data class ResultSummary( val total: Int, @@ -10,13 +12,7 @@ data class ResultSummary( val unchanged: Int ) { fun toJson(): JsonObject { - val json = JsonObject() - json.addProperty("total", total) - json.addProperty("recorded", recorded) - json.addProperty("added", added) - json.addProperty("changed", changed) - json.addProperty("unchanged", unchanged) - return json + return JsonParser.parseString(Gson().toJson(this)).asJsonObject } fun toHtml(): String { diff --git a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt index 222a35e5..825b01bd 100644 --- a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt +++ b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt @@ -112,7 +112,7 @@ class CaptureResultTest { """.trimIndent() val jsonObject = JsonParser.parseString(jsonString).asJsonObject val compareReportResult = CaptureResults.fromJson(jsonObject) - val summary = compareReportResult.summary + val summary = compareReportResult.resultSummary val captureResults = compareReportResult.captureResults // Test summary diff --git a/include-build/roborazzi-gradle-plugin/src/integrationTest/java/io/github/takahirom/roborazzi/RoborazziGradleProject.kt b/include-build/roborazzi-gradle-plugin/src/integrationTest/java/io/github/takahirom/roborazzi/RoborazziGradleProject.kt index cf49163c..f72497da 100644 --- a/include-build/roborazzi-gradle-plugin/src/integrationTest/java/io/github/takahirom/roborazzi/RoborazziGradleProject.kt +++ b/include-build/roborazzi-gradle-plugin/src/integrationTest/java/io/github/takahirom/roborazzi/RoborazziGradleProject.kt @@ -302,17 +302,17 @@ dependencies { val recordedFile = testProjectDir.root.resolve("app/build/test-results/roborazzi/results-summary.json") val resutls = CaptureResults.fromJsonFile(recordedFile.absolutePath) - assert(resutls.summary.recorded == recorded) { - "Expected count: $recorded, actual count: ${resutls.summary.recorded} summary:${resutls.summary}" + assert(resutls.resultSummary.recorded == recorded) { + "Expected count: $recorded, actual count: ${resutls.resultSummary.recorded} summary:${resutls.resultSummary}" } - assert(resutls.summary.added == added) { - "Expected count: $added, actual count: ${resutls.summary.added} summary:${resutls.summary}" + assert(resutls.resultSummary.added == added) { + "Expected count: $added, actual count: ${resutls.resultSummary.added} summary:${resutls.resultSummary}" } - assert(resutls.summary.changed == changed) { - "Expected count: $changed, actual count: ${resutls.summary.changed} summary:${resutls.summary}" + assert(resutls.resultSummary.changed == changed) { + "Expected count: $changed, actual count: ${resutls.resultSummary.changed} summary:${resutls.resultSummary}" } - assert(resutls.summary.unchanged == unchanged) { - "Expected count: $unchanged, actual count: ${resutls.summary.unchanged} summary:${resutls.summary}" + assert(resutls.resultSummary.unchanged == unchanged) { + "Expected count: $unchanged, actual count: ${resutls.resultSummary.unchanged} summary:${resutls.resultSummary}" } } From ebc39a7e510e325f1734fcc0a4652188b577b746 Mon Sep 17 00:00:00 2001 From: sanao1006 Date: Mon, 22 Jan 2024 15:31:57 +0900 Subject: [PATCH 03/13] fix: add gson in androidMain Fixed #236 --- include-build/roborazzi-core/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/include-build/roborazzi-core/build.gradle b/include-build/roborazzi-core/build.gradle index 3216d0c7..3d0dfb22 100644 --- a/include-build/roborazzi-core/build.gradle +++ b/include-build/roborazzi-core/build.gradle @@ -61,6 +61,7 @@ kotlin { compileOnly libs.androidx.compose.ui.test.junit4 api libs.androidx.test.espresso.core implementation libs.androidx.core.ktx + implementation libs.gson } } From 302d3adbe76e538afa6f79a3236c7946782aa64b Mon Sep 17 00:00:00 2001 From: sanao1006 Date: Mon, 22 Jan 2024 16:40:52 +0900 Subject: [PATCH 04/13] fix: fix `fromJsonFile()` Fixed #236 --- .../kotlin/com/github/takahirom/roborazzi/CaptureResults.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 25aaded0..75fa05bc 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -87,7 +87,8 @@ data class CaptureResults( companion object { fun fromJsonFile(inputPath: String): CaptureResults { - return Gson().fromJson(FileReader(inputPath).readText(), CaptureResults::class.java) + val jsonObject = JsonParser.parseString(FileReader(inputPath).readText()).asJsonObject + return fromJson(jsonObject) } fun fromJson(jsonObject: JsonObject): CaptureResults { From 4d937a8b21181447a0df70f62c659c73525626c1 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sat, 27 Jan 2024 18:35:48 +0900 Subject: [PATCH 05/13] Use automatic transform --- .../takahirom/roborazzi/CaptureResult.kt | 117 ++++++------------ .../takahirom/roborazzi/CaptureResults.kt | 39 +++--- .../takahirom/roborazzi/ResultSummary.kt | 25 ---- .../takahirom/roborazzi/RoborazziOptions.kt | 3 +- .../takahirom/roborazzi/CaptureResultTest.kt | 3 +- 5 files changed, 65 insertions(+), 122 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index e4b2f725..d943ded5 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -1,125 +1,88 @@ package com.github.takahirom.roborazzi -import com.google.gson.Gson -import com.google.gson.JsonObject -import com.google.gson.JsonParser +import com.google.gson.annotations.JsonAdapter +import com.google.gson.annotations.SerializedName import java.io.File -import java.io.FileReader +@JsonAdapter(CaptureResult.JsonAdapter::class) sealed interface CaptureResult { - fun toJson(): JsonObject val timestampNs: Long val compareFile: File? val actualFile: File? val goldenFile: File? data class Recorded( + @SerializedName("golden_file_path") override val goldenFile: File, + @SerializedName("timestamp") override val timestampNs: Long, ) : CaptureResult { override val actualFile: File? get() = null override val compareFile: File? get() = null - - override fun toJson(): JsonObject { - val recorded = object { - val golden_file_path = goldenFile.absolutePath - val timestamp = timestampNs - } - return JsonParser.parseString(Gson().toJson(recorded)).asJsonObject - } } data class Added( + @SerializedName("compare_file_path") override val compareFile: File, + @SerializedName("actual_file_path") override val actualFile: File, + @SerializedName("golden_file_path") override val goldenFile: File, + @SerializedName("timestamp") override val timestampNs: Long, - ) : CaptureResult { - override fun toJson(): JsonObject { - val added = object { - val compare_file_path: String = compareFile.absolutePath - val actual_file_path: String = actualFile.absolutePath - val golden_file_path: String = goldenFile.absolutePath - val timestamp: Long = timestampNs - } - return JsonParser.parseString(Gson().toJson(added)).asJsonObject - } - } + ) : CaptureResult data class Changed( + @SerializedName("compare_file_path") override val compareFile: File, + @SerializedName("golden_file_path") override val goldenFile: File, + @SerializedName("actual_file_path") override val actualFile: File, + @SerializedName("timestamp") override val timestampNs: Long - ) : CaptureResult { - override fun toJson(): JsonObject { - val changed = object { - val compare_file_path: String = compareFile.absolutePath - val actual_file_path: String = actualFile.absolutePath - val golden_file_path: String = goldenFile.absolutePath - val timestamp: Long = timestampNs - } - return JsonParser.parseString(Gson().toJson(changed)).asJsonObject - } - } + ) : CaptureResult data class Unchanged( + @SerializedName("golden_file_path") override val goldenFile: File, + @SerializedName("timestamp") override val timestampNs: Long ) : CaptureResult { override val actualFile: File? get() = null override val compareFile: File? get() = null - - override fun toJson(): JsonObject { - val unChanged = object { - val golden_file_path: String = goldenFile.absolutePath - val timestamp: Long = timestampNs - } - return JsonParser.parseString(Gson().toJson(unChanged)).asJsonObject - } } - companion object { - fun fromJsonFile(inputPath: String): CaptureResult { - return Gson().fromJson(FileReader(inputPath).readText(), CaptureResult::class.java) + companion object JsonAdapter : com.google.gson.JsonSerializer, + com.google.gson.JsonDeserializer { + override fun serialize( + src: CaptureResult, + typeOfSrc: java.lang.reflect.Type, + context: com.google.gson.JsonSerializationContext + ): com.google.gson.JsonElement { + return when (src) { + is Recorded -> context.serialize(src, Recorded::class.java) + is Changed -> context.serialize(src, Changed::class.java) + is Unchanged -> context.serialize(src, Unchanged::class.java) + is Added -> context.serialize(src, Added::class.java) + } } - fun fromJson(json: JsonObject): CaptureResult { - val type = json.get("type").asString - val compareFile = json.get("compare_file_path")?.asString?.let{ File(it) } - val goldenFile = json.get("golden_file_path")?.asString?.let{ File(it) } - val actualFile = json.get("actual_file_path")?.asString?.let{ File(it) } - val timestampNs = json.get("timestamp").asLong - + override fun deserialize( + json: com.google.gson.JsonElement, + typeOfT: java.lang.reflect.Type, + context: com.google.gson.JsonDeserializationContext + ): CaptureResult { + val type = json.asJsonObject.get("type").asString return when (type) { - "recorded" -> Recorded( - goldenFile = goldenFile!!, - timestampNs = timestampNs - ) - - "changed" -> Changed( - compareFile = compareFile!!, - goldenFile = goldenFile!!, - actualFile = actualFile!!, - timestampNs = timestampNs - ) - - "unchanged" -> Unchanged( - goldenFile = goldenFile!!, - timestampNs = timestampNs - ) - - "added" -> Added( - compareFile = compareFile!!, - actualFile = actualFile!!, - timestampNs = timestampNs, - goldenFile = goldenFile!!, - ) - + "recorded" -> context.deserialize(json, Recorded::class.java) + "changed" -> context.deserialize(json, Changed::class.java) + "unchanged" -> context.deserialize(json, Unchanged::class.java) + "added" -> context.deserialize(json, Added::class.java) else -> throw IllegalArgumentException("Unknown type $type") } } diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 75fa05bc..005f265e 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -1,22 +1,17 @@ package com.github.takahirom.roborazzi -import com.google.gson.Gson -import com.google.gson.JsonObject -import com.google.gson.JsonParser +import com.google.gson.* +import com.google.gson.annotations.SerializedName import java.io.File import java.io.FileReader +import java.lang.reflect.Type data class CaptureResults( + @SerializedName("summary") val resultSummary: ResultSummary, + @SerializedName("results") val captureResults: List ) { - fun toJson(): JsonObject { - val captureResultsObject = object { - val summary = resultSummary - val results = captureResults.map { it.toJson() } - } - return JsonParser.parseString(Gson().toJson(captureResultsObject)).asJsonObject - } fun toHtml(reportDirectoryPath: String): String { fun File.pathFrom(reportDirectoryPath: String): String { @@ -92,14 +87,8 @@ data class CaptureResults( } fun fromJson(jsonObject: JsonObject): CaptureResults { - val summary = ResultSummary.fromJson(jsonObject.get("summary").asJsonObject) - val resultsArray = jsonObject.get("results").asJsonArray - val captureResults = mutableListOf() - for (i in 0 until resultsArray.size()) { - val resultJson = resultsArray.get(i).asJsonObject - captureResults.add(CaptureResult.fromJson(resultJson)) - } - return CaptureResults(summary, captureResults) + // Auto convert using Gson + return gson.fromJson(jsonObject, CaptureResults::class.java) } fun from(results: List): CaptureResults { @@ -114,5 +103,19 @@ data class CaptureResults( captureResults = results ) } + + val gson = GsonBuilder() + .registerTypeAdapter(File::class.java, object : JsonSerializer, JsonDeserializer { + override fun serialize(src: File?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement { + val absolutePath = src?.absolutePath ?: return JsonNull.INSTANCE + return JsonPrimitive(absolutePath) + } + + override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): File { + val path = json?.asString ?: throw JsonParseException("File path is null") + return File(path) + } + }) + .create() } } diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt index 5548e180..0638414c 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/ResultSummary.kt @@ -1,9 +1,5 @@ package com.github.takahirom.roborazzi -import com.google.gson.Gson -import com.google.gson.JsonObject -import com.google.gson.JsonParser - data class ResultSummary( val total: Int, val recorded: Int, @@ -11,10 +7,6 @@ data class ResultSummary( val changed: Int, val unchanged: Int ) { - fun toJson(): JsonObject { - return JsonParser.parseString(Gson().toJson(this)).asJsonObject - } - fun toHtml(): String { return """

Summary

@@ -40,21 +32,4 @@ data class ResultSummary( """.trimIndent() } - - companion object { - fun fromJson(jsonObject: JsonObject): ResultSummary { - val total = jsonObject.get("total").asInt - val recorded = jsonObject.get("recorded").asInt - val added = jsonObject.get("added").asInt - val changed = jsonObject.get("changed").asInt - val unchanged = jsonObject.get("unchanged").asInt - return ResultSummary( - total = total, - recorded = recorded, - added = added, - changed = changed, - unchanged = unchanged - ) - } - } } \ No newline at end of file diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt index ef75f822..dc232449 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt @@ -2,6 +2,7 @@ package com.github.takahirom.roborazzi import com.dropbox.differ.ImageComparator import com.dropbox.differ.SimpleImageComparator +import com.github.takahirom.roborazzi.CaptureResults.Companion.gson import java.io.File import java.io.FileWriter @@ -241,7 +242,7 @@ data class RoborazziOptions( val reportFileName = "$absolutePath/${captureResult.timestampNs}_$nameWithoutExtension.json" - val jsonResult = captureResult.toJson() + val jsonResult = gson.toJson(captureResult) FileWriter(reportFileName).use { it.write(jsonResult.toString()) } debugLog { "JsonResult file($reportFileName) has been written" } } diff --git a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt index 825b01bd..bbb6ffee 100644 --- a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt +++ b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt @@ -2,6 +2,7 @@ package io.github.takahirom.roborazzi import com.github.takahirom.roborazzi.CaptureResult import com.github.takahirom.roborazzi.CaptureResults +import com.github.takahirom.roborazzi.CaptureResults.Companion.gson import com.github.takahirom.roborazzi.ResultSummary import com.google.gson.JsonParser import org.junit.Assert.assertEquals @@ -38,7 +39,7 @@ class CaptureResultTest { val compareReportResult = CaptureResults(summary, captureResults) - val json = compareReportResult.toJson() + val json = gson.toJsonTree(compareReportResult).asJsonObject val jsonSummary = json.get("summary").asJsonObject val jsonResults = json.get("results").asJsonArray From a0345d5b9f4e205a493a7d66dfe0e1488c1871b3 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sat, 27 Jan 2024 18:52:11 +0900 Subject: [PATCH 06/13] Fix plugin --- .../github/takahirom/roborazzi/CaptureResult.kt | 10 +++++++++- .../github/takahirom/roborazzi/CaptureResults.kt | 4 ++++ .../takahirom/roborazzi/RoborazziPlugin.kt | 16 ++++++---------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index d943ded5..4525ef9d 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -1,8 +1,10 @@ package com.github.takahirom.roborazzi +import com.github.takahirom.roborazzi.CaptureResults.Companion.gson import com.google.gson.annotations.JsonAdapter import com.google.gson.annotations.SerializedName import java.io.File +import java.io.FileReader @JsonAdapter(CaptureResult.JsonAdapter::class) sealed interface CaptureResult { @@ -57,7 +59,13 @@ sealed interface CaptureResult { get() = null } - companion object JsonAdapter : com.google.gson.JsonSerializer, + companion object { + fun fromJsonFile(filePath: String): CaptureResult { + return gson.fromJson(FileReader(filePath), CaptureResult::class.java) + } + } + + object JsonAdapter : com.google.gson.JsonSerializer, com.google.gson.JsonDeserializer { override fun serialize( src: CaptureResult, diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 005f265e..997bce1d 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -13,6 +13,10 @@ data class CaptureResults( val captureResults: List ) { + fun toJson(): String { + return gson.toJson(this) + } + fun toHtml(reportDirectoryPath: String): String { fun File.pathFrom(reportDirectoryPath: String): String { val reportDirectory = File(reportDirectoryPath) diff --git a/include-build/roborazzi-gradle-plugin/src/main/java/io/github/takahirom/roborazzi/RoborazziPlugin.kt b/include-build/roborazzi-gradle-plugin/src/main/java/io/github/takahirom/roborazzi/RoborazziPlugin.kt index 92e45a24..647c1467 100644 --- a/include-build/roborazzi-gradle-plugin/src/main/java/io/github/takahirom/roborazzi/RoborazziPlugin.kt +++ b/include-build/roborazzi-gradle-plugin/src/main/java/io/github/takahirom/roborazzi/RoborazziPlugin.kt @@ -6,11 +6,7 @@ import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.github.takahirom.roborazzi.CaptureResult import com.github.takahirom.roborazzi.CaptureResults import com.github.takahirom.roborazzi.RoborazziReportConst -import org.gradle.api.Action -import org.gradle.api.DefaultTask -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.Task +import org.gradle.api.* import org.gradle.api.file.DirectoryProperty import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property @@ -23,7 +19,7 @@ import org.gradle.api.tasks.testing.Test import org.gradle.language.base.plugins.LifecycleBasePlugin.VERIFICATION_GROUP import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget -import java.util.Locale +import java.util.* import javax.inject.Inject private const val DEFAULT_OUTPUT_DIR = "outputs/roborazzi" @@ -198,16 +194,16 @@ class RoborazziPlugin : Plugin { } t.infoln("Save result to ${resultsSummaryFile.absolutePath} with results:${results.size}") - val roborazziResult = CaptureResults.from(results) + val roborazziResults = CaptureResults.from(results) - val jsonResult = roborazziResult.toJson() + val jsonResult = roborazziResults.toJson() resultsSummaryFile.parentFile.mkdirs() - resultsSummaryFile.writeText(jsonResult.toString()) + resultsSummaryFile.writeText(jsonResult) reportFile.parentFile.mkdirs() reportFile.writeText( RoborazziReportConst.reportHtml.replace( oldValue = "REPORT_TEMPLATE_BODY", - newValue = roborazziResult.toHtml(reportFile.parentFile.absolutePath) + newValue = roborazziResults.toHtml(reportFile.parentFile.absolutePath) ) ) } From e8e8f576ed118b48035fecb7719de268fa568a2d Mon Sep 17 00:00:00 2001 From: sanao1006 Date: Sat, 27 Jan 2024 21:09:34 +0900 Subject: [PATCH 07/13] Fix `deserialize()` to avoid Null Pointer Exception caused by `type` --- .../kotlin/com/github/takahirom/roborazzi/CaptureResult.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index 4525ef9d..0c3671bc 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -84,8 +84,8 @@ sealed interface CaptureResult { json: com.google.gson.JsonElement, typeOfT: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext - ): CaptureResult { - val type = json.asJsonObject.get("type").asString + ): CaptureResult? { + val type = json.asJsonObject.get("type")?.asString ?: return null return when (type) { "recorded" -> context.deserialize(json, Recorded::class.java) "changed" -> context.deserialize(json, Changed::class.java) From b3b1fb0c4b7db1ffaf4104fa9eba9acf96c18275 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 28 Jan 2024 11:13:08 +0900 Subject: [PATCH 08/13] Fix crash of order of initialization --- .../takahirom/roborazzi/CaptureResults.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 997bce1d..67af8a3e 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -85,6 +85,20 @@ data class CaptureResults( } companion object { + val gson = GsonBuilder() + .registerTypeAdapter(File::class.java, object : JsonSerializer, JsonDeserializer { + override fun serialize(src: File?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement { + val absolutePath = src?.absolutePath ?: return JsonNull.INSTANCE + return JsonPrimitive(absolutePath) + } + + override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): File { + val path = json?.asString ?: throw JsonParseException("File path is null") + return File(path) + } + }) + .create() + fun fromJsonFile(inputPath: String): CaptureResults { val jsonObject = JsonParser.parseString(FileReader(inputPath).readText()).asJsonObject return fromJson(jsonObject) @@ -107,19 +121,5 @@ data class CaptureResults( captureResults = results ) } - - val gson = GsonBuilder() - .registerTypeAdapter(File::class.java, object : JsonSerializer, JsonDeserializer { - override fun serialize(src: File?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement { - val absolutePath = src?.absolutePath ?: return JsonNull.INSTANCE - return JsonPrimitive(absolutePath) - } - - override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): File { - val path = json?.asString ?: throw JsonParseException("File path is null") - return File(path) - } - }) - .create() } } From 6350068352f1ce4496366380ec7785986e0a1168 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 28 Jan 2024 11:28:48 +0900 Subject: [PATCH 09/13] Add type property --- .../com/github/takahirom/roborazzi/CaptureResult.kt | 11 ++++++++++- .../com/github/takahirom/roborazzi/CaptureResults.kt | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index 0c3671bc..a0cce99a 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -77,6 +77,15 @@ sealed interface CaptureResult { is Changed -> context.serialize(src, Changed::class.java) is Unchanged -> context.serialize(src, Unchanged::class.java) is Added -> context.serialize(src, Added::class.java) + }.apply { + this.asJsonObject.addProperty( + "type", when (src) { + is Recorded -> "recorded" + is Changed -> "changed" + is Unchanged -> "unchanged" + is Added -> "added" + } + ) } } @@ -85,7 +94,7 @@ sealed interface CaptureResult { typeOfT: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext ): CaptureResult? { - val type = json.asJsonObject.get("type")?.asString ?: return null + val type = requireNotNull(json.asJsonObject.get("type")?.asString) return when (type) { "recorded" -> context.deserialize(json, Recorded::class.java) "changed" -> context.deserialize(json, Changed::class.java) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt index 67af8a3e..70c9eb30 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResults.kt @@ -85,7 +85,7 @@ data class CaptureResults( } companion object { - val gson = GsonBuilder() + val gson: Gson = GsonBuilder() .registerTypeAdapter(File::class.java, object : JsonSerializer, JsonDeserializer { override fun serialize(src: File?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement { val absolutePath = src?.absolutePath ?: return JsonNull.INSTANCE From 23457a4b6578e17c55a6e822e319d94290149366 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 28 Jan 2024 11:35:35 +0900 Subject: [PATCH 10/13] Fix naming of CaptureResultTest --- .../takahirom/roborazzi/CaptureResultTest.kt | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt index bbb6ffee..3f95ba05 100644 --- a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt +++ b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt @@ -13,8 +13,8 @@ class CaptureResultTest { @Test fun testJsonSerialization() { - val summary = ResultSummary(11, 1, 2, 3, 5) - val captureResults = listOf( + val expectedSummary = ResultSummary(11, 1, 2, 3, 5) + val expectedCaptureResults = listOf( CaptureResult.Recorded( goldenFile = File("/golden_file"), timestampNs = 123456789, @@ -37,38 +37,38 @@ class CaptureResultTest { ) ) - val compareReportResult = CaptureResults(summary, captureResults) + val expectedReportResults = CaptureResults(expectedSummary, expectedCaptureResults) - val json = gson.toJsonTree(compareReportResult).asJsonObject - val jsonSummary = json.get("summary").asJsonObject - val jsonResults = json.get("results").asJsonArray + val actualJson = gson.toJsonTree(expectedReportResults).asJsonObject + val actualJsonSummary = actualJson.get("summary").asJsonObject + val actualJsonResults = actualJson.get("results").asJsonArray // Test summary - assertEquals(summary.total, jsonSummary.get("total").asInt) - assertEquals(summary.recorded, jsonSummary.get("recorded").asInt) - assertEquals(summary.added, jsonSummary.get("added").asInt) - assertEquals(summary.changed, jsonSummary.get("changed").asInt) - assertEquals(summary.unchanged, jsonSummary.get("unchanged").asInt) + assertEquals(expectedSummary.total, actualJsonSummary.get("total").asInt) + assertEquals(expectedSummary.recorded, actualJsonSummary.get("recorded").asInt) + assertEquals(expectedSummary.added, actualJsonSummary.get("added").asInt) + assertEquals(expectedSummary.changed, actualJsonSummary.get("changed").asInt) + assertEquals(expectedSummary.unchanged, actualJsonSummary.get("unchanged").asInt) // Test capture results - assertEquals(captureResults.size, jsonResults.size()) + assertEquals(expectedCaptureResults.size, actualJsonResults.size()) - for (i in 0 until jsonResults.size()) { - val jsonResult = jsonResults.get(i).asJsonObject - val captureResult = captureResults[i] + for (i in 0 until actualJsonResults.size()) { + val actualJsonResult = actualJsonResults.get(i).asJsonObject + val expectedCaptureResult = expectedCaptureResults[i] assertEquals( - captureResult.compareFile?.absolutePath, jsonResult.get("compare_file_path")?.asString + expectedCaptureResult.compareFile?.absolutePath, actualJsonResult.get("compare_file_path")?.asString ) assertEquals( - captureResult.goldenFile?.absolutePath, - jsonResult.get("golden_file_path")?.asString + expectedCaptureResult.goldenFile?.absolutePath, + actualJsonResult.get("golden_file_path")?.asString ) assertEquals( - captureResult.actualFile?.absolutePath, - jsonResult.get("actual_file_path")?.asString + expectedCaptureResult.actualFile?.absolutePath, + actualJsonResult.get("actual_file_path")?.asString ) - assertEquals(captureResult.timestampNs, jsonResult.get("timestamp").asLong) + assertEquals(expectedCaptureResult.timestampNs, actualJsonResult.get("timestamp").asLong) } } @@ -111,38 +111,38 @@ class CaptureResultTest { ] } """.trimIndent() - val jsonObject = JsonParser.parseString(jsonString).asJsonObject - val compareReportResult = CaptureResults.fromJson(jsonObject) - val summary = compareReportResult.resultSummary - val captureResults = compareReportResult.captureResults + val actualJsonObject = JsonParser.parseString(jsonString).asJsonObject + val actualCaptureResults= CaptureResults.fromJson(actualJsonObject) + val actualSummary = actualCaptureResults.resultSummary + val actualCaptureResultList = actualCaptureResults.captureResults // Test summary - assertEquals(11, summary.total) - assertEquals(1, summary.recorded) - assertEquals(2, summary.added) - assertEquals(3, summary.changed) - assertEquals(5, summary.unchanged) + assertEquals(11, actualSummary.total) + assertEquals(1, actualSummary.recorded) + assertEquals(2, actualSummary.added) + assertEquals(3, actualSummary.changed) + assertEquals(5, actualSummary.unchanged) // Test capture results - assertEquals(4, captureResults.size) - - val recordedResult = captureResults[0] as CaptureResult.Recorded - assertEquals(File("golden_file"), recordedResult.goldenFile) - assertEquals(123456789, recordedResult.timestampNs) - - val addedResult = captureResults[1] as CaptureResult.Added - assertEquals(File("compare_file"), addedResult.compareFile) - assertEquals(File("actual_file"), addedResult.actualFile) - assertEquals(123456789, addedResult.timestampNs) - - val changedResult = captureResults[2] as CaptureResult.Changed - assertEquals(File("compare_file"), changedResult.compareFile) - assertEquals(File("actual_file"), changedResult.actualFile) - assertEquals(File("golden_file"), changedResult.goldenFile) - assertEquals(123456789, changedResult.timestampNs) - - val unchangedResult = captureResults[3] as CaptureResult.Unchanged - assertEquals(File("golden_file"), unchangedResult.goldenFile) - assertEquals(123456789, unchangedResult.timestampNs) + assertEquals(4, actualCaptureResultList.size) + + val actualRecordedResult = actualCaptureResultList[0] as CaptureResult.Recorded + assertEquals(File("golden_file"), actualRecordedResult.goldenFile) + assertEquals(123456789, actualRecordedResult.timestampNs) + + val actualAddedResult = actualCaptureResultList[1] as CaptureResult.Added + assertEquals(File("compare_file"), actualAddedResult.compareFile) + assertEquals(File("actual_file"), actualAddedResult.actualFile) + assertEquals(123456789, actualAddedResult.timestampNs) + + val actualChangedResult = actualCaptureResultList[2] as CaptureResult.Changed + assertEquals(File("compare_file"), actualChangedResult.compareFile) + assertEquals(File("actual_file"), actualChangedResult.actualFile) + assertEquals(File("golden_file"), actualChangedResult.goldenFile) + assertEquals(123456789, actualChangedResult.timestampNs) + + val actualUnchangedResult = actualCaptureResultList[3] as CaptureResult.Unchanged + assertEquals(File("golden_file"), actualUnchangedResult.goldenFile) + assertEquals(123456789, actualUnchangedResult.timestampNs) } } From 5fce031e7f0a9c672e76d4be527e159e71831fa6 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 28 Jan 2024 12:23:19 +0900 Subject: [PATCH 11/13] Add type property --- .../takahirom/roborazzi/CaptureResult.kt | 24 +++++++++---------- .../takahirom/roborazzi/CaptureResultTest.kt | 5 ++++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt index a0cce99a..a13159b3 100644 --- a/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt +++ b/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/CaptureResult.kt @@ -8,6 +8,7 @@ import java.io.FileReader @JsonAdapter(CaptureResult.JsonAdapter::class) sealed interface CaptureResult { + val type: String val timestampNs: Long val compareFile: File? val actualFile: File? @@ -19,6 +20,8 @@ sealed interface CaptureResult { @SerializedName("timestamp") override val timestampNs: Long, ) : CaptureResult { + + override val type = "recorded" override val actualFile: File? get() = null override val compareFile: File? @@ -34,7 +37,9 @@ sealed interface CaptureResult { override val goldenFile: File, @SerializedName("timestamp") override val timestampNs: Long, - ) : CaptureResult + ) : CaptureResult { + override val type = "added" + } data class Changed( @SerializedName("compare_file_path") @@ -45,7 +50,9 @@ sealed interface CaptureResult { override val actualFile: File, @SerializedName("timestamp") override val timestampNs: Long - ) : CaptureResult + ) : CaptureResult { + override val type = "changed" + } data class Unchanged( @SerializedName("golden_file_path") @@ -53,6 +60,7 @@ sealed interface CaptureResult { @SerializedName("timestamp") override val timestampNs: Long ) : CaptureResult { + override val type = "unchanged" override val actualFile: File? get() = null override val compareFile: File? @@ -72,21 +80,13 @@ sealed interface CaptureResult { typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext ): com.google.gson.JsonElement { - return when (src) { + val jsonElement = when (src) { is Recorded -> context.serialize(src, Recorded::class.java) is Changed -> context.serialize(src, Changed::class.java) is Unchanged -> context.serialize(src, Unchanged::class.java) is Added -> context.serialize(src, Added::class.java) - }.apply { - this.asJsonObject.addProperty( - "type", when (src) { - is Recorded -> "recorded" - is Changed -> "changed" - is Unchanged -> "unchanged" - is Added -> "added" - } - ) } + return jsonElement } override fun deserialize( diff --git a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt index 3f95ba05..c055e573 100644 --- a/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt +++ b/include-build/roborazzi-core/src/jvmTest/kotlin/io/github/takahirom/roborazzi/CaptureResultTest.kt @@ -57,6 +57,11 @@ class CaptureResultTest { val actualJsonResult = actualJsonResults.get(i).asJsonObject val expectedCaptureResult = expectedCaptureResults[i] + assertEquals( + expectedCaptureResult.type, + actualJsonResult.get("type")?.asString + ) + assertEquals( expectedCaptureResult.compareFile?.absolutePath, actualJsonResult.get("compare_file_path")?.asString ) From 614aeb27a57bdad74de6850b7aea0a1c31c575cb Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 28 Jan 2024 12:34:11 +0900 Subject: [PATCH 12/13] Add diff for test --- .../java/com/github/takahirom/roborazzi/sample/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt b/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt index a2382cf9..90f5b0c6 100644 --- a/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt +++ b/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt @@ -18,7 +18,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // for making diff - // setTheme(com.google.android.material.R.style.Theme_Material3_Dark_NoActionBar) + setTheme(com.google.android.material.R.style.Theme_Material3_Dark_NoActionBar) super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) From 9f55fabc706656655dc2876688e1b3fe50409e51 Mon Sep 17 00:00:00 2001 From: takahirom Date: Mon, 29 Jan 2024 13:08:10 +0900 Subject: [PATCH 13/13] Remove changed theme --- .../java/com/github/takahirom/roborazzi/sample/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt b/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt index 90f5b0c6..a2382cf9 100644 --- a/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt +++ b/sample-android/src/main/java/com/github/takahirom/roborazzi/sample/MainActivity.kt @@ -18,7 +18,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // for making diff - setTheme(com.google.android.material.R.style.Theme_Material3_Dark_NoActionBar) + // setTheme(com.google.android.material.R.style.Theme_Material3_Dark_NoActionBar) super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater)