From 5b3c46a036e0e3124bb7546784d51c14bc246dc6 Mon Sep 17 00:00:00 2001 From: Jan Tennert Date: Wed, 29 Oct 2025 20:09:34 +0100 Subject: [PATCH 1/4] Add support for bucket pagination --- .../jan/supabase/storage/BucketFilter.kt | 61 +++++++++++++++++++ .../github/jan/supabase/storage/SortOrder.kt | 16 +++++ .../io/github/jan/supabase/storage/Storage.kt | 31 ++++++++-- Storage/src/commonTest/kotlin/StorageTest.kt | 6 +- 4 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt create mode 100644 Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/SortOrder.kt diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt new file mode 100644 index 000000000..17133068d --- /dev/null +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt @@ -0,0 +1,61 @@ +package io.github.jan.supabase.storage + +import io.ktor.http.parameters + +/** + * A filter builder for [Storage.listBuckets] + */ +class BucketFilter { + + /** + * The maximum number of buckets to return. If null, no limit is applied. + */ + var limit: Int? = null + + /** + * The number of buckets to skip before returning results. Useful for pagination. + */ + var offset: Int? = null + + /** + * A search query to filter buckets by name. If null, no search filter is applied. + */ + var search: String? = null + + /** + * The sort order for the results. Can be [SortOrder.ASC] (ascending) or [SortOrder.DESC] (descending). + * If null, the default sort order from the API is used. + */ + var sortOrder: SortOrder? = null + + /** + * The column to sort the results by. If null, the default sort column from the API is used. + */ + var sortColumn: SortColumn? = null + + internal fun build() = parameters { + limit?.let { set("limit", it.toString()) } + offset?.let { set("offset", it.toString()) } + search?.let { set("search", it) } + sortOrder?.let { set("sortOrder", it.name.lowercase()) } + sortColumn?.let { set("sortColumn", it.name.lowercase()) } + } + + /** + * Represents the available columns for sorting bucket results. + */ + enum class SortColumn { + /** Sort by bucket ID */ + ID, + + /** Sort by bucket name */ + NAME, + + /** Sort by bucket creation timestamp */ + CREATED_AT, + + /** Sort by bucket last updated timestamp */ + UPDATED_AT + } + +} \ No newline at end of file diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/SortOrder.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/SortOrder.kt new file mode 100644 index 000000000..9eba30acc --- /dev/null +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/SortOrder.kt @@ -0,0 +1,16 @@ +package io.github.jan.supabase.storage + +/** + * Represents the sort order for query results. + */ +enum class SortOrder { + /** + * Ascending order + */ + ASC, + + /** + * Descending order + */ + DESC +} \ No newline at end of file diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/Storage.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/Storage.kt index 6774a80e7..7885c8225 100644 --- a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/Storage.kt +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/Storage.kt @@ -75,7 +75,24 @@ interface Storage : MainPlugin, CustomSerializationPlugin { * @throws HttpRequestTimeoutException if the request timed out * @throws HttpRequestException on network related issues */ - suspend fun retrieveBuckets(): List + suspend fun listBuckets(filter: BucketFilter.() -> Unit = {}): List + + /** + * Returns all buckets in the storage + * @throws RestException or one of its subclasses if receiving an error response + * @throws HttpRequestTimeoutException if the request timed out + * @throws HttpRequestException on network related issues + */ + @Deprecated("Use listBuckets instead", ReplaceWith("listBuckets()")) + suspend fun retrieveBuckets(): List = listBuckets() + + /** + * Retrieves a bucket by its [bucketId] + * @throws RestException or one of its subclasses if receiving an error response + * @throws HttpRequestTimeoutException if the request timed out + * @throws HttpRequestException on network related issues + */ + suspend fun getBucket(bucketId: String): Bucket? /** * Retrieves a bucket by its [bucketId] @@ -83,7 +100,8 @@ interface Storage : MainPlugin, CustomSerializationPlugin { * @throws HttpRequestTimeoutException if the request timed out * @throws HttpRequestException on network related issues */ - suspend fun retrieveBucketById(bucketId: String): Bucket? + @Deprecated("Use getBucket instead", ReplaceWith("getBucket(bucketId)")) + suspend fun retrieveBucketById(bucketId: String): Bucket? = getBucket(bucketId) /** * Empties a bucket by its [bucketId] @@ -200,9 +218,14 @@ internal class StorageImpl(override val supabaseClient: SupabaseClient, override private val resumableClients = AtomicMutableMap() - override suspend fun retrieveBuckets(): List = api.get("bucket").safeBody() + override suspend fun listBuckets(filter: BucketFilter.() -> Unit): List { + val response = api.get("bucket") { + url.parameters.appendAll(BucketFilter().apply(filter).build()) + } + return response.safeBody() + } - override suspend fun retrieveBucketById(bucketId: String): Bucket? = api.get("bucket/$bucketId").safeBody() + override suspend fun getBucket(bucketId: String): Bucket? = api.get("bucket/$bucketId").safeBody() override suspend fun deleteBucket(bucketId: String) { api.delete("bucket/$bucketId") diff --git a/Storage/src/commonTest/kotlin/StorageTest.kt b/Storage/src/commonTest/kotlin/StorageTest.kt index 250ed2979..4635ed812 100644 --- a/Storage/src/commonTest/kotlin/StorageTest.kt +++ b/Storage/src/commonTest/kotlin/StorageTest.kt @@ -137,7 +137,7 @@ class StorageTest { """ ) } - val buckets = client.storage.retrieveBuckets() + val buckets = client.storage.listBuckets() assertEquals(1, buckets.size, "Buckets should contain 1 item") assertEquals(expectedId, buckets[0].id, "Bucket id should be 'test-bucket'") assertEquals(expectedId, buckets[0].name, "Bucket name should be 'test-bucket'") @@ -178,7 +178,7 @@ class StorageTest { """ ) } - val bucket = client.storage.retrieveBucketById(expectedId) + val bucket = client.storage.getBucket(expectedId) assertEquals(expectedId, bucket?.id, "Bucket id should be 'test-bucket'") assertEquals(expectedId, bucket?.name, "Bucket name should be 'test-bucket'") assertEquals(expectedPublic, bucket?.public, "Bucket public should be true") @@ -211,7 +211,7 @@ class StorageTest { respond("[]") } client.auth.importAuthToken(key) - client.storage.retrieveBuckets() + client.storage.listBuckets() } } From 2bd716c9eb023b790a2a257ed89b531cb16f6bbd Mon Sep 17 00:00:00 2001 From: Jan Tennert Date: Mon, 3 Nov 2025 22:21:32 +0100 Subject: [PATCH 2/4] add tests --- .../jan/supabase/storage/BucketFilter.kt | 16 +- .../jan/supabase/storage/BucketListFilter.kt | 6 +- .../src/commonTest/kotlin/BucketApiTest.kt | 3 +- .../src/commonTest/kotlin/BucketFilterTest.kt | 260 ++++++++++++++++++ .../commonTest/kotlin/BucketListFilterTest.kt | 231 +++++++++++++++- Storage/src/commonTest/kotlin/StorageTest.kt | 50 ++++ 6 files changed, 558 insertions(+), 8 deletions(-) create mode 100644 Storage/src/commonTest/kotlin/BucketFilterTest.kt diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt index 17133068d..49c06e7b5 100644 --- a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt @@ -26,14 +26,24 @@ class BucketFilter { * The sort order for the results. Can be [SortOrder.ASC] (ascending) or [SortOrder.DESC] (descending). * If null, the default sort order from the API is used. */ - var sortOrder: SortOrder? = null + private var sortOrder: SortOrder? = null /** * The column to sort the results by. If null, the default sort column from the API is used. */ - var sortColumn: SortColumn? = null + private var sortColumn: SortColumn? = null - internal fun build() = parameters { + /** + * Sets the sorting criteria for the bucket list results + * @param column The column to sort by + * @param order The sort order (ascending or descending) + */ + fun sortBy(column: SortColumn, order: SortOrder) { + sortColumn = column + sortOrder = order + } + + fun build() = parameters { limit?.let { set("limit", it.toString()) } offset?.let { set("offset", it.toString()) } search?.let { set("search", it) } diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketListFilter.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketListFilter.kt index 30314026b..6a20f7edb 100644 --- a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketListFilter.kt +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketListFilter.kt @@ -29,10 +29,12 @@ class BucketListFilter { /** * Sorts the result by the given [column] in the given [order] + * @param column The column to sort by + * @param order The sort order (ascending or descending) */ - fun sortBy(column: String, order: String) { + fun sortBy(column: String, order: SortOrder) { this.column = column - this.order = order + this.order = order.name.lowercase() } @SupabaseInternal diff --git a/Storage/src/commonTest/kotlin/BucketApiTest.kt b/Storage/src/commonTest/kotlin/BucketApiTest.kt index 12a948950..ee2e2d91c 100644 --- a/Storage/src/commonTest/kotlin/BucketApiTest.kt +++ b/Storage/src/commonTest/kotlin/BucketApiTest.kt @@ -4,6 +4,7 @@ import io.github.jan.supabase.storage.BucketApi import io.github.jan.supabase.storage.FileObjectV2 import io.github.jan.supabase.storage.FileUploadResponse import io.github.jan.supabase.storage.ImageTransformation +import io.github.jan.supabase.storage.SortOrder import io.github.jan.supabase.storage.Storage import io.github.jan.supabase.storage.resumable.MemoryResumableCache import io.github.jan.supabase.storage.storage @@ -451,7 +452,7 @@ class BucketApiTest { limit = expectedLimit offset = expectedOffset search = expectedSearch - sortBy(expectedColumn, expectedOrder) + sortBy(expectedColumn, SortOrder.ASC) } // assertContentEquals(expectedData, data, "Data should be $expectedData") } diff --git a/Storage/src/commonTest/kotlin/BucketFilterTest.kt b/Storage/src/commonTest/kotlin/BucketFilterTest.kt new file mode 100644 index 000000000..9d51279b0 --- /dev/null +++ b/Storage/src/commonTest/kotlin/BucketFilterTest.kt @@ -0,0 +1,260 @@ +import io.github.jan.supabase.storage.BucketFilter +import io.github.jan.supabase.storage.SortOrder +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +class BucketFilterTest { + + @Test + fun testBucketFilterWithAllParameters() { + val filter = BucketFilter().apply { + limit = 10 + offset = 5 + search = "test" + sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) + } + val params = filter.build() + assertEquals("10", params["limit"]) + assertEquals("5", params["offset"]) + assertEquals("test", params["search"]) + assertEquals("asc", params["sortOrder"]) + assertEquals("name", params["sortColumn"]) + } + + @Test + fun testBucketFilterEmpty() { + val filter = BucketFilter() + val params = filter.build() + assertNull(params["limit"]) + assertNull(params["offset"]) + assertNull(params["search"]) + assertNull(params["sortOrder"]) + assertNull(params["sortColumn"]) + } + + @Test + fun testBucketFilterWithLimitOnly() { + val filter = BucketFilter().apply { + limit = 20 + } + val params = filter.build() + assertEquals("20", params["limit"]) + assertNull(params["offset"]) + assertNull(params["search"]) + assertNull(params["sortOrder"]) + assertNull(params["sortColumn"]) + } + + @Test + fun testBucketFilterWithOffsetOnly() { + val filter = BucketFilter().apply { + offset = 15 + } + val params = filter.build() + assertNull(params["limit"]) + assertEquals("15", params["offset"]) + assertNull(params["search"]) + assertNull(params["sortOrder"]) + assertNull(params["sortColumn"]) + } + + @Test + fun testBucketFilterWithSearchOnly() { + val filter = BucketFilter().apply { + search = "my-bucket" + } + val params = filter.build() + assertNull(params["limit"]) + assertNull(params["offset"]) + assertEquals("my-bucket", params["search"]) + assertNull(params["sortOrder"]) + assertNull(params["sortColumn"]) + } + + @Test + fun testBucketFilterWithLimitAndOffset() { + val filter = BucketFilter().apply { + limit = 25 + offset = 50 + } + val params = filter.build() + assertEquals("25", params["limit"]) + assertEquals("50", params["offset"]) + assertNull(params["search"]) + assertNull(params["sortOrder"]) + assertNull(params["sortColumn"]) + } + + @Test + fun testBucketFilterSortByIdAscending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.ID, SortOrder.ASC) + } + val params = filter.build() + assertEquals("id", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByIdDescending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.ID, SortOrder.DESC) + } + val params = filter.build() + assertEquals("id", params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByNameAscending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) + } + val params = filter.build() + assertEquals("name", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByNameDescending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.NAME, SortOrder.DESC) + } + val params = filter.build() + assertEquals("name", params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByCreatedAtAscending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.ASC) + } + val params = filter.build() + assertEquals("created_at", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByCreatedAtDescending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.DESC) + } + val params = filter.build() + assertEquals("created_at", params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByUpdatedAtAscending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.ASC) + } + val params = filter.build() + assertEquals("updated_at", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSortByUpdatedAtDescending() { + val filter = BucketFilter().apply { + sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.DESC) + } + val params = filter.build() + assertEquals("updated_at", params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) + } + + @Test + fun testBucketFilterSearchWithSpecialCharacters() { + val filter = BucketFilter().apply { + search = "test-bucket_123" + } + val params = filter.build() + assertEquals("test-bucket_123", params["search"]) + } + + @Test + fun testBucketFilterWithZeroLimit() { + val filter = BucketFilter().apply { + limit = 0 + } + val params = filter.build() + assertEquals("0", params["limit"]) + } + + @Test + fun testBucketFilterWithZeroOffset() { + val filter = BucketFilter().apply { + offset = 0 + } + val params = filter.build() + assertEquals("0", params["offset"]) + } + + @Test + fun testBucketFilterComplexScenario() { + val filter = BucketFilter().apply { + limit = 50 + offset = 100 + search = "production" + sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.DESC) + } + val params = filter.build() + assertEquals("50", params["limit"]) + assertEquals("100", params["offset"]) + assertEquals("production", params["search"]) + assertEquals("created_at", params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) + } + + @Test + fun testBucketFilterWithLargeNumbers() { + val filter = BucketFilter().apply { + limit = 1000 + offset = 5000 + } + val params = filter.build() + assertEquals("1000", params["limit"]) + assertEquals("5000", params["offset"]) + } + + @Test + fun testBucketFilterSearchWithEmptyString() { + val filter = BucketFilter().apply { + search = "" + } + val params = filter.build() + assertEquals("", params["search"]) + } + + @Test + fun testBucketFilterWithSearchAndSort() { + val filter = BucketFilter().apply { + search = "images" + sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.ASC) + } + val params = filter.build() + assertEquals("images", params["search"]) + assertEquals("updated_at", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + assertNull(params["limit"]) + assertNull(params["offset"]) + } + + @Test + fun testBucketFilterPaginationScenario() { + val filter = BucketFilter().apply { + limit = 10 + offset = 30 + sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) + } + val params = filter.build() + assertEquals("10", params["limit"]) + assertEquals("30", params["offset"]) + assertEquals("name", params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) + } + +} \ No newline at end of file diff --git a/Storage/src/commonTest/kotlin/BucketListFilterTest.kt b/Storage/src/commonTest/kotlin/BucketListFilterTest.kt index f05715789..b74426b4e 100644 --- a/Storage/src/commonTest/kotlin/BucketListFilterTest.kt +++ b/Storage/src/commonTest/kotlin/BucketListFilterTest.kt @@ -1,19 +1,21 @@ import io.github.jan.supabase.storage.BucketListFilter +import io.github.jan.supabase.storage.SortOrder import kotlinx.serialization.json.int import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNull class BucketListFilterTest { @Test - fun testBucketListFilter() { + fun testBucketListFilterWithAllParameters() { val filter = BucketListFilter().apply { limit = 10 offset = 0 search = "string" - sortBy("name", "asc") + sortBy("name", SortOrder.ASC) } val filterJson = filter.build() assertEquals(10, filterJson["limit"]!!.jsonPrimitive.int) @@ -23,4 +25,229 @@ class BucketListFilterTest { assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) } + @Test + fun testBucketListFilterEmpty() { + val filter = BucketListFilter() + val filterJson = filter.build() + assertNull(filterJson["limit"]) + assertNull(filterJson["offset"]) + assertNull(filterJson["search"]) + assertNull(filterJson["sortBy"]) + } + + @Test + fun testBucketListFilterWithLimitOnly() { + val filter = BucketListFilter().apply { + limit = 25 + } + val filterJson = filter.build() + assertEquals(25, filterJson["limit"]!!.jsonPrimitive.int) + assertNull(filterJson["offset"]) + assertNull(filterJson["search"]) + assertNull(filterJson["sortBy"]) + } + + @Test + fun testBucketListFilterWithOffsetOnly() { + val filter = BucketListFilter().apply { + offset = 50 + } + val filterJson = filter.build() + assertNull(filterJson["limit"]) + assertEquals(50, filterJson["offset"]!!.jsonPrimitive.int) + assertNull(filterJson["search"]) + assertNull(filterJson["sortBy"]) + } + + @Test + fun testBucketListFilterWithSearchOnly() { + val filter = BucketListFilter().apply { + search = "my-file" + } + val filterJson = filter.build() + assertNull(filterJson["limit"]) + assertNull(filterJson["offset"]) + assertEquals("my-file", filterJson["search"]!!.jsonPrimitive.content) + assertNull(filterJson["sortBy"]) + } + + @Test + fun testBucketListFilterWithSortByOnly() { + val filter = BucketListFilter().apply { + sortBy("created_at", SortOrder.DESC) + } + val filterJson = filter.build() + assertNull(filterJson["limit"]) + assertNull(filterJson["offset"]) + assertNull(filterJson["search"]) + assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterWithLimitAndOffset() { + val filter = BucketListFilter().apply { + limit = 20 + offset = 40 + } + val filterJson = filter.build() + assertEquals(20, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(40, filterJson["offset"]!!.jsonPrimitive.int) + assertNull(filterJson["search"]) + assertNull(filterJson["sortBy"]) + } + + @Test + fun testBucketListFilterSortByNameAscending() { + val filter = BucketListFilter().apply { + sortBy("name", SortOrder.ASC) + } + val filterJson = filter.build() + assertEquals("name", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByNameDescending() { + val filter = BucketListFilter().apply { + sortBy("name", SortOrder.DESC) + } + val filterJson = filter.build() + assertEquals("name", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByCreatedAtAscending() { + val filter = BucketListFilter().apply { + sortBy("created_at", SortOrder.ASC) + } + val filterJson = filter.build() + assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByCreatedAtDescending() { + val filter = BucketListFilter().apply { + sortBy("created_at", SortOrder.DESC) + } + val filterJson = filter.build() + assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByUpdatedAtAscending() { + val filter = BucketListFilter().apply { + sortBy("updated_at", SortOrder.ASC) + } + val filterJson = filter.build() + assertEquals("updated_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByUpdatedAtDescending() { + val filter = BucketListFilter().apply { + sortBy("updated_at", SortOrder.DESC) + } + val filterJson = filter.build() + assertEquals("updated_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByIdAscending() { + val filter = BucketListFilter().apply { + sortBy("id", SortOrder.ASC) + } + val filterJson = filter.build() + assertEquals("id", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSortByIdDescending() { + val filter = BucketListFilter().apply { + sortBy("id", SortOrder.DESC) + } + val filterJson = filter.build() + assertEquals("id", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSearchWithSpecialCharacters() { + val filter = BucketListFilter().apply { + search = "file-name_123.png" + } + val filterJson = filter.build() + assertEquals("file-name_123.png", filterJson["search"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterWithZeroLimit() { + val filter = BucketListFilter().apply { + limit = 0 + } + val filterJson = filter.build() + assertEquals(0, filterJson["limit"]!!.jsonPrimitive.int) + } + + @Test + fun testBucketListFilterWithZeroOffset() { + val filter = BucketListFilter().apply { + offset = 0 + } + val filterJson = filter.build() + assertEquals(0, filterJson["offset"]!!.jsonPrimitive.int) + } + + @Test + fun testBucketListFilterComplexScenario() { + val filter = BucketListFilter().apply { + limit = 100 + offset = 200 + search = "production-files" + sortBy("updated_at", SortOrder.DESC) + } + val filterJson = filter.build() + assertEquals(100, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(200, filterJson["offset"]!!.jsonPrimitive.int) + assertEquals("production-files", filterJson["search"]!!.jsonPrimitive.content) + assertEquals("updated_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterWithLargeNumbers() { + val filter = BucketListFilter().apply { + limit = 1000 + offset = 5000 + } + val filterJson = filter.build() + assertEquals(1000, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(5000, filterJson["offset"]!!.jsonPrimitive.int) + } + + @Test + fun testBucketListFilterSortByCustomColumn() { + val filter = BucketListFilter().apply { + sortBy("custom_field", SortOrder.ASC) + } + val filterJson = filter.build() + assertEquals("custom_field", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + } + + @Test + fun testBucketListFilterSearchWithEmptyString() { + val filter = BucketListFilter().apply { + search = "" + } + val filterJson = filter.build() + assertEquals("", filterJson["search"]!!.jsonPrimitive.content) + } + } \ No newline at end of file diff --git a/Storage/src/commonTest/kotlin/StorageTest.kt b/Storage/src/commonTest/kotlin/StorageTest.kt index 4635ed812..68bd16d56 100644 --- a/Storage/src/commonTest/kotlin/StorageTest.kt +++ b/Storage/src/commonTest/kotlin/StorageTest.kt @@ -2,6 +2,8 @@ import io.github.jan.supabase.SupabaseClientBuilder import io.github.jan.supabase.auth.Auth import io.github.jan.supabase.auth.auth import io.github.jan.supabase.auth.minimalConfig +import io.github.jan.supabase.storage.BucketFilter +import io.github.jan.supabase.storage.SortOrder import io.github.jan.supabase.storage.Storage import io.github.jan.supabase.storage.resumable.MemoryResumableCache import io.github.jan.supabase.storage.storage @@ -150,6 +152,54 @@ class StorageTest { } } + @Test + fun testListBucketsWithFilter() { + runTest { + val expectedId = "test-bucket" + val expectedPublic = true + val expectedFileSizeLimit = 10000L + val expectedAllowedMimeTypes = listOf("image/jpeg", "image/png") + val expectedCreatedAt = Clock.System.now() + val expectedUpdatedAt = Clock.System.now() + val owner = "uuid" + val client = createMockedSupabaseClient(configuration = configureClient) { + assertPathIs("/bucket", it.url.pathAfterVersion()) + assertMethodIs(HttpMethod.Get, it.method) + assertEquals("10", it.url.parameters["limit"], "Limit should be 10") + assertEquals("5", it.url.parameters["offset"], "Offset should be 5") + assertEquals("test", it.url.parameters["search"], "Search should be 'test'") + assertEquals("asc", it.url.parameters["sortOrder"], "Sort order should be 'asc'") + assertEquals("name", it.url.parameters["sortColumn"], "Sort column should be 'name'") + respond( + """ + [ + ${ + createSampleBucket( + id = expectedId, + name = expectedId, + public = expectedPublic, + fileSizeLimit = expectedFileSizeLimit, + allowedMimeTypes = expectedAllowedMimeTypes, + createdAt = expectedCreatedAt.toString(), + updatedAt = expectedUpdatedAt.toString(), + owner = owner + ) + } + ] + """ + ) + } + val buckets = client.storage.listBuckets { + limit = 10 + offset = 5 + search = "test" + sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) + } + assertEquals(1, buckets.size, "Buckets should contain 1 item") + assertEquals(expectedId, buckets[0].id, "Bucket id should be 'test-bucket'") + } + } + @Test fun testRetrieveBucket() { runTest { From 9a540653a559960746328ff93bedaa9bd3e76cd1 Mon Sep 17 00:00:00 2001 From: Jan Tennert Date: Mon, 3 Nov 2025 22:24:59 +0100 Subject: [PATCH 3/4] simplify tests --- .../src/commonTest/kotlin/BucketFilterTest.kt | 238 +++++------------ .../commonTest/kotlin/BucketListFilterTest.kt | 242 +++++------------- 2 files changed, 132 insertions(+), 348 deletions(-) diff --git a/Storage/src/commonTest/kotlin/BucketFilterTest.kt b/Storage/src/commonTest/kotlin/BucketFilterTest.kt index 9d51279b0..0964cff01 100644 --- a/Storage/src/commonTest/kotlin/BucketFilterTest.kt +++ b/Storage/src/commonTest/kotlin/BucketFilterTest.kt @@ -34,223 +34,111 @@ class BucketFilterTest { } @Test - fun testBucketFilterWithLimitOnly() { - val filter = BucketFilter().apply { - limit = 20 - } - val params = filter.build() + fun testBucketFilterIndividualParameters() { + // Test limit only + var filter = BucketFilter().apply { limit = 20 } + var params = filter.build() assertEquals("20", params["limit"]) assertNull(params["offset"]) - assertNull(params["search"]) - assertNull(params["sortOrder"]) - assertNull(params["sortColumn"]) - } - @Test - fun testBucketFilterWithOffsetOnly() { - val filter = BucketFilter().apply { - offset = 15 - } - val params = filter.build() - assertNull(params["limit"]) + // Test offset only + filter = BucketFilter().apply { offset = 15 } + params = filter.build() assertEquals("15", params["offset"]) - assertNull(params["search"]) - assertNull(params["sortOrder"]) - assertNull(params["sortColumn"]) - } - - @Test - fun testBucketFilterWithSearchOnly() { - val filter = BucketFilter().apply { - search = "my-bucket" - } - val params = filter.build() assertNull(params["limit"]) - assertNull(params["offset"]) - assertEquals("my-bucket", params["search"]) - assertNull(params["sortOrder"]) - assertNull(params["sortColumn"]) - } - - @Test - fun testBucketFilterWithLimitAndOffset() { - val filter = BucketFilter().apply { - limit = 25 - offset = 50 - } - val params = filter.build() - assertEquals("25", params["limit"]) - assertEquals("50", params["offset"]) - assertNull(params["search"]) - assertNull(params["sortOrder"]) - assertNull(params["sortColumn"]) - } - - @Test - fun testBucketFilterSortByIdAscending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.ID, SortOrder.ASC) - } - val params = filter.build() - assertEquals("id", params["sortColumn"]) - assertEquals("asc", params["sortOrder"]) - } - - @Test - fun testBucketFilterSortByIdDescending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.ID, SortOrder.DESC) - } - val params = filter.build() - assertEquals("id", params["sortColumn"]) - assertEquals("desc", params["sortOrder"]) - } - - @Test - fun testBucketFilterSortByNameAscending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) - } - val params = filter.build() - assertEquals("name", params["sortColumn"]) - assertEquals("asc", params["sortOrder"]) - } - - @Test - fun testBucketFilterSortByNameDescending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.NAME, SortOrder.DESC) - } - val params = filter.build() - assertEquals("name", params["sortColumn"]) - assertEquals("desc", params["sortOrder"]) - } - - @Test - fun testBucketFilterSortByCreatedAtAscending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.ASC) - } - val params = filter.build() - assertEquals("created_at", params["sortColumn"]) - assertEquals("asc", params["sortOrder"]) - } - @Test - fun testBucketFilterSortByCreatedAtDescending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.DESC) - } - val params = filter.build() - assertEquals("created_at", params["sortColumn"]) - assertEquals("desc", params["sortOrder"]) + // Test search only + filter = BucketFilter().apply { search = "my-bucket" } + params = filter.build() + assertEquals("my-bucket", params["search"]) + assertNull(params["limit"]) } @Test - fun testBucketFilterSortByUpdatedAtAscending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.ASC) - } - val params = filter.build() - assertEquals("updated_at", params["sortColumn"]) - assertEquals("asc", params["sortOrder"]) - } + fun testBucketFilterSortColumns() { + // Test all sort columns with both orders + val columns = listOf( + BucketFilter.SortColumn.ID to "id", + BucketFilter.SortColumn.NAME to "name", + BucketFilter.SortColumn.CREATED_AT to "created_at", + BucketFilter.SortColumn.UPDATED_AT to "updated_at" + ) - @Test - fun testBucketFilterSortByUpdatedAtDescending() { - val filter = BucketFilter().apply { - sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.DESC) - } - val params = filter.build() - assertEquals("updated_at", params["sortColumn"]) - assertEquals("desc", params["sortOrder"]) - } + for ((column, expectedName) in columns) { + // Test ascending + var filter = BucketFilter().apply { sortBy(column, SortOrder.ASC) } + var params = filter.build() + assertEquals(expectedName, params["sortColumn"]) + assertEquals("asc", params["sortOrder"]) - @Test - fun testBucketFilterSearchWithSpecialCharacters() { - val filter = BucketFilter().apply { - search = "test-bucket_123" + // Test descending + filter = BucketFilter().apply { sortBy(column, SortOrder.DESC) } + params = filter.build() + assertEquals(expectedName, params["sortColumn"]) + assertEquals("desc", params["sortOrder"]) } - val params = filter.build() - assertEquals("test-bucket_123", params["search"]) } @Test - fun testBucketFilterWithZeroLimit() { - val filter = BucketFilter().apply { + fun testBucketFilterEdgeCases() { + // Zero values + var filter = BucketFilter().apply { limit = 0 - } - val params = filter.build() - assertEquals("0", params["limit"]) - } - - @Test - fun testBucketFilterWithZeroOffset() { - val filter = BucketFilter().apply { offset = 0 } - val params = filter.build() + var params = filter.build() + assertEquals("0", params["limit"]) assertEquals("0", params["offset"]) - } - @Test - fun testBucketFilterComplexScenario() { - val filter = BucketFilter().apply { - limit = 50 - offset = 100 - search = "production" - sortBy(BucketFilter.SortColumn.CREATED_AT, SortOrder.DESC) - } - val params = filter.build() - assertEquals("50", params["limit"]) - assertEquals("100", params["offset"]) - assertEquals("production", params["search"]) - assertEquals("created_at", params["sortColumn"]) - assertEquals("desc", params["sortOrder"]) - } + // Empty search string + filter = BucketFilter().apply { search = "" } + params = filter.build() + assertEquals("", params["search"]) - @Test - fun testBucketFilterWithLargeNumbers() { - val filter = BucketFilter().apply { + // Special characters in search + filter = BucketFilter().apply { search = "test-bucket_123" } + params = filter.build() + assertEquals("test-bucket_123", params["search"]) + + // Large numbers + filter = BucketFilter().apply { limit = 1000 offset = 5000 } - val params = filter.build() + params = filter.build() assertEquals("1000", params["limit"]) assertEquals("5000", params["offset"]) } @Test - fun testBucketFilterSearchWithEmptyString() { - val filter = BucketFilter().apply { - search = "" + fun testBucketFilterCombinations() { + // Limit and offset + var filter = BucketFilter().apply { + limit = 25 + offset = 50 } - val params = filter.build() - assertEquals("", params["search"]) - } + var params = filter.build() + assertEquals("25", params["limit"]) + assertEquals("50", params["offset"]) + assertNull(params["search"]) - @Test - fun testBucketFilterWithSearchAndSort() { - val filter = BucketFilter().apply { + // Search and sort + filter = BucketFilter().apply { search = "images" sortBy(BucketFilter.SortColumn.UPDATED_AT, SortOrder.ASC) } - val params = filter.build() + params = filter.build() assertEquals("images", params["search"]) assertEquals("updated_at", params["sortColumn"]) assertEquals("asc", params["sortOrder"]) - assertNull(params["limit"]) - assertNull(params["offset"]) - } - @Test - fun testBucketFilterPaginationScenario() { - val filter = BucketFilter().apply { + // Pagination with sort + filter = BucketFilter().apply { limit = 10 offset = 30 sortBy(BucketFilter.SortColumn.NAME, SortOrder.ASC) } - val params = filter.build() + params = filter.build() assertEquals("10", params["limit"]) assertEquals("30", params["offset"]) assertEquals("name", params["sortColumn"]) diff --git a/Storage/src/commonTest/kotlin/BucketListFilterTest.kt b/Storage/src/commonTest/kotlin/BucketListFilterTest.kt index b74426b4e..eddd45e3c 100644 --- a/Storage/src/commonTest/kotlin/BucketListFilterTest.kt +++ b/Storage/src/commonTest/kotlin/BucketListFilterTest.kt @@ -36,183 +36,109 @@ class BucketListFilterTest { } @Test - fun testBucketListFilterWithLimitOnly() { - val filter = BucketListFilter().apply { - limit = 25 - } - val filterJson = filter.build() + fun testBucketListFilterIndividualParameters() { + // Test limit only + var filter = BucketListFilter().apply { limit = 25 } + var filterJson = filter.build() assertEquals(25, filterJson["limit"]!!.jsonPrimitive.int) assertNull(filterJson["offset"]) - assertNull(filterJson["search"]) - assertNull(filterJson["sortBy"]) - } - @Test - fun testBucketListFilterWithOffsetOnly() { - val filter = BucketListFilter().apply { - offset = 50 - } - val filterJson = filter.build() - assertNull(filterJson["limit"]) + // Test offset only + filter = BucketListFilter().apply { offset = 50 } + filterJson = filter.build() assertEquals(50, filterJson["offset"]!!.jsonPrimitive.int) - assertNull(filterJson["search"]) - assertNull(filterJson["sortBy"]) - } - - @Test - fun testBucketListFilterWithSearchOnly() { - val filter = BucketListFilter().apply { - search = "my-file" - } - val filterJson = filter.build() assertNull(filterJson["limit"]) - assertNull(filterJson["offset"]) - assertEquals("my-file", filterJson["search"]!!.jsonPrimitive.content) - assertNull(filterJson["sortBy"]) - } - @Test - fun testBucketListFilterWithSortByOnly() { - val filter = BucketListFilter().apply { - sortBy("created_at", SortOrder.DESC) - } - val filterJson = filter.build() + // Test search only + filter = BucketListFilter().apply { search = "my-file" } + filterJson = filter.build() + assertEquals("my-file", filterJson["search"]!!.jsonPrimitive.content) assertNull(filterJson["limit"]) - assertNull(filterJson["offset"]) - assertNull(filterJson["search"]) - assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } - @Test - fun testBucketListFilterWithLimitAndOffset() { - val filter = BucketListFilter().apply { - limit = 20 - offset = 40 - } - val filterJson = filter.build() - assertEquals(20, filterJson["limit"]!!.jsonPrimitive.int) - assertEquals(40, filterJson["offset"]!!.jsonPrimitive.int) - assertNull(filterJson["search"]) - assertNull(filterJson["sortBy"]) - } - - @Test - fun testBucketListFilterSortByNameAscending() { - val filter = BucketListFilter().apply { - sortBy("name", SortOrder.ASC) - } - val filterJson = filter.build() - assertEquals("name", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } - - @Test - fun testBucketListFilterSortByNameDescending() { - val filter = BucketListFilter().apply { - sortBy("name", SortOrder.DESC) - } - val filterJson = filter.build() - assertEquals("name", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } - - @Test - fun testBucketListFilterSortByCreatedAtAscending() { - val filter = BucketListFilter().apply { - sortBy("created_at", SortOrder.ASC) - } - val filterJson = filter.build() - assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } - - @Test - fun testBucketListFilterSortByCreatedAtDescending() { - val filter = BucketListFilter().apply { - sortBy("created_at", SortOrder.DESC) - } - val filterJson = filter.build() + // Test sort only + filter = BucketListFilter().apply { sortBy("created_at", SortOrder.DESC) } + filterJson = filter.build() assertEquals("created_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) + assertNull(filterJson["limit"]) } @Test - fun testBucketListFilterSortByUpdatedAtAscending() { - val filter = BucketListFilter().apply { - sortBy("updated_at", SortOrder.ASC) - } - val filterJson = filter.build() - assertEquals("updated_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } + fun testBucketListFilterSortColumns() { + // Test common sort columns with both orders + val columns = listOf("id", "name", "created_at", "updated_at") - @Test - fun testBucketListFilterSortByUpdatedAtDescending() { - val filter = BucketListFilter().apply { - sortBy("updated_at", SortOrder.DESC) - } - val filterJson = filter.build() - assertEquals("updated_at", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } + for (column in columns) { + // Test ascending + var filter = BucketListFilter().apply { sortBy(column, SortOrder.ASC) } + var filterJson = filter.build() + assertEquals(column, filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - @Test - fun testBucketListFilterSortByIdAscending() { - val filter = BucketListFilter().apply { - sortBy("id", SortOrder.ASC) + // Test descending + filter = BucketListFilter().apply { sortBy(column, SortOrder.DESC) } + filterJson = filter.build() + assertEquals(column, filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) + assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) } - val filterJson = filter.build() - assertEquals("id", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) } @Test - fun testBucketListFilterSortByIdDescending() { - val filter = BucketListFilter().apply { - sortBy("id", SortOrder.DESC) + fun testBucketListFilterEdgeCases() { + // Zero values + var filter = BucketListFilter().apply { + limit = 0 + offset = 0 } - val filterJson = filter.build() - assertEquals("id", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } + var filterJson = filter.build() + assertEquals(0, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(0, filterJson["offset"]!!.jsonPrimitive.int) - @Test - fun testBucketListFilterSearchWithSpecialCharacters() { - val filter = BucketListFilter().apply { - search = "file-name_123.png" - } - val filterJson = filter.build() + // Empty search string + filter = BucketListFilter().apply { search = "" } + filterJson = filter.build() + assertEquals("", filterJson["search"]!!.jsonPrimitive.content) + + // Special characters in search + filter = BucketListFilter().apply { search = "file-name_123.png" } + filterJson = filter.build() assertEquals("file-name_123.png", filterJson["search"]!!.jsonPrimitive.content) - } - @Test - fun testBucketListFilterWithZeroLimit() { - val filter = BucketListFilter().apply { - limit = 0 + // Large numbers + filter = BucketListFilter().apply { + limit = 1000 + offset = 5000 } - val filterJson = filter.build() - assertEquals(0, filterJson["limit"]!!.jsonPrimitive.int) + filterJson = filter.build() + assertEquals(1000, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(5000, filterJson["offset"]!!.jsonPrimitive.int) + + // Custom column name + filter = BucketListFilter().apply { sortBy("custom_field", SortOrder.ASC) } + filterJson = filter.build() + assertEquals("custom_field", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) } @Test - fun testBucketListFilterWithZeroOffset() { - val filter = BucketListFilter().apply { - offset = 0 + fun testBucketListFilterCombinations() { + // Limit and offset + var filter = BucketListFilter().apply { + limit = 20 + offset = 40 } - val filterJson = filter.build() - assertEquals(0, filterJson["offset"]!!.jsonPrimitive.int) - } + var filterJson = filter.build() + assertEquals(20, filterJson["limit"]!!.jsonPrimitive.int) + assertEquals(40, filterJson["offset"]!!.jsonPrimitive.int) + assertNull(filterJson["search"]) - @Test - fun testBucketListFilterComplexScenario() { - val filter = BucketListFilter().apply { + // All parameters together + filter = BucketListFilter().apply { limit = 100 offset = 200 search = "production-files" sortBy("updated_at", SortOrder.DESC) } - val filterJson = filter.build() + filterJson = filter.build() assertEquals(100, filterJson["limit"]!!.jsonPrimitive.int) assertEquals(200, filterJson["offset"]!!.jsonPrimitive.int) assertEquals("production-files", filterJson["search"]!!.jsonPrimitive.content) @@ -220,34 +146,4 @@ class BucketListFilterTest { assertEquals("desc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) } - @Test - fun testBucketListFilterWithLargeNumbers() { - val filter = BucketListFilter().apply { - limit = 1000 - offset = 5000 - } - val filterJson = filter.build() - assertEquals(1000, filterJson["limit"]!!.jsonPrimitive.int) - assertEquals(5000, filterJson["offset"]!!.jsonPrimitive.int) - } - - @Test - fun testBucketListFilterSortByCustomColumn() { - val filter = BucketListFilter().apply { - sortBy("custom_field", SortOrder.ASC) - } - val filterJson = filter.build() - assertEquals("custom_field", filterJson["sortBy"]!!.jsonObject["column"]!!.jsonPrimitive.content) - assertEquals("asc", filterJson["sortBy"]!!.jsonObject["order"]!!.jsonPrimitive.content) - } - - @Test - fun testBucketListFilterSearchWithEmptyString() { - val filter = BucketListFilter().apply { - search = "" - } - val filterJson = filter.build() - assertEquals("", filterJson["search"]!!.jsonPrimitive.content) - } - } \ No newline at end of file From 4a37c6a32ae0e8c090c44806027baa87085cfa02 Mon Sep 17 00:00:00 2001 From: Jan Tennert Date: Mon, 3 Nov 2025 23:40:34 +0100 Subject: [PATCH 4/4] make build internal --- .../kotlin/io/github/jan/supabase/storage/BucketFilter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt index 49c06e7b5..a2d32b797 100644 --- a/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt +++ b/Storage/src/commonMain/kotlin/io/github/jan/supabase/storage/BucketFilter.kt @@ -43,7 +43,7 @@ class BucketFilter { sortOrder = order } - fun build() = parameters { + internal fun build() = parameters { limit?.let { set("limit", it.toString()) } offset?.let { set("offset", it.toString()) } search?.let { set("search", it) }