Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 2230f8ba authored by Ricki Hirner's avatar Ricki Hirner Committed by GitHub
Browse files

Refactor Ktor DavResourceTests (#137)

* Refactor tests

* Refactor Ktor DavResource Tests

- Update `createMockEngineForGet` to accept `content` and `contentType` parameters
- Fix spacing issues in `when` statements and exception handling
- Improve readability of multiline string responses
- Add missing spaces around operators
- Align indentation for better readability
- Fix test case descriptions and comments for consistency

* Remove useless Overwrite

* - Remove redundant contentType parameter in createMockEngineForGet
- Use named parameters for clarity in test cases
parent de16b123
Loading
Loading
Loading
Loading
+344 −358
Original line number Diff line number Diff line
@@ -53,19 +53,63 @@ import org.junit.Test
class DavResourceTest {

    private val sampleText = "SAMPLE RESPONSE"
    val sampleUrl = Url("https://127.0.0.1/dav/")
    val sampleDestination = URLBuilder(sampleUrl).takeFrom("test").build()
    private val sampleUrl = Url("https://127.0.0.1/dav/")
    private val sampleDestination = URLBuilder(sampleUrl).takeFrom("test").build()


    @Test
    fun `Copy POSITIVE no preconditions, 201 Created, resulted in the creation of a new resource`() = runTest {
        val mockEngine = MockEngine {
    // Helper methods for common test patterns
    private fun createMockEngineForCopy(status: HttpStatusCode): MockEngine {
        return MockEngine {
            respond(
                content = sampleText,
                status = HttpStatusCode.Created,  // 201 Created
                status = status,
                headers = headersOf(HttpHeaders.ContentType, ContentType.Text.Plain.toString())
            )
        }
    }

    private fun createMockEngineForDelete(status: HttpStatusCode): MockEngine {
        return MockEngine {
            respond(sampleText, status)
        }
    }

    private fun createMockEngineForGet(status: HttpStatusCode, eTag: String? = null, content: String = sampleText): MockEngine {
        return MockEngine {
            respond(
                content = content,
                status = status,
                headers = HeadersBuilder().apply {
                    eTag?.let { append(HttpHeaders.ETag, it) }
                    append(HttpHeaders.ContentType, "application/x-test-result")
                }.build()
            )
        }
    }

    private fun createMockEngineForPut(status: HttpStatusCode, eTag: String? = null): MockEngine {
        return MockEngine {
            respond(
                content = " ",
                status = status,
                headers = headersOf(HttpHeaders.ETag, eTag ?: "W/\"Weak PUT ETag\"")
            )
        }
    }

    private fun createMockEngineForPropfind(xmlResponse: String): MockEngine {
        return MockEngine {
            respond(
                content = xmlResponse,
                status = HttpStatusCode.MultiStatus,
                headers = headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )
        }
    }


    @Test
    fun `Copy POSITIVE no preconditions, 201 Created, resulted in the creation of a new resource`() = runTest {
        val mockEngine = createMockEngineForCopy(HttpStatusCode.Created)
        val httpClient = HttpClient(mockEngine)
        var called = false

@@ -85,13 +129,7 @@ class DavResourceTest {

    @Test
    fun `Copy POSITIVE no preconditions, 204 No content, resource successfully copied to a preexisting destination resource`() = runTest {
        val mockEngine = MockEngine {
            respond(
                content = sampleText,
                status = HttpStatusCode.NoContent,  // 204 No content
                headers = headersOf(HttpHeaders.ContentType, ContentType.Text.Plain.toString())
            )
        }
        val mockEngine = createMockEngineForCopy(HttpStatusCode.NoContent)
        val httpClient = HttpClient(mockEngine)

        var called = false
@@ -110,13 +148,8 @@ class DavResourceTest {
    }

    @Test
    fun `Copy NEGATIVE 207 multi-status eg errors on some of resources affected by the COPY prevented the operation from taking place`() = runTest {        val mockEngine = MockEngine {
            respond(
                content = sampleText,
                status = HttpStatusCode.MultiStatus,  // 207 multi-status
                headers = headersOf(HttpHeaders.ContentType, ContentType.Text.Plain.toString())
            )
        }
    fun `Copy NEGATIVE 207 multi-status eg errors on some of resources affected by the COPY prevented the operation from taking place`() = runTest {
        val mockEngine = createMockEngineForCopy(HttpStatusCode.MultiStatus)
        val httpClient = HttpClient(mockEngine)
        var called = false

@@ -133,9 +166,7 @@ class DavResourceTest {

    @Test
    fun `Delete only eTag POSITIVE TEST CASES  precondition If-Match 200 OK`() = runTest {
        val mockEngine = MockEngine {
            respond(sampleText, HttpStatusCode.NoContent)  // 204 No Content
        }
        val mockEngine = createMockEngineForDelete(HttpStatusCode.NoContent)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
        var called = false
@@ -150,9 +181,7 @@ class DavResourceTest {

    @Test
    fun `Delete eTag and schedule Tag POSITIVE TEST CASES  precondition If-Match 200 OK`() = runTest {
        val mockEngine = MockEngine {
            respondOk(content = sampleText)
        }
        val mockEngine = MockEngine { respondOk(content = sampleText) }
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
        var called = false
@@ -164,14 +193,13 @@ class DavResourceTest {
        assertEquals("\"SomeETag\"", rq.headers[HttpHeaders.IfMatch])
    }


    @Test
    fun `Delete POSITIVE TEST CASES  precondition If-Match 302 Moved Temporarily`() = runTest {
        var numResponses = 0
        val mockEngine = MockEngine {
            numResponses += 1
            when (numResponses) {
                1 -> respondRedirect("/new-location")  //307 TemporaryRedirect
                1 -> respondRedirect("/new-location")
                else -> respondOk()
            }
        }
@@ -179,18 +207,13 @@ class DavResourceTest {
        val dav = DavResource(httpClient, sampleUrl)
        var called = false

        dav.delete(null) {
            called = true
        }
        dav.delete(null) { called = true }
        assertTrue(called)
    }


    @Test
    fun `Delete NEGATIVE TEST CASES precondition If-Match 207 multi-status`() = runTest {
        val mockEngine = MockEngine {
            respondError(HttpStatusCode.MultiStatus)
        }
        val mockEngine = MockEngine { respondError(HttpStatusCode.MultiStatus) }
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
        var called = false
@@ -244,16 +267,7 @@ class DavResourceTest {

    @Test
    fun `Get POSITIVE TEST CASES 200 OK`() = runTest {
        val mockEngine = MockEngine {
            respond(
                content = sampleText,
                status = HttpStatusCode.OK,     // 200 OK
                headers = HeadersBuilder().apply {
                    append(HttpHeaders.ETag, "W/\"My Weak ETag\"")
                    append(HttpHeaders.ContentType, "application/x-test-result")
                }.build()
            )
        }
        val mockEngine = createMockEngineForGet(status = HttpStatusCode.OK, eTag = "W/\"My Weak ETag\"")
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
        var called = false
@@ -275,7 +289,6 @@ class DavResourceTest {
        assertEquals(ContentType.Any.toString(), rq.headers[HttpHeaders.Accept])
    }


    @Test
    fun `Get POSITIVE TEST CASES 302 Moved Temporarily + 200 OK`() = runTest {
        var numResponses = 0
@@ -304,12 +317,9 @@ class DavResourceTest {
        assertEquals("/target", rq.url.fullPath)
    }


    @Test
    fun `Get POSITIVE TEST CASES 200 OK without ETag in response`() = runTest {
        val mockEngine = MockEngine {
            respond(sampleText, HttpStatusCode.OK)
        }
        val mockEngine = createMockEngineForGet(status = HttpStatusCode.OK, eTag = null)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
        var called = false
@@ -374,7 +384,10 @@ class DavResourceTest {
        val rq = mockEngine.requestHistory.last()
        assertEquals(HttpMethod.Post, rq.method)
        assertEquals(sampleUrl.encodedPath, rq.url.encodedPath)
        assertEquals(ContentType.parse("application/x-test-result"), rq.body.contentType)  // TODO: Originally there was a check for the header, not the content type in the body, what is correct here?
        assertEquals(
            ContentType.parse("application/x-test-result"),
            rq.body.contentType
        )  // TODO: Originally there was a check for the header, not the content type in the body, what is correct here?
        //assertEquals("body", (rq.body as TextContent).text)

        /*
@@ -460,7 +473,8 @@ class DavResourceTest {
    }

    @Test
  fun `Move POSITIVE TEST CASES no preconditions, 201 Created, new URL mapping at the destination`() = runTest {      val mockEngine = MockEngine {
    fun `Move POSITIVE TEST CASES no preconditions, 201 Created, new URL mapping at the destination`() = runTest {
        val mockEngine = MockEngine {
            respond("", HttpStatusCode.Created)     // 201 Created
        }
        val httpClient = HttpClient(mockEngine)
@@ -618,7 +632,11 @@ class DavResourceTest {
    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus malformed XML response`() = runTest {
        val mockEngine = MockEngine {
            respond("<malformed-xml>", HttpStatusCode.MultiStatus, headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString()))   // * malformed XML response
            respond(
                "<malformed-xml>",
                HttpStatusCode.MultiStatus,
                headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )   // * malformed XML response
        }
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)
@@ -636,13 +654,10 @@ class DavResourceTest {

    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus response without multistatus root element`() = runTest {
        val mockEngine = MockEngine {
            respond("<test></test>", HttpStatusCode.MultiStatus, headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString()))   // * response without <multistatus> root element
        }
        val mockEngine = createMockEngineForPropfind("<test></test>")
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

        // * response without <multistatus> root element
        var called = false
        try {
            dav.propfind(0, WebDAV.ResourceType) { _, _ -> called = true }
@@ -652,24 +667,18 @@ class DavResourceTest {
        }
    }


    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus multi-status response with invalid status in response`() = runTest {
        val mockEngine = MockEngine {
            respond("<multistatus xmlns='DAV:'>" +
        val xmlResponse = "<multistatus xmlns='DAV:'>" +
                "  <response>" +
                "    <href>/dav</href>" +
                "    <status>Invalid Status Line</status>" +
                "  </response>" +
                    "</multistatus>",
                HttpStatusCode.MultiStatus,
                headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )   // * multi-status response with invalid <status> in <response>
        }
                "</multistatus>"
        val mockEngine = createMockEngineForPropfind(xmlResponse)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

        // * multi-status response with invalid <status> in <response>
        var called = false
        dav.propfind(0, WebDAV.ResourceType) { response, relation ->
            assertEquals(Response.HrefRelation.SELF, relation)
@@ -681,21 +690,16 @@ class DavResourceTest {

    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus multi-status response with response-status element indicating failure`() = runTest {
        val mockEngine = MockEngine {
            respond("<multistatus xmlns='DAV:'>" +
        val xmlResponse = "<multistatus xmlns='DAV:'>" +
                "  <response>" +
                "    <href>/dav</href>" +
                "    <status>HTTP/1.1 403 Forbidden</status>" +
                "  </response>" +
                    "</multistatus>",
                HttpStatusCode.MultiStatus,
                headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )   // * multi-status response with <response>/<status> element indicating failure
        }
                "</multistatus>"
        val mockEngine = createMockEngineForPropfind(xmlResponse)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

        // * multi-status response with <response>/<status> element indicating failure
        var called = false
        dav.propfind(0, WebDAV.ResourceType) { response, relation ->
            assertEquals(Response.HrefRelation.SELF, relation)
@@ -707,8 +711,7 @@ class DavResourceTest {

    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus multi-status response with invalid status in propstat`() = runTest {
        val mockEngine = MockEngine {
            respond("<multistatus xmlns='DAV:'>" +
        val xmlResponse = "<multistatus xmlns='DAV:'>" +
                "  <response>" +
                "    <href>/dav</href>" +
                "    <propstat>" +
@@ -718,15 +721,11 @@ class DavResourceTest {
                "      <status>Invalid Status Line</status>" +
                "    </propstat>" +
                "  </response>" +
                    "</multistatus>",
                HttpStatusCode.MultiStatus,
                headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )   // * multi-status response with invalid <status> in <propstat>
        }
                "</multistatus>"
        val mockEngine = createMockEngineForPropfind(xmlResponse)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

        // * multi-status response with invalid <status> in <propstat>
        var called = false
        dav.propfind(0, WebDAV.ResourceType) { response, relation ->
            called = true
@@ -736,19 +735,12 @@ class DavResourceTest {
        assertTrue(called)
    }


    @Test
    fun `NEGATIVE TEST CASES Propfind And MultiStatus multi-status response without response elements`() = runTest {
        val mockEngine = MockEngine {
            respond("<multistatus xmlns='DAV:'></multistatus>",
                HttpStatusCode.MultiStatus,
                headersOf(HttpHeaders.ContentType, ContentType.Application.Xml.withCharset(Charsets.UTF_8).toString())
            )   // multi-status response without <response> elements
        }
        val mockEngine = createMockEngineForPropfind("<multistatus xmlns='DAV:'></multistatus>")
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

        // multi-status response without <response> elements
        dav.propfind(0, WebDAV.ResourceType) { _, _ ->
            fail("Shouldn't be called")
        }
@@ -757,7 +749,8 @@ class DavResourceTest {
    @Test
    fun `POSITIVE TEST CASES Propfind And MultiStatus multi-status response with response-status element indicating success`() = runTest {
        val mockEngine = MockEngine {
            respond( "<multistatus xmlns='DAV:'>" +
            respond(
                "<multistatus xmlns='DAV:'>" +
                        "  <response>" +
                        "    <href>/dav</href>" +
                        "    <status>HTTP/1.1 200 OK</status>" +
@@ -785,7 +778,8 @@ class DavResourceTest {
    @Test
    fun `POSITIVE TEST CASES Propfind And MultiStatus multi-status response with response-propstat element`() = runTest {
        val mockEngine = MockEngine {
            respond( "<multistatus xmlns='DAV:'>" +
            respond(
                "<multistatus xmlns='DAV:'>" +
                        "  <response>" +
                        "    <href>/dav</href>" +
                        "    <propstat>" +
@@ -815,9 +809,11 @@ class DavResourceTest {
    }

    @Test
    fun `POSITIVE TEST CASES Propfind And MultiStatus SPECIAL CASES multi-status response for collection with several members, incomplete (not all resourcetypes listed)`() = runTest {
    fun `POSITIVE TEST CASES Propfind And MultiStatus SPECIAL CASES multi-status response for collection with several members, incomplete (not all resourcetypes listed)`() =
        runTest {
            val mockEngine = MockEngine {
            respond( "<multistatus xmlns='DAV:'>" +
                respond(
                    "<multistatus xmlns='DAV:'>" +
                            "  <response>" +
                            "    <href>" + sampleUrl.toString() + "</href>" +
                            "    <propstat>" +
@@ -930,7 +926,8 @@ class DavResourceTest {
    @Test
    fun `POSITIVE TEST CASES Propfind And MultiStatus SPECIAL CASES same property is sent as 200 OK and 404 Not Found in same response (seen in iCloud)`() = runTest {
        val mockEngine = MockEngine {
            respond( "<multistatus xmlns='DAV:'>" +
            respond(
                "<multistatus xmlns='DAV:'>" +
                        "  <response>" +
                        "    <href>" + sampleUrl.toString() + "</href>" +
                        "    <propstat>" +
@@ -971,7 +968,8 @@ class DavResourceTest {
    @Test
    fun `POSITIVE TEST CASES Propfind And MultiStatus SPECIAL CASES multi-status response with propstat that doesn't contain status, assume 200 OK`() = runTest {
        val mockEngine = MockEngine {
            respond( "<multistatus xmlns='DAV:'>" +
            respond(
                "<multistatus xmlns='DAV:'>" +
                        "  <response>" +
                        "    <href>/dav</href>" +
                        "    <propstat>" +
@@ -1046,23 +1044,18 @@ class DavResourceTest {
            setProperties = mapOf(Pair(Property.Name("sample", "setThis"), "Some Value")),
            removeProperties = listOf(Property.Name("sample", "removeThis"))
        )
        assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<d:propertyupdate xmlns:d=\"DAV:\">" +
                    "<d:set><d:prop><n1:setThis xmlns:n1=\"sample\">Some Value</n1:setThis></d:prop></d:set>" +
                    "<d:remove><d:prop><n2:removeThis xmlns:n2=\"sample\" /></d:prop></d:remove>" +
                "</d:propertyupdate>", xml)
                    "</d:propertyupdate>", xml
        )
    }

    @Test
    fun `Put POSITIVE TEST CASES no preconditions, 201 Created`() = runTest {
        val mockEngine = MockEngine {
            respond(
                content = " ",
                status = HttpStatusCode.Created,  // 201 Created
                headers = headersOf(HttpHeaders.ETag, "W/\"Weak PUT ETag\"")
            )
        }

        val mockEngine = createMockEngineForPut(HttpStatusCode.Created)
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)

@@ -1092,11 +1085,7 @@ class DavResourceTest {
        val mockEngine = MockEngine {
            numberOfResponse += 1
            when (numberOfResponse) {
                1 -> respond(
                    content = "",
                    status = HttpStatusCode.MovedPermanently,  // 301 Moved Permanently
                    headers = headersOf(HttpHeaders.Location, "/target")
                )
                1 -> respond("", HttpStatusCode.MovedPermanently, headersOf(HttpHeaders.Location, "/target"))
                else -> respond("", HttpStatusCode.NoContent)
            }
        }
@@ -1125,10 +1114,7 @@ class DavResourceTest {

    @Test
    fun `Put NEGATIVE TEST CASES precondition  If-Match, 412 Precondition Failed`() = runTest {
        val mockEngine = MockEngine {
            respond("", HttpStatusCode.PreconditionFailed)
        }

        val mockEngine = MockEngine { respond("", HttpStatusCode.PreconditionFailed) }
        val httpClient = HttpClient(mockEngine)
        val dav = DavResource(httpClient, sampleUrl)