diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6f03709f1..24bec9c0a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,3 +8,68 @@ 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: Checkout Openfire actions e.g. 'startCIServer'
+ uses: actions/checkout@v4
+ with:
+ repository: igniterealtime/Openfire
+ path: openfire-ci
+ sparse-checkout: |
+ .github
+ - name: Download a recent Openfire daily build.
+ run: |
+ # This tries to find the most recent daily build, going back 30 days if none are available.
+ #Note that the cache above will cause whatever build that's download to be considered 'todays' build.
+ for i in $(seq 0 30); do
+ STAMP=`date --date="$i day ago" +%F`;
+ echo "Attempting to download Openfire build for $STAMP"
+ curl --fail -L "https://download.igniterealtime.org/openfire/dailybuilds/openfire_$STAMP.tar.gz" -o openfire.tar.gz && break
+ done
+
+ - name: Extract Openfire
+ run: |
+ tar -xzf openfire.tar.gz
+
+ - name: Set up yq
+ uses: frenck/action-setup-yq@v1
+
+ - name: Add extras to the demoboot file
+ run: |
+ yq eval-all '. as $item ireduce ({}; . * $item )' openfire/conf/openfire-demoboot.xml test/demoboot-additions.xml > openfire/conf/openfire-demoboot.xml
+
+ - name: Start CI server from distribution
+ id: startCIServer
+ uses: ./openfire-ci/.github/actions/startserver-action
+ with:
+ distBaseDir: './openfire'
+ domain: 'example.org'
+ ip: '127.0.0.1'
+ - name: Download the built artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: restAPI
+ path: .
+ - name: Install plugin
+ run: |
+ cp restAPI-openfire-plugin-assembly.jar openfire/plugins/restAPI.jar
+ - uses: gacts/install-hurl@v1
+ - name: Test the plugin
+ run: |
+ # Wait for the server to start
+ sleep 30
+ # Test the plugin
+ hurl --test test/restAPI.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/*
\ No newline at end of file
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/demoboot-additions.xml b/test/demoboot-additions.xml
new file mode 100644
index 000000000..894fa8dc2
--- /dev/null
+++ b/test/demoboot-additions.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ true
+ secret
+ potato
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/test/restAPI.hurl b/test/restAPI.hurl
new file mode 100644
index 000000000..0061a0352
--- /dev/null
+++ b/test/restAPI.hurl
@@ -0,0 +1,101 @@
+### CLUSTERING ###
+
+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
+
+
+### USER GROUPS ###
+
+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
+
+
+### CHAT ROOMS ###
+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/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