feat: scaffold counter_kt via init_kotlin_app
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
local.properties
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
captures/
|
||||||
|
.externalNativeBuild/
|
||||||
|
.cxx/
|
||||||
|
*.apk
|
||||||
|
*.aab
|
||||||
|
app/src/test/snapshots/
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# counter_kt
|
||||||
|
|
||||||
|
Counter demo: validates FnTheme + Material3 + state + tests
|
||||||
|
|
||||||
|
Generado con `init_kotlin_app` del registry fn_registry.
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- Android SDK 34
|
||||||
|
- JDK 17
|
||||||
|
- Gradle 8.6 (via wrapper)
|
||||||
|
- `kotlin/functions/ui` modulo del registry (composite build)
|
||||||
|
|
||||||
|
## Build rapido
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fn run gradle_assemble_debug_bash_infra apps/counter_kt
|
||||||
|
```
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
name: counter_kt
|
||||||
|
description: "Counter demo: validates FnTheme + Material3 + state + tests"
|
||||||
|
tags: [demo, counter, kotlin, compose, android]
|
||||||
|
lang: kt
|
||||||
|
framework: compose
|
||||||
|
entry_point: "app/src/main/kotlin/com/fnregistry/counterkt/MainActivity.kt"
|
||||||
|
dir_path: "apps/counter_kt"
|
||||||
|
repo_url: "https://gitea.organic-machine.com/dataforge/counter_kt"
|
||||||
|
uses_functions:
|
||||||
|
- fn_theme_kt_ui
|
||||||
|
- fn_tokens_kt_ui
|
||||||
|
uses_types: []
|
||||||
|
e2e_checks:
|
||||||
|
- id: unit
|
||||||
|
cmd: "fn run gradle_unit_test_bash_infra apps/counter_kt"
|
||||||
|
timeout_s: 240
|
||||||
|
- id: screenshot
|
||||||
|
cmd: "fn run gradle_screenshot_test_bash_infra apps/counter_kt"
|
||||||
|
timeout_s: 240
|
||||||
|
- id: build
|
||||||
|
cmd: "fn run gradle_assemble_debug_bash_infra apps/counter_kt"
|
||||||
|
timeout_s: 360
|
||||||
|
- id: emu_start
|
||||||
|
cmd: "fn run android_emulator_start_bash_infra Medium_Phone_API_35"
|
||||||
|
timeout_s: 240
|
||||||
|
- id: instrumented
|
||||||
|
cmd: "fn run gradle_instrumented_test_bash_infra apps/counter_kt"
|
||||||
|
timeout_s: 600
|
||||||
|
- id: emu_stop
|
||||||
|
cmd: "fn run android_emulator_stop_bash_infra"
|
||||||
|
severity: warning
|
||||||
|
timeout_s: 30
|
||||||
|
---
|
||||||
|
|
||||||
|
# counter_kt
|
||||||
|
|
||||||
|
Counter demo: validates FnTheme + Material3 + state + tests
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fn run gradle_assemble_debug_bash_infra apps/counter_kt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests unitarios + Roborazzi screenshots
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fn run gradle_unit_test_bash_infra apps/counter_kt
|
||||||
|
fn run gradle_screenshot_test_bash_infra apps/counter_kt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests instrumentados (requiere emulador)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fn run android_emulator_start_bash_infra Medium_Phone_API_35
|
||||||
|
fn run gradle_instrumented_test_bash_infra apps/counter_kt
|
||||||
|
fn run android_emulator_stop_bash_infra
|
||||||
|
```
|
||||||
|
|
||||||
|
## Package
|
||||||
|
|
||||||
|
`com.fnregistry.counterkt`
|
||||||
|
|
||||||
|
## FnTheme
|
||||||
|
|
||||||
|
La app usa FnTheme y FnTokens via composite build en `kotlin/functions/ui`.
|
||||||
|
Para cambiar colores o tipografia, editar el modulo del registry.
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.application") version "8.4.0"
|
||||||
|
id("org.jetbrains.kotlin.android") version "1.9.22"
|
||||||
|
id("io.github.takahirom.roborazzi") version "1.20.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.fnregistry.counterkt"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "com.fnregistry.counterkt"
|
||||||
|
minSdk = 24
|
||||||
|
targetSdk = 34
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "0.1.0"
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = "1.5.8"
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "17"
|
||||||
|
}
|
||||||
|
testOptions {
|
||||||
|
unitTests {
|
||||||
|
isIncludeAndroidResources = true
|
||||||
|
all {
|
||||||
|
it.systemProperty("robolectric.graphicsMode", "NATIVE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("androidx.activity:activity-compose:1.8.2")
|
||||||
|
implementation(platform("androidx.compose:compose-bom:2024.02.00"))
|
||||||
|
implementation("androidx.compose.ui:ui")
|
||||||
|
implementation("androidx.compose.material3:material3")
|
||||||
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
|
// FnTheme + FnTokens via composite build
|
||||||
|
implementation("fn.compose:ui")
|
||||||
|
|
||||||
|
testImplementation("junit:junit:4.13.2")
|
||||||
|
testImplementation("org.robolectric:robolectric:4.11.1")
|
||||||
|
testImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
|
testImplementation("io.github.takahirom.roborazzi:roborazzi:1.20.0")
|
||||||
|
testImplementation("io.github.takahirom.roborazzi:roborazzi-compose:1.20.0")
|
||||||
|
testImplementation("io.github.takahirom.roborazzi:roborazzi-junit-rule:1.20.0")
|
||||||
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.fnregistry.counterkt
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class MainActivityTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createAndroidComposeRule<MainActivity>()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun appLaunchesAndShowsReadyText() {
|
||||||
|
composeTestRule
|
||||||
|
.onNodeWithText("counter_kt ready")
|
||||||
|
.assertIsDisplayed()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.fnregistry.counterkt
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import fn.compose.theme.FnTheme
|
||||||
|
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
FnTheme {
|
||||||
|
Surface(modifier = Modifier.fillMaxSize()) {
|
||||||
|
Text("counter_kt ready")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">counter_kt</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.fnregistry.counterkt
|
||||||
|
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import com.github.takahirom.roborazzi.RoborazziRule
|
||||||
|
import fn.compose.theme.FnTheme
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.GraphicsMode
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
||||||
|
class ExampleScreenshotTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val roborazziRule = RoborazziRule(
|
||||||
|
options = RoborazziRule.Options(
|
||||||
|
outputDirectoryPath = "src/test/snapshots/images",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun screenshotFnThemeSurface() {
|
||||||
|
composeTestRule.setContent {
|
||||||
|
FnTheme {
|
||||||
|
Surface {
|
||||||
|
Text("counter_kt screenshot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Captura automaticamente al finalizar el test via RoborazziRule
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
plugins {
|
||||||
|
id("com.android.application") version "8.4.0" apply false
|
||||||
|
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
android.useAndroidX=true
|
||||||
|
kotlin.code.style=official
|
||||||
|
android.nonTransitiveRClass=true
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Gradle wrapper stub — descarga gradle-wrapper.jar si no existe.
|
||||||
|
# En CI / en WSL instalar el wrapper real con: gradle wrapper --gradle-version 8.6
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
exec "$SCRIPT_DIR/gradle/wrapper/gradlew" "$@" 2>/dev/null || \
|
||||||
|
exec gradle "$@"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
gradlePluginPortal()
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rootProject.name = "counter_kt"
|
||||||
|
include(":app")
|
||||||
|
|
||||||
|
// Composite build: FnTheme + FnTokens desde el registry
|
||||||
|
includeBuild("../../kotlin/functions/ui") {
|
||||||
|
dependencySubstitution {
|
||||||
|
substitute(module("fn.compose:ui")).using(project(":"))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user