馃摳 Request Snapshot

KNETRequestSnapshot pozwala zapisywa膰 requesty i odpowiedzi do p贸藕niejszego u偶ycia - debugging, testowanie, dokumentacja, eksport do narz臋dzi zewn臋trznych.

馃挕 Kiedy u偶ywa膰?
  • Debugging - zapisz problematyczne requesty do analizy
  • Testowanie - replay zapisanych request贸w
  • Dokumentacja API - export do Postman
  • Wsp贸艂praca - dzielenie si臋 requestami z zespo艂em

馃摝 Import

import rip.nerd.kitsunenet.util.KNETRequestSnapshot

馃殌 Szybki start

// Utw贸rz manager snapshot贸w
val snapshot = KNETRequestSnapshot()

// Wykonaj request
val request = KNETRequest.get("https://api.example.com/users/1")
val response = client.request(request)

// Zapisz snapshot
snapshot.save(
    id = "users/get-single",
    request = request,
    response = response,
    tags = listOf("users", "read"),
    notes = "Pobiera pojedynczego u偶ytkownika po ID"
)

// P贸藕niej - przywr贸膰 snapshot
val restored = snapshot.restore("users/get-single")
println("URL: ${restored?.request?.url}")
println("Status: ${restored?.response?.statusCode}")

馃搵 Struktura Snapshot

data class Snapshot(
    val id: String,                  // Unikalny identyfikator
    val request: KNETRequest,        // Zapisany request
    val response: KNETResponse?,     // Zapisana odpowied藕 (opcjonalna)
    val timestamp: Long,             // Kiedy utworzono
    val tags: List<String>,          // Tagi do grupowania
    val notes: String?               // Notatki
) {
    val group: String?               // Grupa (cz臋艣膰 przed "/")
    val name: String                 // Nazwa (cz臋艣膰 po "/")
}
Konwencja nazewnictwa ID
// U偶yj "/" do grupowania
"auth/login"           // group="auth", name="login"
"auth/logout"          // group="auth", name="logout"
"users/list"           // group="users", name="list"
"users/create"         // group="users", name="create"
"orders/get-by-id"     // group="orders", name="get-by-id"

// Bez grupy
"simple-request"       // group=null, name="simple-request"

馃敡 API Reference

save()

Zapisuje snapshot.

fun save(
    id: String,
    request: KNETRequest,
    response: KNETResponse? = null,
    tags: List<String> = emptyList(),
    notes: String? = null
): Snapshot
Przyk艂ad
// Zapisz tylko request
snapshot.save("templates/post-user", request)

// Zapisz request z odpowiedzi膮
snapshot.save("api/get-users", request, response)

// Z pe艂n膮 metadat膮
snapshot.save(
    id = "auth/login-success",
    request = request,
    response = response,
    tags = listOf("auth", "critical", "happy-path"),
    notes = "Poprawne logowanie z valid credentials"
)

restore()

Przywraca snapshot po ID.

fun restore(id: String): Snapshot?

restoreRequest()

Przywraca tylko request.

fun restoreRequest(id: String): KNETRequest?

restoreResponse()

Przywraca tylko response.

fun restoreResponse(id: String): KNETResponse?
Przyk艂ad - replay request
// Przywr贸膰 i wykonaj ponownie
val savedRequest = snapshot.restoreRequest("users/create")

if (savedRequest != null) {
    // Wykonaj ten sam request ponownie
    val newResponse = client.request(savedRequest)
    println("Nowa odpowied藕: ${newResponse.statusCode}")
}

getAll()

Pobiera wszystkie snapshoty.

fun getAll(): List<Snapshot>

getByGroup()

Pobiera snapshoty z danej grupy.

fun getByGroup(group: String): List<Snapshot>
Przyk艂ad
// Pobierz wszystkie snapshoty autoryzacji
val authSnapshots = snapshot.getByGroup("auth")

authSnapshots.forEach { snap ->
    println("${snap.name}: ${snap.request.method} ${snap.request.url}")
}
// Output:
// login: POST https://api.example.com/auth/login
// logout: POST https://api.example.com/auth/logout
// refresh: POST https://api.example.com/auth/refresh

getByTag()

Pobiera snapshoty z danym tagiem.

fun getByTag(tag: String): List<Snapshot>
Przyk艂ad
// Pobierz wszystkie krytyczne snapshoty
val criticalSnapshots = snapshot.getByTag("critical")

// Pobierz wszystkie b艂臋dne scenariusze
val errorSnapshots = snapshot.getByTag("error-case")

search()

Wyszukuje snapshoty po tek艣cie.

fun search(query: String): List<Snapshot>
Przyk艂ad
// Szukaj w ID, URL i notatkach
val results = snapshot.search("users")

results.forEach { snap ->
    println("${snap.id}: ${snap.request.url}")
}

delete() / clear()

fun delete(id: String): Boolean  // Usu艅 jeden
fun clear()                       // Usu艅 wszystkie

馃捑 Export / Import

exportToJson() / importFromJson()

Eksport/import do formatu JSON.

val json = snapshot.exportToJson()
println(json)
// {
//   "version": "1.0",
//   "exportedAt": "2024-01-15T10:30:00Z",
//   "snapshots": [...]
// }

// Import
val imported = snapshot.importFromJson(json)
println("Zaimportowano $imported snapshot贸w")

saveToFile() / loadFromFile()

Zapis/odczyt z pliku.

// Zapisz do pliku
snapshot.saveToFile(File(context.filesDir, "snapshots.json"))

// Wczytaj z pliku
val loaded = snapshot.loadFromFile(File(context.filesDir, "snapshots.json"))
println("Wczytano $loaded snapshot贸w")

exportToCurl()

Eksport do polece艅 cURL.

val curlCommands = snapshot.exportToCurl()
println(curlCommands)
Przyk艂ad wyj艣cia
curl -X POST 'https://api.example.com/users' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer token123' \
  -d '{"name":"Jan","email":"jan@example.com"}'

curl 'https://api.example.com/users/1' \
  -H 'Authorization: Bearer token123'

exportToPostman()

Eksport do formatu Postman Collection v2.1.

fun exportToPostman(collectionName: String = "KNET Snapshots"): String
Przyk艂ad
// Eksportuj do Postman
val postmanJson = snapshot.exportToPostman("My API Collection")

// Zapisz do pliku
File("postman_collection.json").writeText(postmanJson)

// Teraz mo偶esz zaimportowa膰 ten plik do Postman:
// Postman -> Import -> Upload Files -> wybierz plik
馃挕 Import do Postman
  1. Otw贸rz Postman
  2. Kliknij "Import" w lewym g贸rnym rogu
  3. Przeci膮gnij plik JSON lub kliknij "Upload Files"
  4. Kolekcja pojawi si臋 w panelu bocznym

馃搳 Statystyki

val stats = snapshot.getStats()

println("Snapshoty: ${stats["totalSnapshots"]}")
println("Grupy: ${stats["groups"]}")
println("Tagi: ${stats["tags"]}")
println("Metody: ${stats["byMethod"]}")
println("Z odpowiedzi膮: ${stats["withResponse"]}")
println("Bez odpowiedzi: ${stats["withoutResponse"]}")
Przyk艂ad wyj艣cia
Snapshoty: 15
Grupy: [auth, users, orders]
Tagi: [critical, read, write, error-case]
Metody: {GET=8, POST=5, PUT=1, DELETE=1}
Z odpowiedzi膮: 12
Bez odpowiedzi: 3

馃挕 Praktyczne przyk艂ady

Debugging - zapisywanie b艂臋dnych request贸w

class DebugApiClient(private val client: KNETClient) {

    private val snapshot = KNETRequestSnapshot()

    suspend fun request(request: KNETRequest): KNETResponse {
        val response = client.request(request)

        // Zapisz b艂臋dne requesty do analizy
        if (!response.isSuccessful) {
            snapshot.save(
                id = "errors/${System.currentTimeMillis()}",
                request = request,
                response = response,
                tags = listOf("error", "debug", "status-${response.statusCode}"),
                notes = "B艂膮d: ${response.statusCode} ${response.statusMessage}"
            )
        }

        return response
    }

    fun exportErrors(): String {
        val errors = snapshot.getByTag("error")
        return errors.map { it.toMap() }.toString()
    }
}

Tworzenie dokumentacji API

class ApiDocumentor {

    private val snapshot = KNETRequestSnapshot()

    fun documentEndpoint(
        name: String,
        description: String,
        request: KNETRequest,
        response: KNETResponse
    ) {
        snapshot.save(
            id = "docs/$name",
            request = request,
            response = response,
            tags = listOf("documentation"),
            notes = description
        )
    }

    fun generateDocumentation() {
        val docs = snapshot.getByTag("documentation")

        docs.forEach { doc ->
            println("## ${doc.name}")
            println(doc.notes)
            println()
            println("**Request:**")
            println("```")
            println("${doc.request.method} ${doc.request.url}")
            doc.request.headers.forEach { (k, v) -> println("$k: $v") }
            println("```")
            println()
            println("**Response:** ${doc.response?.statusCode}")
            println()
        }
    }

    fun exportToPostman() = snapshot.exportToPostman("API Documentation")
}

// U偶ycie
val documenter = ApiDocumentor()

// Dokumentuj ka偶dy endpoint
documenter.documentEndpoint(
    name = "get-user",
    description = "Pobiera u偶ytkownika po ID. Wymaga autoryzacji Bearer token.",
    request = KNETRequest.get("https://api.example.com/users/123"),
    response = response
)

// Eksportuj do Postman
val postmanCollection = documenter.exportToPostman()

Test fixtures

class TestFixtures {

    companion object {
        private val snapshot = KNETRequestSnapshot()

        init {
            // Wczytaj fixtures z pliku
            val fixturesFile = File("src/test/resources/fixtures.json")
            if (fixturesFile.exists()) {
                snapshot.loadFromFile(fixturesFile)
            }
        }

        fun getLoginRequest(): KNETRequest {
            return snapshot.restoreRequest("fixtures/login")
                ?: throw IllegalStateException("Missing fixture: fixtures/login")
        }

        fun getExpectedUserResponse(): KNETResponse {
            return snapshot.restoreResponse("fixtures/get-user")
                ?: throw IllegalStateException("Missing fixture: fixtures/get-user")
        }
    }
}

// W testach
class UserApiTest {

    @Test
    fun `should login successfully`() = runTest {
        val request = TestFixtures.getLoginRequest()
        val response = client.request(request)

        assertEquals(200, response.statusCode)
    }
}

Klonowanie i modyfikacja

// Sklonuj istniej膮cy snapshot z nowym ID
snapshot.clone("users/create", "users/create-v2")

// Przywr贸膰, zmodyfikuj i zapisz
val original = snapshot.restoreRequest("users/create")!!

val modified = original.copy(
    url = original.url.replace("/users", "/v2/users"),
    headers = original.headers + ("X-Version" to "2")
)

snapshot.save("users/create-v2", modified)

馃摫 Integracja z UI

class SnapshotViewModel : ViewModel() {

    private val snapshot = KNETRequestSnapshot()

    private val _snapshots = MutableStateFlow<List<Snapshot>>(emptyList())
    val snapshots = _snapshots.asStateFlow()

    init {
        loadSnapshots()
    }

    private fun loadSnapshots() {
        _snapshots.value = snapshot.getAll()
    }

    fun saveRequest(id: String, request: KNETRequest, response: KNETResponse?) {
        snapshot.save(id, request, response)
        loadSnapshots()
    }

    fun deleteSnapshot(id: String) {
        snapshot.delete(id)
        loadSnapshots()
    }

    fun exportAll(): String {
        return snapshot.exportToJson()
    }

    fun shareAsPostman(): String {
        return snapshot.exportToPostman("Moje Snapshoty")
    }
}

馃摎 Zobacz te偶