From a2c330d9dc8a35642f625f439558859423fceaa6 Mon Sep 17 00:00:00 2001 From: xis Date: Mon, 16 Oct 2023 19:43:36 +0200 Subject: [PATCH] browse root node int test --- .../controller/UpnpControllerIntTest.groovy | 111 +++++++++++++----- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy b/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy index ac50715..f941614 100644 --- a/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy +++ b/src/integration/groovy/net/schowek/nextclouddlna/controller/UpnpControllerIntTest.groovy @@ -1,13 +1,14 @@ package net.schowek.nextclouddlna.controller -import net.schowek.nextclouddlna.DlnaService import net.schowek.nextclouddlna.dlna.media.MediaServer import org.jupnp.support.contentdirectory.DIDLParser +import org.jupnp.support.model.DIDLContent import org.jupnp.support.model.DIDLObject import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpEntity import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity import org.w3c.dom.Document import org.w3c.dom.Node import org.w3c.dom.NodeList @@ -26,8 +27,6 @@ class UpnpControllerIntTest extends IntegrationSpecification { @Autowired private MediaServer mediaServer - @Autowired - private DlnaService dlnaService def uid @@ -114,40 +113,20 @@ class UpnpControllerIntTest extends IntegrationSpecification { } } - def "should handle upnp browse ROOT request"() { + def "should handle upnp browse metadata for ROOT request"() { given: - def requestBody = '\n' + - '\n' + - ' \n' + - ' \n' + - ' 0\n' + - ' BrowseMetadata\n' + - ' *\n' + - ' 0\n' + - ' 0\n' + - ' \n' + - ' \n' + - ' \n' + - '' + def nodeId = "0" + def browseFlag = "BrowseMetadata" when: - def headers = new HttpHeaders([ - 'content-type': 'text/xml; charset="utf-8"', - 'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' - ]); - HttpEntity request = new HttpEntity(requestBody, headers); - def response = restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String) + def response = performContentDirectoryAction(nodeId, browseFlag) then: response.statusCode == HttpStatus.OK response.headers['content-type'].find() == "text/xml;charset=utf-8" when: - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( - new InputSource(new StringReader(response.body)) - ); - def didl = new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result")) + def didl = extractDIDLFromResponse(response) then: didl.containers.size() == 1 @@ -163,6 +142,52 @@ class UpnpControllerIntTest extends IntegrationSpecification { } } + def "should handle upnp browse direct children for ROOT request"() { + given: + def nodeId = "0" + def browseFlag = "BrowseDirectChildren" + + when: + def response = performContentDirectoryAction(nodeId, browseFlag) + + then: + response.statusCode == HttpStatus.OK + response.headers['content-type'].find() == "text/xml;charset=utf-8" + + when: + def didl = extractDIDLFromResponse(response) + + then: + didl.containers.size() == 3 + didl.containers.each { + assert it.searchable + assert it.restricted + assert it.writeStatus == NOT_WRITABLE + assert it.clazz.value == new DIDLObject.Class("object.container").value + } + + with(didl.containers[0]) { + assert id == "2" + assert parentID == "1" + assert title == "johndoe" + assert childCount == 3 + } + + with(didl.containers[1]) { + assert id == "387" + assert parentID == "384" + assert title == "janedoe" + assert childCount == 1 + } + + with(didl.containers[2]) { + assert id == "586" + assert parentID == "584" + assert title == "family folder" + assert childCount == 1 + } + } + private String nodeValue(Document dom, String pattern) { return node(dom, "$pattern/text()").nodeValue } @@ -176,4 +201,34 @@ class UpnpControllerIntTest extends IntegrationSpecification { XPath xpath = XPathFactory.newInstance().newXPath(); return (xpath.evaluate(pattern, dom, NODESET) as NodeList) } + + private ResponseEntity performContentDirectoryAction(String nodeId, String browseFlag) { + def requestBody = '\n' + + '\n' + + ' \n' + + ' \n' + + ' ' + nodeId + '\n' + + ' ' + browseFlag + '\n' + + ' *\n' + + ' 0\n' + + ' 200\n' + + ' \n' + + ' \n' + + ' \n' + + '' + def headers = new HttpHeaders([ + 'content-type': 'text/xml; charset="utf-8"', + 'soapaction' : '"urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' + ]); + HttpEntity request = new HttpEntity(requestBody, headers); + return restTemplate().postForEntity(urlWithPort("/dev/$uid/svc/upnp-org/ContentDirectory/action"), request, String) + } + + private DIDLContent extractDIDLFromResponse(ResponseEntity response) { + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( + new InputSource(new StringReader(response.body)) + ); + return new DIDLParser().parse(nodeValue(dom, "/Envelope/Body/BrowseResponse/Result")) + } }