diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md new file mode 100644 index 0000000..968d7fb --- /dev/null +++ b/src/test/smoketest/SMOKE_TEST.md @@ -0,0 +1,53 @@ +# JPA Server Starter Smoke Tests + +--- + +When updating the supporting HAPI-FHIR version, or making changes to the JPA server starter code itself, it is recommended to run basic smoke tests to ensure the basic functionality of the server is maintained. The goal of these tests is +to provide users a quick way to run groups of tests that correspond to various sections within the +[HAPI-FHIR documentation][Link-HAPI-FHIR-docs]. + +### Requirements +Tests are written in IntelliJ [HTTP Client Request files][Link-HTTP-Client-Req-Intro]. Ultimate edition of IntelliJ +is required to run these tests. + +For more details on integrated tooling and request syntax, there is [documentation available][Link-HTTP-Client-Req-Exploring] +on the jetbrains website, in addition to the [API reference][Link-HTTP-Client-Req-API]. + +### Formatting +Each test file corresponds to a given section within the hapifhir documentation as close as possible. For +example, there is a `plain_server.rest` file, which attemps to smoke test all basic functionality outlined in the section +[within the docs][Link-HAPI-FHIR-docs-plain-server]. + +Individual tests are formatted as follows: +```javascript +### Test Title Here +# +REST-OPERATION ENDPOINT-URL +// Verification Steps +``` + +To run these tests against a specific server, configure the server details within the `http-client.env.json` file. By default, we provide the following: +```json +{ + "default": { + "host": "localhost:8080", + "username": "username", + "password": "password" + } +} +``` + +### Running the Tests +Within IntelliJ, right click the file you wish to run tests in and select the `Run All` option from the menu. + +**Important:** Tests may not work individually when run. Often times, tests need to be run sequentially, as they depend +on resources/references from previous tests to complete. _(An example of this would be adding a Patient, saving the id, +then using that saved id to test if we can successfully PATCH that Patient resource. Without that saved id from the +previous test creating that patient, the PATCH test will fail.)_ + + +[Link-HAPI-FHIR-docs]: https://hapifhir.io/hapi-fhir/docs/ +[Link-HAPI-FHIR-docs-plain-server]: https://hapifhir.io/hapi-fhir/docs/server_plain/server_types.html +[Link-HTTP-Client-Req-Intro]: https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html +[Link-HTTP-Client-Req-Exploring]: https://www.jetbrains.com/help/idea/exploring-http-syntax.html +[Link-HTTP-Client-Req-API]: https://www.jetbrains.com/help/idea/http-response-handling-api-reference.html \ No newline at end of file diff --git a/src/test/smoketest/http-client.env.json b/src/test/smoketest/http-client.env.json new file mode 100644 index 0000000..85b8ef4 --- /dev/null +++ b/src/test/smoketest/http-client.env.json @@ -0,0 +1,7 @@ +{ + "default": { + "host": "localhost:8080", + "username": "username", + "password": "password" + } +} \ No newline at end of file diff --git a/src/test/smoketest/plain_server.rest b/src/test/smoketest/plain_server.rest new file mode 100644 index 0000000..c5856ff --- /dev/null +++ b/src/test/smoketest/plain_server.rest @@ -0,0 +1,223 @@ +### Create Single Patient +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#type_create +POST http://{{host}}/fhir/Patient +Content-Type: application/json + +< smoketestfiles/patient_create.json + +> {% + client.test("Patient created successfully", function() { + client.assert(response.status === 201, "Response status is not 201"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.global.set("single_patient_id", response.body.id); + client.global.set("single_patient_family_name", response.body.name[0].family); +%} + +### Search Single Patient +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#type_search +GET http://{{host}}/fhir/Patient?name={{single_patient_family_name}}&_id={{single_patient_id}} + +> {% + client.test("Patient search successful", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("Total patients found is 1", function() { + const totalFound = response.body.total; + client.assert(totalFound === 1, "Expected '1' match but found '" + totalFound + "'"); + }); + %} + +### Delete Patient +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance_delete +DELETE http://{{host}}/fhir/Patient/{{single_patient_id}} + +> {% + client.test("Patient deleted successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is OperationOutcome", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "OperationOutcome", "Expected 'OperationOutcome' but received '" + resourceType + "'"); + }); +%} + +### Batch Patient Create +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#system_transaction +POST http://{{host}}/fhir/ +Content-Type: application/json + +< smoketestfiles/patient_batch_create.json + +> {% + client.test("Bundle transaction completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("All patient additions successful", function() { + for (var index = 0; index < response.body.entry.length; index++) { + client.assert(response.body.entry[index].response.status === "201 Created", "Expected '201 Created' for patient index " + index + " but received '" + response.body.entry[index].response.status + "'"); + } + }); + const batch_patient_location = response.body.entry[0].response.location; + const indexOfHistory = batch_patient_location.lastIndexOf("/_history"); + trimmed_location = batch_patient_location.substring(0, indexOfHistory); + trimmed_location = trimmed_location.replace("Patient/", "") + client.global.set("batch_patient_id", trimmed_location); +%} + +### Update - Instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance_update +PUT http://{{host}}/fhir/Patient/{{batch_patient_id}} +Content-Type: application/json + +< smoketestfiles/patient_update.json + +> {% + client.test("Bundle transaction completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.test("Test last name updated", function() { + const familyName = response.body.name[0].family; + client.assert(familyName === "Iantoryes", "Expected updated family name 'Iantoryes' but received '" + familyName + "'"); + }); + client.test("Test version number updated", function() { + const versionId = response.body.meta.versionId; + client.assert(versionId === "2", "Expected updated versionId name '2' but received '" + versionId + "'"); + }); +%} + +### Patch - Instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance-level-patch +PATCH http://{{host}}/fhir/Patient/{{batch_patient_id}} +Content-Type: application/json-patch+json + +< smoketestfiles/patient_patch.json + +> {% + client.test("Patch operation completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.test("Test active field patched", function() { + const active = response.body.active; + client.assert(active === false, "Expected updated active 'false' but received '" + active + "'"); + }); +%} + +### History - Server/Type/Instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#history +GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/_history + +> {% + client.test("History completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("Test receive history type", function() { + const type = response.body.type; + client.assert(type === "history", "Expected type 'history' but received '" + type + "'"); + }); +%} + +### Capability Statement +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#system_capabilities +GET http://{{host}}/fhir/metadata + +> {% + client.test("CapabilityStatement fetched successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is CapabilityStatement", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "CapabilityStatement", "Expected 'CapabilityStatement' but received '" + resourceType + "'"); + }); +%} + +### Extended Operations - everything +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations_operations.html +GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/$everything + +> {% + client.test("$everything operation successful", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); +%} + +### Extended Operations - validate +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations_operations.html +POST http://{{host}}/fhir/Patient/{{batch_patient_id}}/$validate + +> {% + client.test("$validate operation successful", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is OperationOutcome", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "OperationOutcome", "Expected 'OperationOutcome' but received '" + resourceType + "'"); + }); +%} \ No newline at end of file diff --git a/src/test/smoketest/smoketestfiles/patient_batch_create.json b/src/test/smoketest/smoketestfiles/patient_batch_create.json new file mode 100644 index 0000000..c476f72 --- /dev/null +++ b/src/test/smoketest/smoketestfiles/patient_batch_create.json @@ -0,0 +1,85 @@ +{ + "resourceType": "Bundle", + "id": "bundle-transaction", + "meta": { + "lastUpdated": "2014-08-18T01:43:30Z" + }, + "type": "transaction", + "entry": [ + { + "resource": { + "resourceType": "Patient", + "text": { + "status": "generated", + "div": "
| Name | \n\t\t\t\t\t\tPeter James \n Chalmers ("Jim")\n | \n\t\t\t\t\t
| Address | \n\t\t\t\t\t\t534 Erewhon, Pleasantville, Vic, 3999 | \n\t\t\t\t\t
| Contacts | \n\t\t\t\t\t\tHome: unknown. Work: (03) 5555 6473 | \n\t\t\t\t\t
| Id | \n\t\t\t\t\t\tMRN: 12345 (Acme Healthcare) | \n\t\t\t\t\t
Update Person resource for Peter James CHALMERS (Jim), MRN: 12345 (Acme Healthcare)
\n\t\t