added test to verify that wizard resource creation works correctly.
update fasten-sources (contains fix for silently ignoring failures during wizard resource creation). fixed file upload error in wizard. Fixed data structure error in wizard for DocumentReference. fixes #393
This commit is contained in:
parent
1b3e43556e
commit
870f6ffee2
|
@ -8,7 +8,7 @@ import (
|
|||
"net/http"
|
||||
)
|
||||
|
||||
// SECURITY: this is a secure endpoint, and should only be called after a double confirmation
|
||||
// UX: this is a secure endpoint, and should only be called after a double confirmation
|
||||
func DeleteAccount(c *gin.Context) {
|
||||
logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry)
|
||||
databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository)
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/fastenhealth/fasten-onprem/backend/pkg"
|
||||
mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock"
|
||||
"github.com/fastenhealth/fasten-onprem/backend/pkg/database"
|
||||
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
|
||||
"github.com/fastenhealth/fasten-onprem/backend/pkg/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Go through this page to understand how this file is structured.
|
||||
// https://pkg.go.dev/github.com/stretchr/testify/suite#section-documentation
|
||||
|
||||
// Define the suite, and absorb the built-in basic suite
|
||||
// functionality from testify - including a T() method which
|
||||
// returns the current testing context
|
||||
type ResourceRelatedHandlerTestSuite struct {
|
||||
suite.Suite
|
||||
MockCtrl *gomock.Controller
|
||||
TestDatabase *os.File
|
||||
|
||||
AppConfig *mock_config.MockInterface
|
||||
AppRepository database.DatabaseRepository
|
||||
AppEventBus event_bus.Interface
|
||||
}
|
||||
|
||||
// BeforeTest has a function to be executed right before the test starts and receives the suite and test names as input
|
||||
func (suite *ResourceRelatedHandlerTestSuite) BeforeTest(suiteName, testName string) {
|
||||
suite.MockCtrl = gomock.NewController(suite.T())
|
||||
|
||||
dbFile, err := ioutil.TempFile("", fmt.Sprintf("%s.*.db", testName))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
suite.TestDatabase = dbFile
|
||||
|
||||
appConfig := mock_config.NewMockInterface(suite.MockCtrl)
|
||||
appConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
|
||||
appConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
|
||||
appConfig.EXPECT().IsSet("database.encryption.key").Return(false).AnyTimes()
|
||||
appConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
|
||||
suite.AppConfig = appConfig
|
||||
|
||||
appRepo, err := database.NewRepository(suite.AppConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
|
||||
suite.AppRepository = appRepo
|
||||
|
||||
suite.AppEventBus = event_bus.NewNoopEventBusServer()
|
||||
|
||||
appRepo.CreateUser(context.Background(), &models.User{
|
||||
Username: "test_username",
|
||||
Password: "test",
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// AfterTest has a function to be executed right after the test finishes and receives the suite and test names as input
|
||||
func (suite *ResourceRelatedHandlerTestSuite) AfterTest(suiteName, testName string) {
|
||||
suite.MockCtrl.Finish()
|
||||
os.Remove(suite.TestDatabase.Name())
|
||||
}
|
||||
|
||||
// In order for 'go test' to run this suite, we need to create
|
||||
// a normal test function and pass our suite to suite.Run
|
||||
func TestResourceRelatedHandlerTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(ResourceRelatedHandlerTestSuite))
|
||||
}
|
||||
|
||||
func (suite *ResourceRelatedHandlerTestSuite) TestResourceRelatedHandlerTestSuite() {
|
||||
//setup
|
||||
w := httptest.NewRecorder()
|
||||
ctx, _ := gin.CreateTestContext(w)
|
||||
ctx.Set(pkg.ContextKeyTypeLogger, logrus.WithField("test", suite.T().Name()))
|
||||
ctx.Set(pkg.ContextKeyTypeDatabase, suite.AppRepository)
|
||||
ctx.Set(pkg.ContextKeyTypeConfig, suite.AppConfig)
|
||||
ctx.Set(pkg.ContextKeyTypeEventBusServer, suite.AppEventBus)
|
||||
ctx.Set(pkg.ContextKeyTypeAuthUsername, "test_username")
|
||||
|
||||
//test
|
||||
relatedJsonForm, relatedJsonWriter := createMultipartFormData(suite.T(), "file", "testdata/related.json") // just pass the file name
|
||||
relatedReq, err := http.NewRequest("POST", "/api/v1/resource/related", &relatedJsonForm)
|
||||
// set the content type, this will contain the boundary.
|
||||
relatedReq.Header.Set("Content-Type", relatedJsonWriter.FormDataContentType())
|
||||
ctx.Request = relatedReq
|
||||
require.NoError(suite.T(), err)
|
||||
|
||||
CreateRelatedResources(ctx)
|
||||
|
||||
var responseWrapper models.ResponseWrapper
|
||||
err = json.Unmarshal(w.Body.Bytes(), &responseWrapper)
|
||||
require.NoError(suite.T(), err)
|
||||
|
||||
summary := responseWrapper.Data.(map[string]interface{})
|
||||
|
||||
//assert
|
||||
assert.EqualValues(suite.T(), http.StatusOK, w.Code)
|
||||
assert.Equal(suite.T(), summary["TotalResources"], 3)
|
||||
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/56696333/1157633
|
||||
func createMultipartFormData(t *testing.T, fieldName, fileName string) (bytes.Buffer, *multipart.Writer) {
|
||||
var b bytes.Buffer
|
||||
var err error
|
||||
w := multipart.NewWriter(&b)
|
||||
var fw io.Writer
|
||||
file := mustOpen(fileName)
|
||||
if fw, err = w.CreateFormFile(fieldName, file.Name()); err != nil {
|
||||
t.Errorf("Error creating writer: %v", err)
|
||||
}
|
||||
if _, err = io.Copy(fw, file); err != nil {
|
||||
t.Errorf("Error with io.Copy: %v", err)
|
||||
}
|
||||
w.Close()
|
||||
return b, w
|
||||
}
|
||||
|
||||
func mustOpen(f string) *os.File {
|
||||
r, err := os.Open(f)
|
||||
if err != nil {
|
||||
pwd, _ := os.Getwd()
|
||||
fmt.Println("PWD: ", pwd)
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"resourceType": "List",
|
||||
"entry": [],
|
||||
"encounter": {
|
||||
"reference": "Encounter/4e4e6346-2350-47c0-ba73-ee0fdaf3a8a7"
|
||||
},
|
||||
"contained": [
|
||||
{
|
||||
"resourceType": "Encounter",
|
||||
"id": "4e4e6346-2350-47c0-ba73-ee0fdaf3a8a7",
|
||||
"serviceType": {
|
||||
"id": "562",
|
||||
"identifier": [
|
||||
{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/service-type",
|
||||
"code": "562",
|
||||
"display": "Test Message"
|
||||
}
|
||||
],
|
||||
"text": "Test Message"
|
||||
},
|
||||
"status": "finished",
|
||||
"participant": [],
|
||||
"period": {
|
||||
"start": "2024-01-04T08:00:00.000Z",
|
||||
"end": "2024-01-27T08:00:00.000Z"
|
||||
},
|
||||
"reasonReference": [],
|
||||
"serviceProvider": {}
|
||||
},
|
||||
{
|
||||
"id": "4e2611e4-df0d-4dae-ad32-1c90537b32af",
|
||||
"resourceType": "Binary",
|
||||
"contentType": "application/pdf",
|
||||
"data": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwogIC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAvTWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0KPj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAgL1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9udAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2JqCgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJUCjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4gCjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAwMDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G"
|
||||
},
|
||||
{
|
||||
"id": "53066674-9e89-41e9-95d9-8eaf24b41ea6",
|
||||
"resourceType": "DocumentReference",
|
||||
"status": "current",
|
||||
"category": [
|
||||
{
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://loinc.org",
|
||||
"code": "11488-4",
|
||||
"display": "Consult Note"
|
||||
}
|
||||
],
|
||||
"text": "Consult Note"
|
||||
}
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"attachment": {
|
||||
"contentType": "application/pdf",
|
||||
"url": "urn:uuid:4e2611e4-df0d-4dae-ad32-1c90537b32af",
|
||||
"title": "test attachment"
|
||||
}
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"encounter": [{
|
||||
"reference": "Encounter/4e4e6346-2350-47c0-ba73-ee0fdaf3a8a7"
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
</div><!-- col -->
|
||||
<div class="col-6 mg-t-10 mg-lg-t-0 mg-l-10">
|
||||
<label for="customFile" class="custom-file-label">{{newAttachmentForm.get('file_name').value || 'Choose file'}}</label>
|
||||
<input id="customFile" (change)="onAttachmentFileChange($event)" class="custom-file-input" formControlName="file_name" type="file">
|
||||
<input id="customFile" (change)="onAttachmentFileChange($event)" class="custom-file-input" type="file">
|
||||
</div><!-- col -->
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
|
@ -41,15 +41,16 @@ export class MedicalRecordWizardAddAttachmentComponent implements OnInit {
|
|||
console.log("onAttachmentFileChange")
|
||||
let fileInput = $event.target as HTMLInputElement;
|
||||
if (fileInput.files && fileInput.files[0]) {
|
||||
let processingFile = fileInput.files[0]
|
||||
let reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
// use a regex to remove data url part
|
||||
const base64String = (reader.result as string).replace('data:', '').replace(/^.+,/, '');
|
||||
this.newAttachmentForm.get('file_content').setValue(base64String)
|
||||
};
|
||||
reader.readAsDataURL(fileInput.files[0]);
|
||||
this.newAttachmentForm.get('file_name').setValue(fileInput.files[0].name)
|
||||
this.newAttachmentForm.get('file_size').setValue(fileInput.files[0].size)
|
||||
reader.readAsDataURL(processingFile);
|
||||
this.newAttachmentForm.get('file_name').setValue(processingFile.name)
|
||||
this.newAttachmentForm.get('file_size').setValue(processingFile.size)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -371,13 +371,12 @@ function resourceAttachmentToR4DocumentReference(resourceStorage: ResourceStorag
|
|||
}
|
||||
}
|
||||
],
|
||||
context: [
|
||||
{
|
||||
encounter: {
|
||||
context: {
|
||||
encounter: [{
|
||||
reference: generateReferenceUriFromResourceOrReference(encounterResource) //Encounter
|
||||
},
|
||||
}],
|
||||
}
|
||||
]
|
||||
|
||||
// date: `${new Date(resourceDocumentReference.date.year,resourceDocumentReference.date.month-1,resourceDocumentReference.date.day).toISOString()}`,
|
||||
} as DocumentReference
|
||||
resourceStorage['DocumentReference'][documentReferenceResource.id] = documentReferenceResource
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<br/>
|
||||
<br/>
|
||||
In <strong>Sandbox mode</strong> Fasten Health cannot access real patient information. You must use Sandbox credentials when authenticating to healthcare sources.
|
||||
<a href="https://github.com/fastenhealth/docs/blob/main/BETA.md#connecting-a-new-source" externalLink>These credentials are available on Github</a>
|
||||
<a href="https://docs.fastenhealth.com/getting-started/sandbox.html#connecting-a-new-source" externalLink>These credentials are available in our Sandbox Guide</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
2
go.mod
2
go.mod
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/dave/jennifer v1.6.1
|
||||
github.com/dominikbraun/graph v0.15.0
|
||||
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
|
||||
github.com/fastenhealth/fasten-sources v0.5.5
|
||||
github.com/fastenhealth/fasten-sources v0.5.6
|
||||
github.com/fastenhealth/gofhir-models v0.0.6
|
||||
github.com/gin-gonic/gin v1.9.0
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -101,8 +101,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fastenhealth/fasten-sources v0.5.5 h1:+vOIG7R/J7QxEZrrfPFfaBzqYU5eDu7x/bc/cgOjvW4=
|
||||
github.com/fastenhealth/fasten-sources v0.5.5/go.mod h1:hUQATAu5KrxKbACJoVt4iEKIGnRtmiOmHz+5TLfyiCM=
|
||||
github.com/fastenhealth/fasten-sources v0.5.6 h1:F4Qmw9ABLSkqkWncoSnChBRDVWLrzkJv+z4z/Ue/fdc=
|
||||
github.com/fastenhealth/fasten-sources v0.5.6/go.mod h1:hUQATAu5KrxKbACJoVt4iEKIGnRtmiOmHz+5TLfyiCM=
|
||||
github.com/fastenhealth/gofhir-models v0.0.6 h1:yJYYaV1eJtHiGEfA1rXLsyOm/9hIi6s2cGoZzGfW1tM=
|
||||
github.com/fastenhealth/gofhir-models v0.0.6/go.mod h1:xB8ikGxu3bUq2b1JYV+CZpHqBaLXpOizFR0eFBCunis=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
|
|
Loading…
Reference in New Issue