Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ out/
!.idea/codeInsightSettings.xml
.gradle/
build/
schemas/

# Local configuration file (sdk path, etc)
local.properties
Expand Down
9 changes: 7 additions & 2 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ kotlin {
// room
implementation(libs.room.runtime)
implementation(libs.sqlite.bundled)

// kotlinx
implementation(libs.kotlinx.datetime)
}
nativeMain.dependencies {
implementation(libs.ktor.client.darwin)
Expand All @@ -119,6 +122,7 @@ kotlin {
implementation(kotlin("test"))
implementation(libs.androidx.test.runner)
implementation("io.coil-kt.coil3:coil-test:3.3.0")
implementation("androidx.room:room-testing:2.7.2")
}
}
}
Expand Down Expand Up @@ -244,9 +248,10 @@ val fileFilter =
"com/nacchofer31/randomboxd/core/data/RandomBoxdHttpClientExtKt*",
"com/nacchofer31/randomboxd/core/presentation/RandomBoxdTheme*",
// Room generated code
"com/nacchofer31/randomboxd/core/data/UsernameDatabase_Impl*",
"com/nacchofer31/randomboxd/core/data/UserNameDatabaseConstructor*",
"com/nacchofer31/randomboxd/core/data/RandomBoxdDatabase_Impl*",
"com/nacchofer31/randomboxd/core/data/RandomBoxdDatabaseConstructor*",
"com/nacchofer31/randomboxd/random_film/domain/model/UserNameDao_Impl*",
"com/nacchofer31/randomboxd/history/domain/model/FilmHistoryDao_Impl*",
// Inline functions — JaCoCo cannot track coverage of Kotlin inline function bodies
"com/nacchofer31/randomboxd/core/domain/ResultData*",
"com/nacchofer31/randomboxd/core/domain/ResultDataKt*",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "ce25309d9c838ed831bb1af90f04448b",
"entities": [
{
"tableName": "UserName",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ce25309d9c838ed831bb1af90f04448b')"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "a1ca11c1bb9562d9aff407e02ea1afaa",
"entities": [
{
"tableName": "UserName",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
}
},
{
"tableName": "film_history_entry",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `filmSlug` TEXT NOT NULL, `filmName` TEXT NOT NULL, `posterUrl` TEXT NOT NULL, `releaseYear` INTEGER, `userNames` TEXT NOT NULL, `searchMode` TEXT NOT NULL, `selectedGenres` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "filmSlug",
"columnName": "filmSlug",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "filmName",
"columnName": "filmName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "posterUrl",
"columnName": "posterUrl",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "releaseYear",
"columnName": "releaseYear",
"affinity": "INTEGER"
},
{
"fieldPath": "userNames",
"columnName": "userNames",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "searchMode",
"columnName": "searchMode",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "selectedGenres",
"columnName": "selectedGenres",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isFavorite",
"columnName": "isFavorite",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a1ca11c1bb9562d9aff407e02ea1afaa')"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.nacchofer31.randomboxd.core.data

import androidx.room.Room
import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MigrationTest {
private val testHelper =
MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
RandomBoxdDatabase::class.java,
emptyList(),
FrameworkSQLiteOpenHelperFactory(),
)

private val testUserName = "testuser"

@Test
fun v1_to_v2_preserves_usernames_and_creates_film_history_entry() {
// Create v1 database
val v1Db = testHelper.createDatabase(DATABASE_NAME, 1)
v1Db.execSQL("INSERT INTO UserName (username) VALUES ('$testUserName')")
v1Db.close()

// Migrate to v2
val v2Db =
Room
.databaseBuilder(
InstrumentationRegistry.getInstrumentation().targetContext,
RandomBoxdDatabase::class.java,
DATABASE_NAME,
).addMigrations(MIGRATION_1_2)
.build()
v2Db.openHelper.writableDatabase

// Verify UserName survived
val cursor = v2Db.query("SELECT COUNT(*) FROM UserName WHERE username = '$testUserName'", emptyArray())
cursor.moveToFirst()
assertEquals(1, cursor.getInt(0))
cursor.close()

// Verify film_history_entry table exists
val tableCursor =
v2Db.query(
"SELECT name FROM sqlite_master WHERE type='table' AND name='film_history_entry'",
emptyArray(),
)
assertEquals(1, tableCursor.count)
tableCursor.close()

v2Db.close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.randomboxd.feature.random_film.data
import androidx.room.Room
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.nacchofer31.randomboxd.core.data.UsernameDatabase
import com.nacchofer31.randomboxd.core.data.RandomBoxdDatabase
import com.nacchofer31.randomboxd.random_film.data.repository_impl.UserNameRepositoryImpl
import com.nacchofer31.randomboxd.random_film.domain.model.UserName
import kotlinx.coroutines.flow.first
Expand All @@ -17,15 +17,15 @@ import kotlin.test.assertTrue

@RunWith(AndroidJUnit4::class)
class UserNameRepositoryImplTest {
private lateinit var database: UsernameDatabase
private lateinit var database: RandomBoxdDatabase
private lateinit var repository: UserNameRepositoryImpl

@Before
fun setUp() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
database =
Room
.inMemoryDatabaseBuilder(context, UsernameDatabase::class.java)
.inMemoryDatabaseBuilder(context, RandomBoxdDatabase::class.java)
.allowMainThreadQueries()
.build()
repository = UserNameRepositoryImpl(database)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.randomboxd.history.presentation

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nacchofer31.randomboxd.history.presentation.components.FavoritesFilterChip
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class FavoritesFilterChipTest {
@get:Rule
val composeTestRule = createComposeRule()

private fun setChipContent(
isActive: Boolean,
showLabel: Boolean = true,
onClick: () -> Unit = {},
) {
composeTestRule.setContent {
FavoritesFilterChip(
isActive = isActive,
onClick = onClick,
showLabel = showLabel,
)
}
}

@Test
fun favorites_chip_shows_label_when_active_and_label_enabled() {
setChipContent(isActive = true)

composeTestRule.onNodeWithText("Favorites").assertIsDisplayed()
}

@Test
fun favorites_chip_shows_label_when_inactive_and_label_enabled() {
setChipContent(isActive = false)

composeTestRule.onNodeWithText("Favorites").assertIsDisplayed()
}

@Test
fun favorites_chip_hides_label_when_label_disabled() {
setChipContent(isActive = false, showLabel = false)

composeTestRule.onNodeWithText("Favorites").assertDoesNotExist()
}

@Test
fun favorites_chip_click_triggers_callback() {
var clicked = false
setChipContent(isActive = false, onClick = { clicked = true })

composeTestRule.onNodeWithTag("test-history-favorites-chip").performClick()

assertTrue(clicked)
}
}
Loading
Loading