mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-13 06:19:05 +02:00
implement integration tests for person operations
This commit is contained in:
28
apps/db-adapter/example-payloads/create_person.bru
Normal file
28
apps/db-adapter/example-payloads/create_person.bru
Normal file
@@ -0,0 +1,28 @@
|
||||
meta {
|
||||
name: create_person
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:8080/person
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
X-User-Id: 1
|
||||
X-User-Name: Alice Wonderland
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"first_name": "Jhon",
|
||||
"last_name": "Doe",
|
||||
"born": "1985-07-01",
|
||||
"limit": 1000,
|
||||
"mothers_first_name": "Mary",
|
||||
"mothers_last_name": "Smith",
|
||||
"email": "jd@example.com"
|
||||
}
|
||||
}
|
19
apps/db-adapter/example-payloads/generate_invite_code.bru
Normal file
19
apps/db-adapter/example-payloads/generate_invite_code.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: generate_invite_code
|
||||
type: http
|
||||
seq: 8
|
||||
}
|
||||
|
||||
patch {
|
||||
url: http://localhost:8080/person/{{id}}
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
X-User-Id: 2
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
id: 10
|
||||
}
|
@@ -9,3 +9,7 @@ get {
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
google_id: alice123
|
||||
}
|
||||
|
19
apps/db-adapter/example-payloads/hard_delete_person.bru
Normal file
19
apps/db-adapter/example-payloads/hard_delete_person.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: hard_delete_person
|
||||
type: http
|
||||
seq: 9
|
||||
}
|
||||
|
||||
delete {
|
||||
url: http://localhost:8080/person/{{id}}
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
X-User-Id: 2
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
id: 10
|
||||
}
|
11
apps/db-adapter/example-payloads/soft_delete_person.bru
Normal file
11
apps/db-adapter/example-payloads/soft_delete_person.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: soft_delete_person
|
||||
type: http
|
||||
seq: 6
|
||||
}
|
||||
|
||||
delete {
|
||||
url: http://localhost:8080/person/{{id}}
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
172
apps/db-adapter/example-payloads/update_person.bru
Normal file
172
apps/db-adapter/example-payloads/update_person.bru
Normal file
@@ -0,0 +1,172 @@
|
||||
meta {
|
||||
name: update_person
|
||||
type: http
|
||||
seq: 8
|
||||
}
|
||||
|
||||
patch {
|
||||
url: http://localhost:8080/person/{{id}}
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
X-User-Id: 2
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"invite_code": "ABCD1234",
|
||||
"first_name": "John",
|
||||
"middle_name": "Fitzgerald",
|
||||
"last_name": "Doe",
|
||||
"titles": [
|
||||
"Dr.",
|
||||
"Prof."
|
||||
],
|
||||
"suffixes": [
|
||||
"Jr."
|
||||
],
|
||||
"extra_names": [
|
||||
"Johnny",
|
||||
"J.D."
|
||||
],
|
||||
"aliases": [
|
||||
"The Professor"
|
||||
],
|
||||
"mothers_first_name": "Jane",
|
||||
"mothers_last_name": "Smith",
|
||||
"born": "1980-05-15",
|
||||
"place_of_birth": "New York, USA",
|
||||
"died": null,
|
||||
"place_of_death": null,
|
||||
"life_events": [
|
||||
{
|
||||
"from": "2000-01-01",
|
||||
"to": "2004-12-31",
|
||||
"description": "Studied at Harvard University"
|
||||
},
|
||||
{
|
||||
"from": "2005-01-01",
|
||||
"to": "2015-01-01",
|
||||
"description": "Worked at NASA"
|
||||
}
|
||||
],
|
||||
"occupations": [
|
||||
"Engineer",
|
||||
"Professor"
|
||||
],
|
||||
"occupation_to_display": "Professor",
|
||||
"others_said": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice Johnson",
|
||||
"relationship": "Colleague",
|
||||
"description": "John was always a dedicated professional.",
|
||||
"url": "https://example.com/testimonial"
|
||||
}
|
||||
],
|
||||
"limit": 10,
|
||||
"photos": [
|
||||
{
|
||||
"url": "https://example.com/photo1.jpg",
|
||||
"description": "Graduation day",
|
||||
"date": "2004-06-15",
|
||||
"name": "Harvard Graduation"
|
||||
}
|
||||
],
|
||||
"videos": [
|
||||
{
|
||||
"url": "https://example.com/video1.mp4",
|
||||
"description": "Interview about Mars mission",
|
||||
"date": "2012-09-10",
|
||||
"name": "NASA Interview"
|
||||
}
|
||||
],
|
||||
"audios": [
|
||||
{
|
||||
"url": "https://example.com/audio1.mp3",
|
||||
"description": "Podcast guest appearance",
|
||||
"date": "2020-11-20",
|
||||
"name": "Science Today Podcast"
|
||||
}
|
||||
],
|
||||
"profile_picture": "https://example.com/profile.jpg",
|
||||
"verified": true,
|
||||
"email": "john.doe@example.com",
|
||||
"phone": "+1-555-123-4567",
|
||||
"residence": {
|
||||
"city": "San Francisco",
|
||||
"country": "USA",
|
||||
"zip_code": "94103",
|
||||
"address_line_1": "123 Main St",
|
||||
"address_line_2": "Apt 4B"
|
||||
},
|
||||
"religion": "Agnostic",
|
||||
"baptized": null,
|
||||
"ideologies": [
|
||||
"Environmentalism",
|
||||
"Humanism"
|
||||
],
|
||||
"blood_type": "O+",
|
||||
"allergies": [
|
||||
"Peanuts",
|
||||
"Pollen"
|
||||
],
|
||||
"medications": [
|
||||
{
|
||||
"name": "Ibuprofen",
|
||||
"description": "Pain relief",
|
||||
"components": "Ibuprofen 400mg",
|
||||
"dosage": "Once a day",
|
||||
"from": "2024-01-01",
|
||||
"to": null
|
||||
}
|
||||
],
|
||||
"medical_conditions": [
|
||||
{
|
||||
"condition": "Hypertension",
|
||||
"diagnosed_on": "2023-03-01"
|
||||
}
|
||||
],
|
||||
"height": 180.5,
|
||||
"weight": 75.0,
|
||||
"hair_colour": "Brown",
|
||||
"skin_colour": "Light",
|
||||
"eye_colour": "Green",
|
||||
"sports": [
|
||||
"Tennis",
|
||||
"Cycling"
|
||||
],
|
||||
"hobbies": [
|
||||
"Painting",
|
||||
"Chess"
|
||||
],
|
||||
"interests": [
|
||||
"Astronomy",
|
||||
"AI Research"
|
||||
],
|
||||
"languages": [
|
||||
{
|
||||
"language": "English",
|
||||
"level": "Native"
|
||||
},
|
||||
{
|
||||
"language": "French",
|
||||
"level": "Intermediate"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"date": "2023-12-01",
|
||||
"title": "Family Tree Interview",
|
||||
"note": "Discussed with John's aunt about his early years.",
|
||||
"url": "https://example.com/note1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
id: 10
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"first_name": "Jhon",
|
||||
"last_name": "Doe",
|
||||
"born": "1985-07-01",
|
||||
"limit": 1000,
|
||||
"mothers_first_name": "Mary",
|
||||
"mothers_last_name": "Smith",
|
||||
"email": "jd@example.com"
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"invite_code": "test-invite-code"
|
||||
}
|
150
apps/db-adapter/integration-tests/payloads/update_person.json
Normal file
150
apps/db-adapter/integration-tests/payloads/update_person.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"invite_code": "ABCD1234",
|
||||
"first_name": "John",
|
||||
"middle_name": "Fitzgerald",
|
||||
"last_name": "Doe",
|
||||
"titles": [
|
||||
"Dr.",
|
||||
"Prof."
|
||||
],
|
||||
"suffixes": [
|
||||
"Jr."
|
||||
],
|
||||
"extra_names": [
|
||||
"Johnny",
|
||||
"J.D."
|
||||
],
|
||||
"aliases": [
|
||||
"The Professor"
|
||||
],
|
||||
"mothers_first_name": "Jane",
|
||||
"mothers_last_name": "Smith",
|
||||
"born": "1980-05-15",
|
||||
"place_of_birth": "New York, USA",
|
||||
"died": null,
|
||||
"place_of_death": null,
|
||||
"life_events": [
|
||||
{
|
||||
"from": "2000-01-01",
|
||||
"to": "2004-12-31",
|
||||
"description": "Studied at Harvard University"
|
||||
},
|
||||
{
|
||||
"from": "2005-01-01",
|
||||
"to": "2015-01-01",
|
||||
"description": "Worked at NASA"
|
||||
}
|
||||
],
|
||||
"occupations": [
|
||||
"Engineer",
|
||||
"Professor"
|
||||
],
|
||||
"occupation_to_display": "Professor",
|
||||
"others_said": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice Johnson",
|
||||
"relationship": "Colleague",
|
||||
"description": "John was always a dedicated professional.",
|
||||
"url": "https://example.com/testimonial"
|
||||
}
|
||||
],
|
||||
"limit": 10,
|
||||
"photos": [
|
||||
{
|
||||
"url": "https://example.com/photo1.jpg",
|
||||
"description": "Graduation day",
|
||||
"date": "2004-06-15",
|
||||
"name": "Harvard Graduation"
|
||||
}
|
||||
],
|
||||
"videos": [
|
||||
{
|
||||
"url": "https://example.com/video1.mp4",
|
||||
"description": "Interview about Mars mission",
|
||||
"date": "2012-09-10",
|
||||
"name": "NASA Interview"
|
||||
}
|
||||
],
|
||||
"audios": [
|
||||
{
|
||||
"url": "https://example.com/audio1.mp3",
|
||||
"description": "Podcast guest appearance",
|
||||
"date": "2020-11-20",
|
||||
"name": "Science Today Podcast"
|
||||
}
|
||||
],
|
||||
"profile_picture": "https://example.com/profile.jpg",
|
||||
"verified": true,
|
||||
"email": "john.doe@example.com",
|
||||
"phone": "+1-555-123-4567",
|
||||
"residence": {
|
||||
"city": "San Francisco",
|
||||
"country": "USA",
|
||||
"zip_code": "94103",
|
||||
"address_line_1": "123 Main St",
|
||||
"address_line_2": "Apt 4B"
|
||||
},
|
||||
"religion": "Agnostic",
|
||||
"baptized": null,
|
||||
"ideologies": [
|
||||
"Environmentalism",
|
||||
"Humanism"
|
||||
],
|
||||
"blood_type": "O+",
|
||||
"allergies": [
|
||||
"Peanuts",
|
||||
"Pollen"
|
||||
],
|
||||
"medications": [
|
||||
{
|
||||
"name": "Ibuprofen",
|
||||
"description": "Pain relief",
|
||||
"components": "Ibuprofen 400mg",
|
||||
"dosage": "Once a day",
|
||||
"from": "2024-01-01",
|
||||
"to": null
|
||||
}
|
||||
],
|
||||
"medical_conditions": [
|
||||
{
|
||||
"condition": "Hypertension",
|
||||
"diagnosed_on": "2023-03-01"
|
||||
}
|
||||
],
|
||||
"height": 180.5,
|
||||
"weight": 75.0,
|
||||
"hair_colour": "Brown",
|
||||
"skin_colour": "Light",
|
||||
"eye_colour": "Green",
|
||||
"sports": [
|
||||
"Tennis",
|
||||
"Cycling"
|
||||
],
|
||||
"hobbies": [
|
||||
"Painting",
|
||||
"Chess"
|
||||
],
|
||||
"interests": [
|
||||
"Astronomy",
|
||||
"AI Research"
|
||||
],
|
||||
"languages": [
|
||||
{
|
||||
"language": "English",
|
||||
"level": "Native"
|
||||
},
|
||||
{
|
||||
"language": "French",
|
||||
"level": "Intermediate"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"date": "2023-12-01",
|
||||
"title": "Family Tree Interview",
|
||||
"note": "Discussed with John's aunt about his early years.",
|
||||
"url": "https://example.com/note1"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,16 +1,187 @@
|
||||
package integration_tests
|
||||
|
||||
func CreatePerson() {
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api"
|
||||
)
|
||||
|
||||
//go:embed payloads\create_other_person.json
|
||||
var create_other_person []byte
|
||||
|
||||
func CreatePersonTest(dbAdapterUri string, client *http.Client) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, url, bytes.NewBuffer(create_other_person))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "0")
|
||||
req.Header.Set("X-User-Name", "application/json")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody map[string]any
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
_, ok := responseBody["Id"]
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, "Jhon", responseBody["Props"].(map[string]any)["first_name"])
|
||||
require.Equal(t, "Doe", responseBody["Props"].(map[string]any)["last_name"])
|
||||
}
|
||||
}
|
||||
|
||||
func GetPersonById() {
|
||||
func GetPersonById(dbAdapterUri string, client *http.Client) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person/0"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, url, http.NoBody)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "0")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody map[string]any
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
_, ok := responseBody["Id"]
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, "Alice", responseBody["Props"].(map[string]any)["first_name"])
|
||||
require.Equal(t, "Wonderland", responseBody["Props"].(map[string]any)["last_name"])
|
||||
}
|
||||
}
|
||||
|
||||
func SoftDeletePerson() {
|
||||
func SoftDeletePersonTest(dbAdapterUri string, client *http.Client) func(t *testing.T) { //nolint:dupl,lll // This just does not worth abstracting anymore
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person/0"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodDelete, url, http.NoBody)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "0")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody map[string]any
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
require.Equal(t, "Person soft deleted", responseBody["description"])
|
||||
}
|
||||
}
|
||||
|
||||
func UpdatePerson() {
|
||||
//go:embed payloads\update_person.json
|
||||
var update_person []byte
|
||||
|
||||
func UpdatePersonTest(dbAdapterUri string, client *http.Client) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person/1"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodPatch, url, bytes.NewBuffer(update_person))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "1")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody map[string]any
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
_, ok := responseBody["Id"]
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, "John", responseBody["Props"].(map[string]any)["first_name"])
|
||||
require.Equal(t, "Doe", responseBody["Props"].(map[string]any)["last_name"])
|
||||
require.Equal(t, "ABCD1234", responseBody["Props"].(map[string]any)["invite_code"])
|
||||
}
|
||||
}
|
||||
|
||||
func HardDeletePerson() {
|
||||
//go:embed payloads\generate_invite_code.json
|
||||
var generate_invite_code []byte
|
||||
|
||||
func UpdatePersonWithInviteCodeTest(dbAdapterUri string, client *http.Client) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person/1"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodPatch, url, bytes.NewBuffer(generate_invite_code))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "0")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody api.Person
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
require.NotNil(t, responseBody.Id)
|
||||
|
||||
require.Equal(t, "test-invite-code", *responseBody.Props.InviteCode)
|
||||
}
|
||||
}
|
||||
|
||||
func HardDeletePersonTest(dbAdapterUri string, client *http.Client) func(t *testing.T) { //nolint:dupl,lll // This just does not worth abstracting anymore
|
||||
return func(t *testing.T) {
|
||||
url := dbAdapterUri + "/person/0/hard-delete"
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodDelete, url, http.NoBody)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", "0")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var responseBody map[string]any
|
||||
err = json.NewDecoder(resp.Body).Decode(&responseBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate the response
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
require.Equal(t, "Person hard deleted", responseBody["description"])
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j/dbtype"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/api/auth"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api"
|
||||
@@ -38,8 +39,9 @@ func (srv *server) CreatePerson(c *gin.Context, params api.CreatePersonParams) {
|
||||
|
||||
qctx, qCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout)
|
||||
defer qCancel()
|
||||
convertedPerson := memgraph.StructToMap(person)
|
||||
res, err := trs.Run(qctx, memgraph.CreatePersonCypherQuery, map[string]any{
|
||||
"Person": *person,
|
||||
"Person": convertedPerson,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
|
||||
@@ -54,17 +56,19 @@ func (srv *server) CreatePerson(c *gin.Context, params api.CreatePersonParams) {
|
||||
return
|
||||
}
|
||||
|
||||
personId, ok := singleRes.Get("id")
|
||||
createdPerson, ok := singleRes.Get("person")
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": "Person ID not found in response"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": "Person not found in db response"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
personId := createdPerson.(dbtype.Node).Id //nolint:staticcheck // this is a difference in neo4j and memgraph
|
||||
|
||||
actx, acancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout)
|
||||
defer acancel()
|
||||
_, aErr := trs.Run(actx, memgraph.CreateAdminRelationshipCypherQuery, map[string]any{
|
||||
"id2": personId.(int),
|
||||
"id2": personId,
|
||||
"id1": params.XUserID,
|
||||
})
|
||||
if aErr != nil {
|
||||
@@ -80,10 +84,10 @@ func (srv *server) CreatePerson(c *gin.Context, params api.CreatePersonParams) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, singleRes.AsMap())
|
||||
c.JSON(http.StatusOK, createdPerson)
|
||||
}
|
||||
|
||||
func (srv *server) GetPersonById(c *gin.Context, id int, params api.GetPersonByIdParams) { //nolint:dupl // not worth abstracting more
|
||||
func (srv *server) GetPersonById(c *gin.Context, id int, params api.GetPersonByIdParams) {
|
||||
session := srv.createSessionWithTimeout(c.Request.Context())
|
||||
defer closeSession(c.Request.Context(), srv.logger, session, srv.dbOpTimeout)
|
||||
|
||||
@@ -107,7 +111,7 @@ func (srv *server) GetPersonById(c *gin.Context, id int, params api.GetPersonByI
|
||||
c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (srv *server) SoftDeletePerson(c *gin.Context, id int, params api.SoftDeletePersonParams) {
|
||||
func (srv *server) SoftDeletePerson(c *gin.Context, id int, params api.SoftDeletePersonParams) { //nolint:dupl,lll // This just does not worth abstracting anymore
|
||||
session := srv.createSessionWithTimeout(c.Request.Context())
|
||||
defer closeSession(c.Request.Context(), srv.logger, session, srv.dbOpTimeout)
|
||||
|
||||
@@ -128,7 +132,7 @@ func (srv *server) SoftDeletePerson(c *gin.Context, id int, params api.SoftDelet
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, map[string]string{"description": "Person soft deleted"})
|
||||
c.JSON(http.StatusOK, gin.H{"description": "Person soft deleted"})
|
||||
}
|
||||
|
||||
func (srv *server) UpdatePerson(c *gin.Context, id int, params api.UpdatePersonParams) {
|
||||
@@ -176,12 +180,14 @@ func (srv *server) HardDeletePerson(c *gin.Context, id int, params api.HardDelet
|
||||
|
||||
qctx, qCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout)
|
||||
defer qCancel()
|
||||
res, err := session.ExecuteWrite(qctx, memgraph.HardDeletePerson(qctx, id))
|
||||
_, err := session.ExecuteWrite(qctx, memgraph.HardDeletePerson(qctx, id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, res)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"description": "Person hard deleted",
|
||||
})
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j/dbtype"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api"
|
||||
"go.uber.org/zap"
|
||||
@@ -36,8 +37,9 @@ func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params ap
|
||||
|
||||
qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout)
|
||||
defer qCancel()
|
||||
convertedPerson := memgraph.StructToMap(requestBody.Person)
|
||||
res, err := trs.Run(qctx, memgraph.CreatePersonCypherQuery, map[string]any{
|
||||
"Person": requestBody.Person,
|
||||
"Person": convertedPerson,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
|
||||
@@ -51,17 +53,19 @@ func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params ap
|
||||
|
||||
return
|
||||
}
|
||||
personID, ok := singleRes.Get("id")
|
||||
createdPerson, ok := singleRes.Get("person")
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": "Person ID not found in response"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
personID := createdPerson.(dbtype.Node).Id //nolint:staticcheck // this is a difference in neo4j and memgraph
|
||||
|
||||
actx, acancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout)
|
||||
defer acancel()
|
||||
_, aErr := trs.Run(actx, memgraph.CreateAdminRelationshipCypherQuery, map[string]any{
|
||||
"id2": personID.(int),
|
||||
"id2": personID,
|
||||
"id1": params.XUserID,
|
||||
})
|
||||
if aErr != nil {
|
||||
@@ -73,36 +77,38 @@ func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params ap
|
||||
relCtx, relCCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout)
|
||||
defer relCCancel()
|
||||
|
||||
convertedRelationship := memgraph.StructToMap(requestBody.Relationship)
|
||||
|
||||
var relationShipResultRaw any
|
||||
var relationshipError error
|
||||
switch *requestBody.Type {
|
||||
case api.CreatePersonAndRelationshipJSONBodyTypeChild:
|
||||
relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateChildParentRelationshipCypherQuery, map[string]any{
|
||||
"childId": personID.(int),
|
||||
"childId": personID,
|
||||
"parentId": id,
|
||||
"childRelationship": requestBody.Relationship,
|
||||
"parentRelationship": requestBody.Relationship,
|
||||
"childRelationship": convertedRelationship,
|
||||
"parentRelationship": convertedRelationship,
|
||||
})
|
||||
case api.CreatePersonAndRelationshipJSONBodyTypeParent:
|
||||
relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateChildParentRelationshipCypherQuery, map[string]any{
|
||||
"childId": id,
|
||||
"parentId": personID.(int),
|
||||
"childRelationship": requestBody.Relationship,
|
||||
"parentRelationship": requestBody.Relationship,
|
||||
"parentId": personID,
|
||||
"childRelationship": convertedRelationship,
|
||||
"parentRelationship": convertedRelationship,
|
||||
})
|
||||
case api.CreatePersonAndRelationshipJSONBodyTypeSibling:
|
||||
relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateSiblingRelationshipCypherQuery, map[string]any{
|
||||
"id1": id,
|
||||
"id2": personID.(int),
|
||||
"Relationship1": requestBody.Relationship,
|
||||
"Relationship2": requestBody.Relationship,
|
||||
"id2": personID,
|
||||
"Relationship1": convertedRelationship,
|
||||
"Relationship2": convertedRelationship,
|
||||
})
|
||||
case api.CreatePersonAndRelationshipJSONBodyTypeSpouse:
|
||||
relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateSpouseRelationshipCypherQuery, map[string]any{
|
||||
"id1": personID.(int),
|
||||
"id1": personID,
|
||||
"id2": id,
|
||||
"Relationship1": requestBody.Relationship,
|
||||
"Relationship2": requestBody.Relationship,
|
||||
"Relationship1": convertedRelationship,
|
||||
"Relationship2": convertedRelationship,
|
||||
})
|
||||
default:
|
||||
c.JSON(http.StatusBadRequest, gin.H{"msg": "invalid relationship type"})
|
||||
|
@@ -41,7 +41,12 @@ func GetPersonById(ctx context.Context, id int) neo4j.ManagedTransactionWork {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return record.AsMap(), nil
|
||||
person, ok := record.Get("person")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("person not found")
|
||||
}
|
||||
|
||||
return person, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +66,12 @@ func UpdatePerson(ctx context.Context, id int, person *api.PersonProperties) neo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return record.AsMap(), nil
|
||||
person, ok := record.Get("person")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("person not found")
|
||||
}
|
||||
|
||||
return person, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
MATCH (n:Person {id: $id})
|
||||
MATCH (n:Person)
|
||||
WHERE id(n)=$id
|
||||
SET n:DeletedPerson
|
||||
REMOVE n:Person
|
||||
RETURN labels(n) AS labels, n AS person
|
@@ -71,6 +71,8 @@ func StructToMap(input any) map[string]any {
|
||||
switch val.Kind() {
|
||||
case reflect.Struct:
|
||||
result[jsonKey] = StructToMap(val.Interface())
|
||||
case reflect.Slice, reflect.Array:
|
||||
result[jsonKey] = processSlice(val)
|
||||
default:
|
||||
result[jsonKey] = val.Interface()
|
||||
}
|
||||
@@ -104,3 +106,19 @@ func isPreservedType(v any) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func processSlice(val reflect.Value) []any {
|
||||
slice := make([]any, val.Len())
|
||||
for i := range val.Len() {
|
||||
item := val.Index(i).Interface()
|
||||
if isPreservedType(item) {
|
||||
slice[i] = item
|
||||
} else if reflect.ValueOf(item).Kind() == reflect.Struct {
|
||||
slice[i] = StructToMap(item)
|
||||
} else {
|
||||
slice[i] = item
|
||||
}
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -11,6 +12,8 @@ import (
|
||||
)
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
net, err := network.New(t.Context())
|
||||
if err != nil {
|
||||
t.Logf("failed to create network: %s", err)
|
||||
@@ -97,5 +100,18 @@ func TestIntegration(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
dbAdapterURI := "http://" + dbAdapterHost + ":" + dbAdapterPort.Port()
|
||||
|
||||
t.Run("TestCreatePersonByGoogleIdAndGetById", integration_tests.TestPersonGoogle(dbAdapterURI))
|
||||
IntegrationTestFlow(dbAdapterURI)(t)
|
||||
}
|
||||
|
||||
func IntegrationTestFlow(dbAdapterURI string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
client := &http.Client{}
|
||||
t.Run("CreatePersonByGoogleIdAndGetById", integration_tests.TestPersonGoogle(dbAdapterURI))
|
||||
t.Run("CreatePerson", integration_tests.CreatePersonTest(dbAdapterURI, client))
|
||||
t.Run("UpdatePerson", integration_tests.UpdatePersonTest(dbAdapterURI, client))
|
||||
t.Run("AddInviteCodeToPerson", integration_tests.UpdatePersonWithInviteCodeTest(dbAdapterURI, client))
|
||||
t.Run("GetPersonById", integration_tests.GetPersonById(dbAdapterURI, client))
|
||||
t.Run("SoftDeletePerson", integration_tests.SoftDeletePersonTest(dbAdapterURI, client))
|
||||
t.Run("HardDeletePerson", integration_tests.HardDeletePersonTest(dbAdapterURI, client))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user