Skip to content
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

ISSUE-405: init commit with simple code gen #584

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b43b98e
ISSUE-405: init commit with simple code gen
OvsyannikovMaksim Sep 27, 2023
3ec0093
ISSUE-405: some refactoring
OvsyannikovMaksim Oct 23, 2023
c3faddb
ISSUE-405: some refactoring and adding test prototype
OvsyannikovMaksim Nov 1, 2023
7be0032
ISSUE-405: some refactoring
OvsyannikovMaksim Dec 2, 2023
7b4e13c
ISSUE-405: some refactoring
OvsyannikovMaksim Dec 3, 2023
9b55b6a
ISSUE-405: some refactoring and create unit test
OvsyannikovMaksim Dec 3, 2023
513c50c
ISSUE-405: some refactoring
OvsyannikovMaksim Dec 3, 2023
9f7e280
ISSUE-405: preparing to add recyclerview support
OvsyannikovMaksim Dec 11, 2023
da789b9
ISSUE-405: add recyclerview support
OvsyannikovMaksim Dec 23, 2023
d55b08a
ISSUE-405: add recyclerview support
OvsyannikovMaksim Dec 23, 2023
e91aea5
ISSUE-405: fix static analysis
OvsyannikovMaksim Dec 23, 2023
2e4ff9d
ISSUE-405: fix static analysis
OvsyannikovMaksim Dec 23, 2023
709d2c3
ISSUE-405: fix static analysis
OvsyannikovMaksim Dec 23, 2023
a14796b
ISSUE-405: add 1 unit test and create SupportedViews.kt to easily add…
OvsyannikovMaksim Jan 15, 2024
6df5ad8
ISSUE-405: add ViewType.kt Enum class for storage supported views
OvsyannikovMaksim Feb 18, 2024
5a15b71
ISSUE-405: fix typo and remove some useless dependencies in build.gra…
OvsyannikovMaksim Feb 18, 2024
3d4f168
ISSUE-405: fix typo and upgrade build.gradle.kts to create .jar and c…
OvsyannikovMaksim Feb 19, 2024
eae3954
ISSUE-405: remove test prints
OvsyannikovMaksim Feb 19, 2024
28c9a42
ISSUE-405: fix conflict
OvsyannikovMaksim Feb 19, 2024
c13e8ba
ISSUE-405: fix conflict #2
OvsyannikovMaksim Feb 19, 2024
fef381b
Merge branch 'master' into ISSUE-405-page-object-code-gen
OvsyannikovMaksim Feb 19, 2024
045339f
Merge branch 'master' into ISSUE-405-page-object-code-gen
OvsyannikovMaksim Mar 3, 2024
72989bc
ISSUE-405: improve ViewType.kt
OvsyannikovMaksim Mar 3, 2024
308e731
ISSUE-405: create one more test
OvsyannikovMaksim Mar 4, 2024
61e6eba
ISSUE-405: crate shell script to launch jar file
OvsyannikovMaksim May 4, 2024
f1f5747
ISSUE-405: crate bat script to launch jar file
OvsyannikovMaksim May 4, 2024
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
132 changes: 132 additions & 0 deletions page-object-code-gen/createPageObjectFromUiDump.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import org.w3c.dom.Document
import java.io.File
import javax.xml.parsers.DocumentBuilderFactory

/**
* inputs:
* 1. Path to xml file with UI Dump
* output:
* Kotlin file with screen code in the same derictory as jar execute
*/
fun main(vararg args: String) {
val filePath = args.first()
if (!File(filePath).isFile) {
throw Exception("File is not exist or derictory")
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved
}
val fileResult = File("result.kt")

val documentBuilderFactory = DocumentBuilderFactory.newInstance()
val documentBuilder = documentBuilderFactory.newDocumentBuilder()
val doc = documentBuilder.parse(filePath)

val screenElements: List<View> = findAllViewInDump(doc)

fileResult.writeText(createScreenClass(screenElements))
}

data class View(val resourceId: String, val viewType: String, val packages: String) {
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved

fun toKaspressoExpression(): String {
return "val ${parseElementName(resourceId, viewType)} = K$viewType{ withId(R.id.$resourceId) }"
}
}

fun findAllViewInDump(document: Document): List<View> {
val collectableElements = listOf("android.widget.Button", "android.widget.TextView", "android.widget.ImageView")
val screenElements: MutableList<View> = mutableListOf<View>()
val bookNodeList = document.getElementsByTagName("node")

for (i in 0..bookNodeList.length - 1) {
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved
val bookNodeAttr = bookNodeList.item(i).attributes
if (bookNodeAttr.getNamedItem("class").nodeValue in collectableElements) {
val elem: View = View(
bookNodeAttr.getNamedItem("resource-id").nodeValue.substringAfterLast("/"),
bookNodeAttr.getNamedItem("class").nodeValue.substringAfterLast("."),
bookNodeAttr.getNamedItem("package").nodeValue,
)
screenElements.add(elem)
}
}

return screenElements
}

fun createScreenClass(screenElements: List<View>): String {
val packages = screenElements[0].packages
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved
val elements = createElements(screenElements)
val imports = createImports(screenElements)
val elementForWaitForScreen = parseElementName(screenElements.first().resourceId, screenElements.first().viewType)
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved

val screenClassTemplate =
"""
import $packages.R
import com.screen.common.KScreen
$imports

object screenClass : KScreen<screenClass>() {
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved

override val layoutId: Int? = TODO("Need To Implemet")
override val viewClass: Class<*>? = TODO("Need To Implemet")

$elements

override fun BaseTestContext.waitForScreen() {
$elementForWaitForScreen{
isVisible()
}
}
}
"""

return screenClassTemplate
}

fun createElements(screenElements: List<View>): String {
var elemetsStringResult: String = ""

screenElements.forEach { elemetsStringResult += it.toKaspressoExpression() + "\n\t\t" }
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved

return elemetsStringResult
}

fun createImports(screenElements: List<View>): String {
var importsStringResult: String = ""
val importsList: MutableList<String> = mutableListOf<String>()
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved

for (element in screenElements) {
var view = element.viewType
when (view) {
"ImageView" -> importsList.add("import io.guthub.kakaocup.kakao.image.KImageView\n\t")
"Button" -> importsList.add("import io.guthub.kakaocup.kakao.text.KButton\n\t")
"TextView" -> importsList.add("import io.guthub.kakaocup.kakao.text.KTextView\n\t")
"RecyclerView" -> importsList.add("import io.guthub.kakaocup.kakao.recycler.KRecyclerView\n\t")
"RecyclerItem" -> importsList.add("import io.guthub.kakaocup.kakao.recycler.KRecyclerItem\n\t")
"EditText" -> importsList.add("import io.guthub.kakaocup.kakao.edit.KEditText\n\t")
}
}

val uniqueImportsList: List<String> = unique(importsList).sorted()
uniqueImportsList.forEach { importsStringResult += it }

return importsStringResult
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved
}

fun parseElementName(resourceId: String, viewType: String): String {
var parts = resourceId.split("_").filter { it -> it !in listOf("button", "image", "text") }
Nikitae57 marked this conversation as resolved.
Show resolved Hide resolved
val name = parts.joinToString(separator = "") { it -> it.replaceFirstChar { it.uppercase() } }.replaceFirstChar { it.lowercase() }
when (viewType) {
"Button" -> return name + "Btn"
"ImageView" -> return name + "Img"
else -> return name
}
}

fun unique(list: List<String>): MutableList<String> {
val resultList: MutableList<String> = mutableListOf()
for (elem in list) {
if (elem !in resultList) {
resultList.add(elem)
}
}
return resultList
}
Loading