diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f03709f1..206aba875 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,3 +8,51 @@ jobs: secrets: IGNITE_REALTIME_MAVEN_USERNAME: ${{ secrets.IGNITE_REALTIME_MAVEN_USERNAME }} IGNITE_REALTIME_MAVEN_PASSWORD: ${{ secrets.IGNITE_REALTIME_MAVEN_PASSWORD }} + test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout tests + uses: actions/checkout@v4 + with: + sparse-checkout: | + test + + - name: Download the built plugin + uses: actions/download-artifact@v4 + with: + name: restAPI + path: . + + - name: Rename plugin + run: | + mv restAPI-openfire-plugin-assembly.jar restAPI.jar + + - name: Run Openfire + uses: igniterealtime/launch-openfire-action@v1.1.2 + with: + version: 4.9.0 + config: ./test/demoboot-with-additions.xml + plugin: ./restAPI.jar + + - uses: gacts/install-hurl@v1 + + - name: Test the plugin + run: | + hurl --test --report-junit test-results.xml --variables-file test/test.env --jobs 1 test/*.hurl + + - name: Expose Openfire logs + uses: actions/upload-artifact@v4 + if: always() # always run even if the previous step fails + with: + name: Openfire server logs + path: openfire/logs/* + + - name: Publish Test Report + uses: mikepenz/action-junit-report@v4 + if: always() # always run even if the previous step fails + with: + report_paths: 'test-results.xml' + suite_regex: '*' + include_passed: true + detailed_summary: true diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..cb404e3e0 --- /dev/null +++ b/test/README.md @@ -0,0 +1,11 @@ +# Tests + +The tests contained in this folder are written in Hurl (see [docs](https://hurl.dev/docs/manual.html)). + +Install Hurl with instructions as per the documentation. + +Configure the Rest API: + +* Enable it +* Set auth for shared key, and set the value in test.env +* Set `adminConsole.access.allow-wildcards-in-excludes` to true \ No newline at end of file diff --git a/test/chatrooms.hurl b/test/chatrooms.hurl new file mode 100644 index 000000000..1c3027a89 --- /dev/null +++ b/test/chatrooms.hurl @@ -0,0 +1,14 @@ +GET http://localhost:9090/plugins/restapi/v1/chatrooms +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/sessions +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/sessions[not(child::node())]" count == 1 # sessions at the root, with no child nodes + + +GET http://localhost:9090/plugins/restapi/v1/system/readiness/server +Authorization: {{authkey}} +HTTP 200 \ No newline at end of file diff --git a/test/chatservice.hurl b/test/chatservice.hurl new file mode 100644 index 000000000..99f31274b --- /dev/null +++ b/test/chatservice.hurl @@ -0,0 +1,8 @@ +GET http://localhost:9090/plugins/restapi/v1/chatservices +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/chatServices/chatService" count == 1 +xpath "string(/chatServices/chatService/serviceName)" == "conference" +xpath "string(/chatServices/chatService/description)" == "Public Chatrooms" +xpath "string(/chatServices/chatService/hidden)" == "false" diff --git a/test/clustering.hurl b/test/clustering.hurl new file mode 100644 index 000000000..84fd5d471 --- /dev/null +++ b/test/clustering.hurl @@ -0,0 +1,11 @@ +GET {{host}}/plugins/restapi/v1/clustering/status +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "string(/clustering/status)" == "Disabled" + +GET {{host}}/plugins/restapi/v1/clustering/nodes +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/clusterNodes[not(child::node())]" exists diff --git a/test/demoboot-with-additions.xml b/test/demoboot-with-additions.xml new file mode 100644 index 000000000..f65b5841d --- /dev/null +++ b/test/demoboot-with-additions.xml @@ -0,0 +1,64 @@ + + + + + true + secret + potato + + + + + true + + 9090 + 9091 + + + org.jivesoftware.database.EmbeddedConnectionProvider + + + true + en + + + true + + example.org + example.org + + + embedded + + + admin@example.com + admin + + + + john + secret + John Doe + john.doe@example.com + + + jane@example.org + Jane + + + + + jane + secret + Jane Doe + jane.doe@example.com + + + john@example.org + John + + + + + + \ No newline at end of file diff --git a/test/groups.hurl b/test/groups.hurl new file mode 100644 index 000000000..299ec523a --- /dev/null +++ b/test/groups.hurl @@ -0,0 +1,69 @@ + +GET http://localhost:9090/plugins/restapi/v1/groups +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/groups[not(child::node())]" exists # groups at the root, with no child nodes + +POST http://localhost:9090/plugins/restapi/v1/groups +Authorization: {{authkey}} +Content-Type: application/xml +``` + + + group1 + test-group + false + + jane + + + john + + +``` +HTTP 201 + +GET http://localhost:9090/plugins/restapi/v1/groups # check if the group was created +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/groups/group[name='group1']" exists + +GET http://localhost:9090/plugins/restapi/v1/groups/group1 +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/group[name='group1']" exists +xpath "string(/group/description)" == "test-group" + +PUT http://localhost:9090/plugins/restapi/v1/groups/group1 +Authorization: {{authkey}} +Content-Type: application/xml +``` + + + group1 + test-group-updated + false + + jane + + + john + + +``` +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/groups/group1 +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/group[name='group1']" exists +xpath "string(/group/description)" == "test-group-updated" + +DELETE http://localhost:9090/plugins/restapi/v1/groups/group1 +Authorization: {{authkey}} +HTTP 200 + diff --git a/test/messagearchive.hurl b/test/messagearchive.hurl new file mode 100644 index 000000000..7b06bc4f2 --- /dev/null +++ b/test/messagearchive.hurl @@ -0,0 +1,8 @@ +GET http://localhost:9090/plugins/restapi/v1/archive/messages/unread/john@example.org +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "string(/archive/jid)" == "john@example.org" +xpath "string(/archive/count)" == "0" + +# TODO: How to get this >0 ? \ No newline at end of file diff --git a/test/messagebroadcast.hurl b/test/messagebroadcast.hurl new file mode 100644 index 000000000..3bec3dbf5 --- /dev/null +++ b/test/messagebroadcast.hurl @@ -0,0 +1,12 @@ +POST http://localhost:9090/plugins/restapi/v1/messages/users +Authorization: {{authkey}} +Content-Type: application/xml +``` + + + test + +``` +HTTP 201 + +# TODO: What could validate behaviour? \ No newline at end of file diff --git a/test/securitylog.hurl b/test/securitylog.hurl new file mode 100644 index 000000000..6a820dcf3 --- /dev/null +++ b/test/securitylog.hurl @@ -0,0 +1,11 @@ +GET http://localhost:9090/plugins/restapi/v1/logs/security +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/logs/log" count == 0 # TODO: How to make this have 1+ events +#xpath "/logs/log/details" exists +#xpath "/logs/log/logId" exists +#xpath "/logs/log/node" exists +#xpath "/logs/log/summary" exists +#xpath "/logs/log/timestamp" exists +#xpath "/logs/log/username" exists \ No newline at end of file diff --git a/test/sessions.hurl b/test/sessions.hurl new file mode 100644 index 000000000..12d28127e --- /dev/null +++ b/test/sessions.hurl @@ -0,0 +1,20 @@ +GET http://localhost:9090/plugins/restapi/v1/sessions +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/sessions" exists + +GET http://localhost:9090/plugins/restapi/v1/sessions/john +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/sessions" exists + +# TODO: This documents behaviour, but is it correct?? +GET http://localhost:9090/plugins/restapi/v1/sessions/nonexistent +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/sessions" exists + +# TODO: create a session (somehow), then read its props, then kick it with DELETE \ No newline at end of file diff --git a/test/statistics.hurl b/test/statistics.hurl new file mode 100644 index 000000000..4df4014d3 --- /dev/null +++ b/test/statistics.hurl @@ -0,0 +1,6 @@ +GET http://localhost:9090/plugins/restapi/v1/system/statistics/sessions +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/sessions/clusterSessions" exists +xpath "/sessions/localSessions" exists \ No newline at end of file diff --git a/test/system.hurl b/test/system.hurl new file mode 100644 index 000000000..51a8eb62f --- /dev/null +++ b/test/system.hurl @@ -0,0 +1,86 @@ +GET http://localhost:9090/plugins/restapi/v1/system/liveness +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/liveness/deadlock +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/liveness/properties +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/readiness +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/readiness/cluster +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/readiness/connections +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/readiness/plugins +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/readiness/server +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/system/properties +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/properties/property" count > 150 +# TODO test that property with attribute key=admin.authorizedJIDs exists +# TODO test that property with attribute key=plugin.restapi.enabled has value=true + +POST http://localhost:9090/plugins/restapi/v1/system/properties +Authorization: {{authkey}} +Content-Type: application/xml +``` + + +``` +HTTP 201 + +GET http://localhost:9090/plugins/restapi/v1/system/properties/test.key +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/property" count == 1 +# TODO test that property with attribute key=test.key has value=test-value + +PUT http://localhost:9090/plugins/restapi/v1/system/properties/test.key +Authorization: {{authkey}} +Content-Type: application/xml +``` + + +``` +HTTP 200 + +PUT http://localhost:9090/plugins/restapi/v1/system/properties/wrong.key +Authorization: {{authkey}} +Content-Type: application/xml +``` + + +``` +HTTP 404 + +PUT http://localhost:9090/plugins/restapi/v1/system/properties/test.key +Authorization: {{authkey}} +Content-Type: application/xml +``` + + +``` +HTTP 400 + +DELETE http://localhost:9090/plugins/restapi/v1/system/properties/test.key +Authorization: {{authkey}} +HTTP 200 \ No newline at end of file diff --git a/test/test.env b/test/test.env new file mode 100644 index 000000000..6d4bd1e85 --- /dev/null +++ b/test/test.env @@ -0,0 +1,2 @@ +host=http://localhost:9090 +authkey=potato \ No newline at end of file diff --git a/test/users.hurl b/test/users.hurl new file mode 100644 index 000000000..8e450aae6 --- /dev/null +++ b/test/users.hurl @@ -0,0 +1,110 @@ +GET http://localhost:9090/plugins/restapi/v1/users +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/users/user" count == 3 +xpath "/users/user[username='admin']" exists +xpath "/users/user[username='jane']" exists +xpath "/users/user[username='john']" exists +xpath "/users/user[name='John Doe']" exists +xpath "/users/user[email='john.doe@example.com']" exists + +GET http://localhost:9090/plugins/restapi/v1/users?search=john +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/users/user" count == 1 +xpath "/users/user[username='john']" exists +xpath "/users/user[name='John Doe']" exists +xpath "/users/user[email='john.doe@example.com']" exists + +# TODO: Add a user with a property to the demoboot +# How to launch with custom demoboot.xml locally? +#GET http://localhost:9090/plugins/restapi/v1/users?propertyKey=tea&propertyValue=earlgreyhot +#Authorization: {{authkey}} +#HTTP 200 +#[Asserts] +#xpath "/users/user" count == 1 + +POST http://localhost:9090/plugins/restapi/v1/users +Authorization: {{authkey}} +Content-Type: application/xml +``` + + + jeanluc + Jean-Luc + jlp@example.com + makeitso + + + + +``` +HTTP 201 + +GET http://localhost:9090/plugins/restapi/v1/users?propertyKey=tea&propertyValue=earlgreyhot +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/users/user" count == 1 +xpath "string(/users/user/username)" == "jeanluc" +xpath "/users/user[name='Jean-Luc']" exists +xpath "/users/user[email='jlp@example.com']" exists +# TODO xpath for attributes +xpath "/users/user/properties/property" exists + +PUT http://localhost:9090/plugins/restapi/v1/users/jeanluc +Authorization: {{authkey}} +Content-Type: application/xml +``` + + + jeanluc + Jean-Luc + jeanluc@example.com + + + + +``` +HTTP 200 + + +GET http://localhost:9090/plugins/restapi/v1/users/jeanluc +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/user" count == 1 +xpath "string(/user/username)" == "jeanluc" +xpath "/user[name='Jean-Luc']" exists +xpath "/user[email='jlp@example.com']" not exists +xpath "/user[email='jeanluc@example.com']" exists + +DELETE http://localhost:9090/plugins/restapi/v1/users/jeanluc +Authorization: {{authkey}} +HTTP 200 + +GET http://localhost:9090/plugins/restapi/v1/users/jeanluc +Authorization: {{authkey}} +HTTP 404 +[Asserts] +xpath "string(/error/exception)" == "UserNotFoundException" +xpath "string(/error/message)" == "Could not get user" +xpath "string(/error/resource)" == "jeanluc" + +GET http://localhost:9090/plugins/restapi/v1/users/john/roster +Authorization: {{authkey}} +HTTP 200 +[Asserts] +xpath "/roster/rosterItem" count == 1 +xpath "string(/roster/rosterItem/jid)" == "jane@example.org" +xpath "string(/roster/rosterItem/nickname)" == "Jane" +xpath "string(/roster/rosterItem/subscriptionType)" == "3" +xpath "/roster/rosterItem/groups" exists + +# TODO: Roster add/edit/delete + +# TODO: Group membership + +# TODO: User lockouts \ No newline at end of file