@stamhoofd/backend 2.78.4 → 2.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +1 -1
- package/package.json +13 -12
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +1 -1
- package/src/endpoints/auth/CreateAdminEndpoint.ts +1 -1
- package/src/endpoints/auth/CreateTokenEndpoint.ts +1 -1
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
- package/src/endpoints/auth/PatchUserEndpoint.ts +1 -1
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +1964 -4
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +175 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +1 -1
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +2 -2
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +7 -1
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +3 -23
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +12 -0
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +2 -3
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +164 -0
- package/src/helpers/AdminPermissionChecker.ts +22 -1
- package/src/helpers/AuthenticatedStructures.ts +77 -20
- package/src/helpers/ForwardHandler.test.ts +16 -5
- package/src/helpers/ForwardHandler.ts +21 -9
- package/src/helpers/MemberUserSyncer.test.ts +822 -0
- package/src/helpers/MemberUserSyncer.ts +137 -108
- package/src/helpers/TagHelper.ts +3 -3
- package/src/seeds/1734596144-fill-previous-period-id.ts +1 -1
- package/src/seeds/1741008870-fix-auditlog-description.ts +50 -0
- package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +88 -0
- package/src/services/PlatformMembershipService.ts +7 -2
- package/src/services/SSOService.ts +1 -1
- package/tests/e2e/register.test.ts +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Database } from '@simonbackx/simple-database';
|
|
2
|
-
import { PatchableArray, PatchMap } from '@simonbackx/simple-encoding';
|
|
2
|
+
import { PatchableArray, PatchableArrayAutoEncoder, PatchMap } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { Endpoint, Request } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { GroupFactory, MemberFactory, OrganizationFactory, OrganizationTagFactory, Platform, RegistrationFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
5
|
-
import { MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, Permissions, PermissionsResourceType, RecordCategory, RecordSettings, RecordTextAnswer, ResourcePermissions,
|
|
5
|
+
import { Address, Country, EmergencyContact, MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, Permissions, PermissionsResourceType, RecordCategory, RecordSettings, RecordTextAnswer, ResourcePermissions, ReviewTime, ReviewTimes } from '@stamhoofd/structures';
|
|
6
6
|
import { TestUtils } from '@stamhoofd/test-utils';
|
|
7
7
|
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
8
8
|
import { PatchOrganizationMembersEndpoint } from './PatchOrganizationMembersEndpoint';
|
|
@@ -579,7 +579,7 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
579
579
|
],
|
|
580
580
|
});
|
|
581
581
|
|
|
582
|
-
const platform = await Platform.
|
|
582
|
+
const platform = await Platform.getForEditing();
|
|
583
583
|
platform.config.recordsConfiguration.recordCategories.push(recordCategory);
|
|
584
584
|
await platform.save();
|
|
585
585
|
|
|
@@ -657,7 +657,7 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
657
657
|
],
|
|
658
658
|
});
|
|
659
659
|
|
|
660
|
-
const platform = await Platform.
|
|
660
|
+
const platform = await Platform.getForEditing();
|
|
661
661
|
platform.config.recordsConfiguration.recordCategories.push(recordCategory);
|
|
662
662
|
await platform.save();
|
|
663
663
|
|
|
@@ -723,4 +723,1964 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
723
723
|
});
|
|
724
724
|
});
|
|
725
725
|
});
|
|
726
|
+
|
|
727
|
+
describe('Parents', () => {
|
|
728
|
+
test('Setting updatedAt for one parent, changes it for the whole family', async () => {
|
|
729
|
+
const user = await new UserFactory({}).create();
|
|
730
|
+
|
|
731
|
+
const parent1 = Parent.create({
|
|
732
|
+
firstName: 'Linda',
|
|
733
|
+
lastName: 'Doe',
|
|
734
|
+
email: 'linda@example.com',
|
|
735
|
+
alternativeEmails: ['linda@work.com'],
|
|
736
|
+
phone: '+32412345678',
|
|
737
|
+
address: Address.create({
|
|
738
|
+
street: 'Main street 1',
|
|
739
|
+
postalCode: '1000',
|
|
740
|
+
city: 'Brussels',
|
|
741
|
+
country: Country.Belgium,
|
|
742
|
+
}),
|
|
743
|
+
nationalRegisterNumber: '93042012345',
|
|
744
|
+
updatedAt: new Date(0),
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
const member1 = await new MemberFactory({
|
|
748
|
+
user,
|
|
749
|
+
details: MemberDetails.create({
|
|
750
|
+
firstName: 'John',
|
|
751
|
+
lastName: 'Doe',
|
|
752
|
+
parents: [parent1],
|
|
753
|
+
}),
|
|
754
|
+
}).create();
|
|
755
|
+
|
|
756
|
+
const member2 = await new MemberFactory({
|
|
757
|
+
user,
|
|
758
|
+
details: MemberDetails.create({
|
|
759
|
+
firstName: 'Jane',
|
|
760
|
+
lastName: 'Doe',
|
|
761
|
+
parents: [parent1],
|
|
762
|
+
}),
|
|
763
|
+
}).create();
|
|
764
|
+
|
|
765
|
+
// Parent3 was reviewed last, so has priority
|
|
766
|
+
const member3 = await new MemberFactory({
|
|
767
|
+
user,
|
|
768
|
+
details: MemberDetails.create({
|
|
769
|
+
firstName: 'Bob',
|
|
770
|
+
lastName: 'Doe',
|
|
771
|
+
parents: [parent1],
|
|
772
|
+
}),
|
|
773
|
+
}).create();
|
|
774
|
+
|
|
775
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
776
|
+
const admin = await new UserFactory({
|
|
777
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
778
|
+
}).create();
|
|
779
|
+
const token = await Token.createToken(admin);
|
|
780
|
+
|
|
781
|
+
const arr: Body = new PatchableArray();
|
|
782
|
+
const d = new Date();
|
|
783
|
+
const parentsPatch = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
784
|
+
parentsPatch.addPatch(
|
|
785
|
+
Parent.patch({
|
|
786
|
+
id: parent1.id,
|
|
787
|
+
updatedAt: d,
|
|
788
|
+
}),
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
792
|
+
id: member1.id,
|
|
793
|
+
details: MemberDetails.patch({
|
|
794
|
+
parents: parentsPatch,
|
|
795
|
+
}),
|
|
796
|
+
});
|
|
797
|
+
arr.addPatch(patch);
|
|
798
|
+
|
|
799
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
800
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
801
|
+
const response = await testServer.test(endpoint, request);
|
|
802
|
+
|
|
803
|
+
// Check returned
|
|
804
|
+
expect(response.status).toBe(200);
|
|
805
|
+
expect(response.body.members.length).toBe(1);
|
|
806
|
+
|
|
807
|
+
// Load parents again
|
|
808
|
+
await member1.refresh();
|
|
809
|
+
await member2.refresh();
|
|
810
|
+
await member3.refresh();
|
|
811
|
+
|
|
812
|
+
// Check all parents equal
|
|
813
|
+
const expectedParent = Parent.create({
|
|
814
|
+
...parent1,
|
|
815
|
+
updatedAt: d,
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
819
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
820
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
test('Patches without updatedAt are handled correctly and applied to the most recent parent', async () => {
|
|
824
|
+
const user = await new UserFactory({}).create();
|
|
825
|
+
|
|
826
|
+
const mostRecentParent = Parent.create({
|
|
827
|
+
firstName: 'Linda',
|
|
828
|
+
lastName: 'Doe',
|
|
829
|
+
email: 'linda@example.com',
|
|
830
|
+
alternativeEmails: ['linda@work.com'],
|
|
831
|
+
phone: '+32412345678',
|
|
832
|
+
address: Address.create({
|
|
833
|
+
street: 'Main street 1',
|
|
834
|
+
postalCode: '1000',
|
|
835
|
+
city: 'Brussels',
|
|
836
|
+
country: Country.Belgium,
|
|
837
|
+
}),
|
|
838
|
+
nationalRegisterNumber: '93042012347',
|
|
839
|
+
updatedAt: new Date(10_000),
|
|
840
|
+
createdAt: new Date(0),
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
const outOfDateParent = Parent.create({
|
|
844
|
+
id: mostRecentParent.id,
|
|
845
|
+
firstName: 'Linda',
|
|
846
|
+
lastName: 'Doe',
|
|
847
|
+
email: 'linda@example.com',
|
|
848
|
+
alternativeEmails: ['linda@work.com'],
|
|
849
|
+
phone: '+32412345678',
|
|
850
|
+
address: Address.create({
|
|
851
|
+
street: 'Main street 1',
|
|
852
|
+
postalCode: '1000',
|
|
853
|
+
city: 'Brussels',
|
|
854
|
+
country: Country.Belgium,
|
|
855
|
+
}),
|
|
856
|
+
nationalRegisterNumber: '93042012345',
|
|
857
|
+
updatedAt: new Date(0),
|
|
858
|
+
createdAt: new Date(200),
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
const member1 = await new MemberFactory({
|
|
862
|
+
user,
|
|
863
|
+
details: MemberDetails.create({
|
|
864
|
+
firstName: 'John',
|
|
865
|
+
lastName: 'Doe',
|
|
866
|
+
parents: [outOfDateParent],
|
|
867
|
+
}),
|
|
868
|
+
}).create();
|
|
869
|
+
|
|
870
|
+
const member2 = await new MemberFactory({
|
|
871
|
+
user,
|
|
872
|
+
details: MemberDetails.create({
|
|
873
|
+
firstName: 'Jane',
|
|
874
|
+
lastName: 'Doe',
|
|
875
|
+
parents: [outOfDateParent],
|
|
876
|
+
}),
|
|
877
|
+
}).create();
|
|
878
|
+
|
|
879
|
+
// Parent3 was reviewed last, so has priority
|
|
880
|
+
const member3 = await new MemberFactory({
|
|
881
|
+
user,
|
|
882
|
+
details: MemberDetails.create({
|
|
883
|
+
firstName: 'Bob',
|
|
884
|
+
lastName: 'Doe',
|
|
885
|
+
parents: [mostRecentParent],
|
|
886
|
+
}),
|
|
887
|
+
}).create();
|
|
888
|
+
|
|
889
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
890
|
+
const admin = await new UserFactory({
|
|
891
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
892
|
+
}).create();
|
|
893
|
+
const token = await Token.createToken(admin);
|
|
894
|
+
|
|
895
|
+
const arr: Body = new PatchableArray();
|
|
896
|
+
const parentsPatch = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
897
|
+
parentsPatch.addPatch(
|
|
898
|
+
Parent.patch({
|
|
899
|
+
id: outOfDateParent.id,
|
|
900
|
+
email: 'changed@example.com',
|
|
901
|
+
}),
|
|
902
|
+
);
|
|
903
|
+
|
|
904
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
905
|
+
id: member2.id,
|
|
906
|
+
details: MemberDetails.patch({
|
|
907
|
+
parents: parentsPatch,
|
|
908
|
+
}),
|
|
909
|
+
});
|
|
910
|
+
arr.addPatch(patch);
|
|
911
|
+
|
|
912
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
913
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
914
|
+
const response = await testServer.test(endpoint, request);
|
|
915
|
+
|
|
916
|
+
// Check returned
|
|
917
|
+
expect(response.status).toBe(200);
|
|
918
|
+
expect(response.body.members.length).toBe(1);
|
|
919
|
+
|
|
920
|
+
// Load parents again
|
|
921
|
+
await member1.refresh();
|
|
922
|
+
await member2.refresh();
|
|
923
|
+
await member3.refresh();
|
|
924
|
+
|
|
925
|
+
// Check all parents equal
|
|
926
|
+
const expectedParent = Parent.create({
|
|
927
|
+
...mostRecentParent,
|
|
928
|
+
email: 'changed@example.com',
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
932
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
933
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
test('Patches without updatedAt are handled correctly and applied to the most recent parent when merging', async () => {
|
|
937
|
+
const user = await new UserFactory({}).create();
|
|
938
|
+
|
|
939
|
+
const mostRecentParent = Parent.create({
|
|
940
|
+
firstName: 'Linda',
|
|
941
|
+
lastName: 'Doe',
|
|
942
|
+
email: 'linda@example.com',
|
|
943
|
+
alternativeEmails: ['linda@work.com'],
|
|
944
|
+
phone: '+32412345678',
|
|
945
|
+
address: Address.create({
|
|
946
|
+
street: 'Main street 1',
|
|
947
|
+
postalCode: '1000',
|
|
948
|
+
city: 'Brussels',
|
|
949
|
+
country: Country.Belgium,
|
|
950
|
+
}),
|
|
951
|
+
nationalRegisterNumber: '93042012347',
|
|
952
|
+
updatedAt: new Date(10_000),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
const outOfDateParent = Parent.create({
|
|
956
|
+
firstName: 'Linda',
|
|
957
|
+
lastName: 'Doe',
|
|
958
|
+
email: 'linda@example.com',
|
|
959
|
+
alternativeEmails: ['linda+oldest@work.com'],
|
|
960
|
+
phone: '+32412345678',
|
|
961
|
+
address: Address.create({
|
|
962
|
+
street: 'Main street 1',
|
|
963
|
+
postalCode: '1000',
|
|
964
|
+
city: 'Brussels',
|
|
965
|
+
country: Country.Belgium,
|
|
966
|
+
}),
|
|
967
|
+
nationalRegisterNumber: '93042012345',
|
|
968
|
+
updatedAt: new Date(0),
|
|
969
|
+
createdAt: new Date(0),
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
const outOfDateParent2 = Parent.create({
|
|
973
|
+
firstName: 'Linda',
|
|
974
|
+
lastName: 'Doe',
|
|
975
|
+
email: 'linda@example.com',
|
|
976
|
+
alternativeEmails: ['linda@work.com'],
|
|
977
|
+
phone: '+32412345678',
|
|
978
|
+
address: Address.create({
|
|
979
|
+
street: 'Main street 1',
|
|
980
|
+
postalCode: '1000',
|
|
981
|
+
city: 'Brussels',
|
|
982
|
+
country: Country.Belgium,
|
|
983
|
+
}),
|
|
984
|
+
nationalRegisterNumber: '93042012345',
|
|
985
|
+
updatedAt: new Date(1000),
|
|
986
|
+
});
|
|
987
|
+
|
|
988
|
+
const member1 = await new MemberFactory({
|
|
989
|
+
user,
|
|
990
|
+
details: MemberDetails.create({
|
|
991
|
+
firstName: 'John',
|
|
992
|
+
lastName: 'Doe',
|
|
993
|
+
parents: [outOfDateParent],
|
|
994
|
+
}),
|
|
995
|
+
}).create();
|
|
996
|
+
|
|
997
|
+
const member2 = await new MemberFactory({
|
|
998
|
+
user,
|
|
999
|
+
details: MemberDetails.create({
|
|
1000
|
+
firstName: 'Jane',
|
|
1001
|
+
lastName: 'Doe',
|
|
1002
|
+
parents: [outOfDateParent2],
|
|
1003
|
+
}),
|
|
1004
|
+
}).create();
|
|
1005
|
+
|
|
1006
|
+
// Parent3 was reviewed last, so has priority
|
|
1007
|
+
const member3 = await new MemberFactory({
|
|
1008
|
+
user,
|
|
1009
|
+
details: MemberDetails.create({
|
|
1010
|
+
firstName: 'Bob',
|
|
1011
|
+
lastName: 'Doe',
|
|
1012
|
+
parents: [mostRecentParent],
|
|
1013
|
+
}),
|
|
1014
|
+
}).create();
|
|
1015
|
+
|
|
1016
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
1017
|
+
const admin = await new UserFactory({
|
|
1018
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1019
|
+
}).create();
|
|
1020
|
+
const token = await Token.createToken(admin);
|
|
1021
|
+
|
|
1022
|
+
const arr: Body = new PatchableArray();
|
|
1023
|
+
const parentsPatch = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1024
|
+
parentsPatch.addPatch(
|
|
1025
|
+
Parent.patch({
|
|
1026
|
+
id: outOfDateParent.id,
|
|
1027
|
+
email: 'changed@example.com',
|
|
1028
|
+
}),
|
|
1029
|
+
);
|
|
1030
|
+
|
|
1031
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1032
|
+
id: member2.id,
|
|
1033
|
+
details: MemberDetails.patch({
|
|
1034
|
+
parents: parentsPatch,
|
|
1035
|
+
}),
|
|
1036
|
+
});
|
|
1037
|
+
arr.addPatch(patch);
|
|
1038
|
+
|
|
1039
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1040
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1041
|
+
const response = await testServer.test(endpoint, request);
|
|
1042
|
+
|
|
1043
|
+
// Check returned
|
|
1044
|
+
expect(response.status).toBe(200);
|
|
1045
|
+
expect(response.body.members.length).toBe(1);
|
|
1046
|
+
|
|
1047
|
+
// Load parents again
|
|
1048
|
+
await member1.refresh();
|
|
1049
|
+
await member2.refresh();
|
|
1050
|
+
await member3.refresh();
|
|
1051
|
+
|
|
1052
|
+
// Check all parents equal
|
|
1053
|
+
const expectedParent = Parent.create({
|
|
1054
|
+
...mostRecentParent,
|
|
1055
|
+
id: outOfDateParent.id, // the oldest parent id is use
|
|
1056
|
+
createdAt: outOfDateParent.createdAt,
|
|
1057
|
+
email: 'changed@example.com',
|
|
1058
|
+
alternativeEmails: [
|
|
1059
|
+
'linda@work.com',
|
|
1060
|
+
'linda+oldest@work.com',
|
|
1061
|
+
],
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1065
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1066
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
test('Puts without updatedAt are handled correctly and applied to the most recent parent when merging', async () => {
|
|
1070
|
+
const user = await new UserFactory({}).create();
|
|
1071
|
+
|
|
1072
|
+
const mostRecentParent = Parent.create({
|
|
1073
|
+
firstName: 'Linda',
|
|
1074
|
+
lastName: 'Doe',
|
|
1075
|
+
email: 'linda@example.com',
|
|
1076
|
+
alternativeEmails: ['linda@work.com'],
|
|
1077
|
+
phone: '+32412345678',
|
|
1078
|
+
address: Address.create({
|
|
1079
|
+
street: 'Main street 1',
|
|
1080
|
+
postalCode: '1000',
|
|
1081
|
+
city: 'Brussels',
|
|
1082
|
+
country: Country.Belgium,
|
|
1083
|
+
}),
|
|
1084
|
+
nationalRegisterNumber: '93042012347',
|
|
1085
|
+
updatedAt: new Date(10_000),
|
|
1086
|
+
});
|
|
1087
|
+
|
|
1088
|
+
const outOfDateParent = Parent.create({
|
|
1089
|
+
firstName: 'Linda',
|
|
1090
|
+
lastName: 'Doe',
|
|
1091
|
+
email: 'linda@example.com',
|
|
1092
|
+
alternativeEmails: ['linda+oldest@work.com'],
|
|
1093
|
+
phone: '+32412345678',
|
|
1094
|
+
address: Address.create({
|
|
1095
|
+
street: 'Main street 1',
|
|
1096
|
+
postalCode: '1000',
|
|
1097
|
+
city: 'Brussels',
|
|
1098
|
+
country: Country.Belgium,
|
|
1099
|
+
}),
|
|
1100
|
+
nationalRegisterNumber: '93042012345',
|
|
1101
|
+
updatedAt: new Date(1000),
|
|
1102
|
+
createdAt: new Date(0),
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
const member1 = await new MemberFactory({
|
|
1106
|
+
user,
|
|
1107
|
+
details: MemberDetails.create({
|
|
1108
|
+
firstName: 'John',
|
|
1109
|
+
lastName: 'Doe',
|
|
1110
|
+
parents: [outOfDateParent],
|
|
1111
|
+
}),
|
|
1112
|
+
}).create();
|
|
1113
|
+
|
|
1114
|
+
const member2 = await new MemberFactory({
|
|
1115
|
+
user,
|
|
1116
|
+
details: MemberDetails.create({
|
|
1117
|
+
firstName: 'Jane',
|
|
1118
|
+
lastName: 'Doe',
|
|
1119
|
+
parents: [],
|
|
1120
|
+
}),
|
|
1121
|
+
}).create();
|
|
1122
|
+
|
|
1123
|
+
// Parent3 was reviewed last, so has priority
|
|
1124
|
+
const member3 = await new MemberFactory({
|
|
1125
|
+
user,
|
|
1126
|
+
details: MemberDetails.create({
|
|
1127
|
+
firstName: 'Bob',
|
|
1128
|
+
lastName: 'Doe',
|
|
1129
|
+
parents: [mostRecentParent],
|
|
1130
|
+
}),
|
|
1131
|
+
}).create();
|
|
1132
|
+
|
|
1133
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
1134
|
+
const admin = await new UserFactory({
|
|
1135
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1136
|
+
}).create();
|
|
1137
|
+
const token = await Token.createToken(admin);
|
|
1138
|
+
|
|
1139
|
+
const arr: Body = new PatchableArray();
|
|
1140
|
+
const parentsPatch = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1141
|
+
const createdParent = Parent.create({
|
|
1142
|
+
firstName: 'Linda',
|
|
1143
|
+
lastName: 'Doe',
|
|
1144
|
+
updatedAt: new Date(0),
|
|
1145
|
+
email: 'changed@example.com',
|
|
1146
|
+
phone: '+3241111111',
|
|
1147
|
+
alternativeEmails: ['another-alternative-email@example.com'],
|
|
1148
|
+
});
|
|
1149
|
+
parentsPatch.addPut(createdParent);
|
|
1150
|
+
|
|
1151
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1152
|
+
id: member2.id,
|
|
1153
|
+
details: MemberDetails.patch({
|
|
1154
|
+
parents: parentsPatch,
|
|
1155
|
+
}),
|
|
1156
|
+
});
|
|
1157
|
+
arr.addPatch(patch);
|
|
1158
|
+
|
|
1159
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1160
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1161
|
+
const response = await testServer.test(endpoint, request);
|
|
1162
|
+
|
|
1163
|
+
// Check returned
|
|
1164
|
+
expect(response.status).toBe(200);
|
|
1165
|
+
expect(response.body.members.length).toBe(1);
|
|
1166
|
+
|
|
1167
|
+
// Load parents again
|
|
1168
|
+
await member1.refresh();
|
|
1169
|
+
await member2.refresh();
|
|
1170
|
+
await member3.refresh();
|
|
1171
|
+
|
|
1172
|
+
// Check all parents equal
|
|
1173
|
+
const expectedParent = Parent.create({
|
|
1174
|
+
...mostRecentParent,
|
|
1175
|
+
id: outOfDateParent.id, // the oldest parent id is use
|
|
1176
|
+
createdAt: outOfDateParent.createdAt,
|
|
1177
|
+
email: 'changed@example.com',
|
|
1178
|
+
phone: '+3241111111',
|
|
1179
|
+
alternativeEmails: [
|
|
1180
|
+
'linda@work.com',
|
|
1181
|
+
'linda+oldest@work.com',
|
|
1182
|
+
'another-alternative-email@example.com',
|
|
1183
|
+
],
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1187
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1188
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
test('Duplicate parents are merged in a family', async () => {
|
|
1192
|
+
const user = await new UserFactory({}).create();
|
|
1193
|
+
|
|
1194
|
+
const parent1 = Parent.create({
|
|
1195
|
+
firstName: 'Linda',
|
|
1196
|
+
lastName: 'Doe',
|
|
1197
|
+
email: 'linda@example.com',
|
|
1198
|
+
alternativeEmails: ['linda@work.com'],
|
|
1199
|
+
phone: '+32412345678',
|
|
1200
|
+
address: Address.create({
|
|
1201
|
+
street: 'Main street 1',
|
|
1202
|
+
postalCode: '1000',
|
|
1203
|
+
city: 'Brussels',
|
|
1204
|
+
country: Country.Belgium,
|
|
1205
|
+
}),
|
|
1206
|
+
nationalRegisterNumber: '93042012345',
|
|
1207
|
+
createdAt: new Date(0),
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
// Create two clones of this parent with a different ID
|
|
1211
|
+
const parent2 = Parent.create({
|
|
1212
|
+
firstName: 'Linda',
|
|
1213
|
+
lastName: 'Doe',
|
|
1214
|
+
createdAt: new Date(1000),
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
const parent3 = Parent.create({
|
|
1218
|
+
firstName: 'Linda',
|
|
1219
|
+
lastName: 'Doe',
|
|
1220
|
+
email: 'linda@example.com',
|
|
1221
|
+
alternativeEmails: ['linda@work2.com'],
|
|
1222
|
+
phone: '+32412345679',
|
|
1223
|
+
address: Address.create({
|
|
1224
|
+
street: 'Main street 2',
|
|
1225
|
+
postalCode: '1000',
|
|
1226
|
+
city: 'Brussels',
|
|
1227
|
+
country: Country.Belgium,
|
|
1228
|
+
}),
|
|
1229
|
+
nationalRegisterNumber: '93042012348',
|
|
1230
|
+
createdAt: new Date(2000),
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
const member1 = await new MemberFactory({
|
|
1234
|
+
user,
|
|
1235
|
+
details: MemberDetails.create({
|
|
1236
|
+
firstName: 'John',
|
|
1237
|
+
lastName: 'Doe',
|
|
1238
|
+
parents: [parent1],
|
|
1239
|
+
reviewTimes: ReviewTimes.create({
|
|
1240
|
+
times: [
|
|
1241
|
+
ReviewTime.create({
|
|
1242
|
+
name: 'parents',
|
|
1243
|
+
reviewedAt: new Date(0),
|
|
1244
|
+
}),
|
|
1245
|
+
],
|
|
1246
|
+
}),
|
|
1247
|
+
}),
|
|
1248
|
+
}).create();
|
|
1249
|
+
|
|
1250
|
+
const member2 = await new MemberFactory({
|
|
1251
|
+
user,
|
|
1252
|
+
details: MemberDetails.create({
|
|
1253
|
+
firstName: 'Jane',
|
|
1254
|
+
lastName: 'Doe',
|
|
1255
|
+
parents: [parent2],
|
|
1256
|
+
reviewTimes: ReviewTimes.create({
|
|
1257
|
+
times: [
|
|
1258
|
+
ReviewTime.create({
|
|
1259
|
+
name: 'parents',
|
|
1260
|
+
reviewedAt: new Date(1000),
|
|
1261
|
+
}),
|
|
1262
|
+
],
|
|
1263
|
+
}),
|
|
1264
|
+
}),
|
|
1265
|
+
}).create();
|
|
1266
|
+
|
|
1267
|
+
// Parent3 was reviewed last, so has priority
|
|
1268
|
+
const member3 = await new MemberFactory({
|
|
1269
|
+
user,
|
|
1270
|
+
details: MemberDetails.create({
|
|
1271
|
+
firstName: 'Bob',
|
|
1272
|
+
lastName: 'Doe',
|
|
1273
|
+
parents: [parent3],
|
|
1274
|
+
reviewTimes: ReviewTimes.create({
|
|
1275
|
+
times: [
|
|
1276
|
+
ReviewTime.create({
|
|
1277
|
+
name: 'parents',
|
|
1278
|
+
reviewedAt: new Date(2000),
|
|
1279
|
+
}),
|
|
1280
|
+
],
|
|
1281
|
+
}),
|
|
1282
|
+
}),
|
|
1283
|
+
}).create();
|
|
1284
|
+
|
|
1285
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
1286
|
+
const admin = await new UserFactory({
|
|
1287
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1288
|
+
}).create();
|
|
1289
|
+
const token = await Token.createToken(admin);
|
|
1290
|
+
|
|
1291
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1292
|
+
nonEmtpyArray.addPatch(Parent.patch({
|
|
1293
|
+
id: parent1.id,
|
|
1294
|
+
// no changes
|
|
1295
|
+
}));
|
|
1296
|
+
|
|
1297
|
+
const arr: Body = new PatchableArray();
|
|
1298
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1299
|
+
id: member1.id,
|
|
1300
|
+
details: MemberDetails.patch({
|
|
1301
|
+
parents: nonEmtpyArray,
|
|
1302
|
+
}),
|
|
1303
|
+
});
|
|
1304
|
+
arr.addPatch(patch);
|
|
1305
|
+
|
|
1306
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1307
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1308
|
+
const response = await testServer.test(endpoint, request);
|
|
1309
|
+
|
|
1310
|
+
// Check returned
|
|
1311
|
+
expect(response.status).toBe(200);
|
|
1312
|
+
expect(response.body.members.length).toBe(1);
|
|
1313
|
+
|
|
1314
|
+
// Load parents again
|
|
1315
|
+
await member1.refresh();
|
|
1316
|
+
await member2.refresh();
|
|
1317
|
+
await member3.refresh();
|
|
1318
|
+
|
|
1319
|
+
// Check all parents equal
|
|
1320
|
+
const expectedParent = Parent.create({
|
|
1321
|
+
...parent3,
|
|
1322
|
+
id: parent1.id, // the oldest parent id is use
|
|
1323
|
+
createdAt: parent1.createdAt,
|
|
1324
|
+
alternativeEmails: [
|
|
1325
|
+
'linda@work2.com',
|
|
1326
|
+
'linda@work.com',
|
|
1327
|
+
],
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1331
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1332
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
test('Deleting a parent alternative email address is possible in a family if all parents have the same ID', async () => {
|
|
1336
|
+
const user = await new UserFactory({}).create();
|
|
1337
|
+
|
|
1338
|
+
const parent1 = Parent.create({
|
|
1339
|
+
firstName: 'Linda',
|
|
1340
|
+
lastName: 'Doe',
|
|
1341
|
+
email: 'linda@example.com',
|
|
1342
|
+
alternativeEmails: ['linda@work.com'],
|
|
1343
|
+
phone: '+32412345678',
|
|
1344
|
+
address: Address.create({
|
|
1345
|
+
street: 'Main street 1',
|
|
1346
|
+
postalCode: '1000',
|
|
1347
|
+
city: 'Brussels',
|
|
1348
|
+
country: Country.Belgium,
|
|
1349
|
+
}),
|
|
1350
|
+
nationalRegisterNumber: '93042012345',
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
// Create two clones of this parent with a different ID
|
|
1354
|
+
const parent2 = Parent.create({
|
|
1355
|
+
id: parent1.id,
|
|
1356
|
+
firstName: 'Linda',
|
|
1357
|
+
lastName: 'Doe',
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
const parent3 = Parent.create({
|
|
1361
|
+
id: parent1.id,
|
|
1362
|
+
firstName: 'Linda',
|
|
1363
|
+
lastName: 'Doe',
|
|
1364
|
+
email: 'linda@example.com',
|
|
1365
|
+
alternativeEmails: ['linda@work2.com'],
|
|
1366
|
+
phone: '+32412345679',
|
|
1367
|
+
address: Address.create({
|
|
1368
|
+
street: 'Main street 2',
|
|
1369
|
+
postalCode: '1000',
|
|
1370
|
+
city: 'Brussels',
|
|
1371
|
+
country: Country.Belgium,
|
|
1372
|
+
}),
|
|
1373
|
+
nationalRegisterNumber: '93042012348',
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
const member1 = await new MemberFactory({
|
|
1377
|
+
user,
|
|
1378
|
+
details: MemberDetails.create({
|
|
1379
|
+
firstName: 'John',
|
|
1380
|
+
lastName: 'Doe',
|
|
1381
|
+
parents: [parent1],
|
|
1382
|
+
reviewTimes: ReviewTimes.create({
|
|
1383
|
+
times: [
|
|
1384
|
+
ReviewTime.create({
|
|
1385
|
+
name: 'parents',
|
|
1386
|
+
reviewedAt: new Date(0),
|
|
1387
|
+
}),
|
|
1388
|
+
],
|
|
1389
|
+
}),
|
|
1390
|
+
}),
|
|
1391
|
+
}).create();
|
|
1392
|
+
|
|
1393
|
+
const member2 = await new MemberFactory({
|
|
1394
|
+
user,
|
|
1395
|
+
details: MemberDetails.create({
|
|
1396
|
+
firstName: 'Jane',
|
|
1397
|
+
lastName: 'Doe',
|
|
1398
|
+
parents: [parent2],
|
|
1399
|
+
reviewTimes: ReviewTimes.create({
|
|
1400
|
+
times: [
|
|
1401
|
+
ReviewTime.create({
|
|
1402
|
+
name: 'parents',
|
|
1403
|
+
reviewedAt: new Date(1000),
|
|
1404
|
+
}),
|
|
1405
|
+
],
|
|
1406
|
+
}),
|
|
1407
|
+
}),
|
|
1408
|
+
}).create();
|
|
1409
|
+
|
|
1410
|
+
// Parent3 was reviewed last, so has priority
|
|
1411
|
+
const member3 = await new MemberFactory({
|
|
1412
|
+
user,
|
|
1413
|
+
details: MemberDetails.create({
|
|
1414
|
+
firstName: 'Bob',
|
|
1415
|
+
lastName: 'Doe',
|
|
1416
|
+
parents: [parent3],
|
|
1417
|
+
reviewTimes: ReviewTimes.create({
|
|
1418
|
+
times: [
|
|
1419
|
+
ReviewTime.create({
|
|
1420
|
+
name: 'parents',
|
|
1421
|
+
reviewedAt: new Date(2000),
|
|
1422
|
+
}),
|
|
1423
|
+
],
|
|
1424
|
+
}),
|
|
1425
|
+
}),
|
|
1426
|
+
}).create();
|
|
1427
|
+
|
|
1428
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
1429
|
+
const admin = await new UserFactory({
|
|
1430
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1431
|
+
}).create();
|
|
1432
|
+
const token = await Token.createToken(admin);
|
|
1433
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1434
|
+
nonEmtpyArray.addPatch(Parent.patch({
|
|
1435
|
+
id: parent1.id,
|
|
1436
|
+
// no changes
|
|
1437
|
+
}));
|
|
1438
|
+
const arr: Body = new PatchableArray();
|
|
1439
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1440
|
+
id: member1.id,
|
|
1441
|
+
details: MemberDetails.patch({
|
|
1442
|
+
parents: nonEmtpyArray,
|
|
1443
|
+
}),
|
|
1444
|
+
});
|
|
1445
|
+
arr.addPatch(patch);
|
|
1446
|
+
|
|
1447
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1448
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1449
|
+
const response = await testServer.test(endpoint, request);
|
|
1450
|
+
|
|
1451
|
+
// Check returned
|
|
1452
|
+
expect(response.status).toBe(200);
|
|
1453
|
+
expect(response.body.members.length).toBe(1);
|
|
1454
|
+
|
|
1455
|
+
// Load parents again
|
|
1456
|
+
await member1.refresh();
|
|
1457
|
+
await member2.refresh();
|
|
1458
|
+
await member3.refresh();
|
|
1459
|
+
|
|
1460
|
+
// Check all parents equal
|
|
1461
|
+
const expectedParent = parent3;
|
|
1462
|
+
|
|
1463
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1464
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1465
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
test('Deleting a parent address, NRN, phone or email is possible in a family if all parents have the same ID', async () => {
|
|
1469
|
+
const user = await new UserFactory({}).create();
|
|
1470
|
+
|
|
1471
|
+
const parent1 = Parent.create({
|
|
1472
|
+
firstName: 'Linda',
|
|
1473
|
+
lastName: 'Doe',
|
|
1474
|
+
email: 'linda@example.com',
|
|
1475
|
+
alternativeEmails: ['linda@work.com'],
|
|
1476
|
+
phone: '+32412345678',
|
|
1477
|
+
address: Address.create({
|
|
1478
|
+
street: 'Main street 1',
|
|
1479
|
+
postalCode: '1000',
|
|
1480
|
+
city: 'Brussels',
|
|
1481
|
+
country: Country.Belgium,
|
|
1482
|
+
}),
|
|
1483
|
+
nationalRegisterNumber: '93042012345',
|
|
1484
|
+
createdAt: new Date(0),
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
// Create two clones of this parent with a different ID
|
|
1488
|
+
const parent2 = Parent.create({
|
|
1489
|
+
id: parent1.id,
|
|
1490
|
+
firstName: 'Linda',
|
|
1491
|
+
lastName: 'Doe',
|
|
1492
|
+
createdAt: new Date(1000),
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
const parent3 = Parent.create({
|
|
1496
|
+
id: parent1.id,
|
|
1497
|
+
firstName: 'Linda',
|
|
1498
|
+
lastName: 'Doe',
|
|
1499
|
+
email: 'linda@example.com',
|
|
1500
|
+
alternativeEmails: ['linda@work2.com'],
|
|
1501
|
+
phone: '+32412345679',
|
|
1502
|
+
address: Address.create({
|
|
1503
|
+
street: 'Main street 2',
|
|
1504
|
+
postalCode: '1000',
|
|
1505
|
+
city: 'Brussels',
|
|
1506
|
+
country: Country.Belgium,
|
|
1507
|
+
}),
|
|
1508
|
+
nationalRegisterNumber: '93042012348',
|
|
1509
|
+
createdAt: new Date(3000),
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
const member1 = await new MemberFactory({
|
|
1513
|
+
user,
|
|
1514
|
+
details: MemberDetails.create({
|
|
1515
|
+
firstName: 'John',
|
|
1516
|
+
lastName: 'Doe',
|
|
1517
|
+
parents: [parent1],
|
|
1518
|
+
reviewTimes: ReviewTimes.create({
|
|
1519
|
+
times: [
|
|
1520
|
+
ReviewTime.create({
|
|
1521
|
+
name: 'parents',
|
|
1522
|
+
reviewedAt: new Date(0),
|
|
1523
|
+
}),
|
|
1524
|
+
],
|
|
1525
|
+
}),
|
|
1526
|
+
}),
|
|
1527
|
+
}).create();
|
|
1528
|
+
|
|
1529
|
+
const member2 = await new MemberFactory({
|
|
1530
|
+
user,
|
|
1531
|
+
details: MemberDetails.create({
|
|
1532
|
+
firstName: 'Jane',
|
|
1533
|
+
lastName: 'Doe',
|
|
1534
|
+
parents: [parent2],
|
|
1535
|
+
reviewTimes: ReviewTimes.create({
|
|
1536
|
+
times: [
|
|
1537
|
+
ReviewTime.create({
|
|
1538
|
+
name: 'parents',
|
|
1539
|
+
reviewedAt: new Date(1000),
|
|
1540
|
+
}),
|
|
1541
|
+
],
|
|
1542
|
+
}),
|
|
1543
|
+
}),
|
|
1544
|
+
}).create();
|
|
1545
|
+
|
|
1546
|
+
// Parent3 was reviewed last, so has priority
|
|
1547
|
+
const member3 = await new MemberFactory({
|
|
1548
|
+
user,
|
|
1549
|
+
details: MemberDetails.create({
|
|
1550
|
+
firstName: 'Bob',
|
|
1551
|
+
lastName: 'Doe',
|
|
1552
|
+
parents: [parent3],
|
|
1553
|
+
reviewTimes: ReviewTimes.create({
|
|
1554
|
+
times: [
|
|
1555
|
+
ReviewTime.create({
|
|
1556
|
+
name: 'parents',
|
|
1557
|
+
reviewedAt: new Date(2000),
|
|
1558
|
+
}),
|
|
1559
|
+
],
|
|
1560
|
+
}),
|
|
1561
|
+
}),
|
|
1562
|
+
}).create();
|
|
1563
|
+
|
|
1564
|
+
// Now simulate a change to member1's parents, and check if all parents are updated to the same id and details
|
|
1565
|
+
const admin = await new UserFactory({
|
|
1566
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1567
|
+
}).create();
|
|
1568
|
+
const token = await Token.createToken(admin);
|
|
1569
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1570
|
+
nonEmtpyArray.addPatch(Parent.patch({
|
|
1571
|
+
id: parent1.id,
|
|
1572
|
+
// no changes
|
|
1573
|
+
}));
|
|
1574
|
+
const arr: Body = new PatchableArray();
|
|
1575
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1576
|
+
id: member2.id,
|
|
1577
|
+
details: MemberDetails.patch({
|
|
1578
|
+
parents: nonEmtpyArray,
|
|
1579
|
+
// Mark these parents as reviewed last, so it overrides all the same parents
|
|
1580
|
+
reviewTimes: ReviewTimes.patch({
|
|
1581
|
+
times: [
|
|
1582
|
+
ReviewTime.create({
|
|
1583
|
+
name: 'parents',
|
|
1584
|
+
reviewedAt: new Date(),
|
|
1585
|
+
}),
|
|
1586
|
+
],
|
|
1587
|
+
}),
|
|
1588
|
+
}),
|
|
1589
|
+
});
|
|
1590
|
+
arr.addPatch(patch);
|
|
1591
|
+
|
|
1592
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1593
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1594
|
+
const response = await testServer.test(endpoint, request);
|
|
1595
|
+
|
|
1596
|
+
// Check returned
|
|
1597
|
+
expect(response.status).toBe(200);
|
|
1598
|
+
expect(response.body.members.length).toBe(1);
|
|
1599
|
+
|
|
1600
|
+
// Load parents again
|
|
1601
|
+
await member1.refresh();
|
|
1602
|
+
await member2.refresh();
|
|
1603
|
+
await member3.refresh();
|
|
1604
|
+
|
|
1605
|
+
// Check all parents equal
|
|
1606
|
+
const expectedParent = Parent.create({
|
|
1607
|
+
...parent2,
|
|
1608
|
+
createdAt: parent1.createdAt, // the oldest one is used
|
|
1609
|
+
});
|
|
1610
|
+
|
|
1611
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1612
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1613
|
+
expect(member3.details.parents).toEqual([expectedParent]);
|
|
1614
|
+
});
|
|
1615
|
+
|
|
1616
|
+
test('When adding a new parent that is and old copy, the most recent copy is added instead', async () => {
|
|
1617
|
+
const user = await new UserFactory({}).create();
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* This one is the oldest and has been reviewed the most recent
|
|
1621
|
+
*/
|
|
1622
|
+
const latestParent = Parent.create({
|
|
1623
|
+
firstName: 'Linda',
|
|
1624
|
+
lastName: 'Doe',
|
|
1625
|
+
email: 'linda@example.com',
|
|
1626
|
+
alternativeEmails: ['linda@work2.com'],
|
|
1627
|
+
phone: '+32412345679',
|
|
1628
|
+
address: Address.create({
|
|
1629
|
+
street: 'Main street 2',
|
|
1630
|
+
postalCode: '1000',
|
|
1631
|
+
city: 'Brussels',
|
|
1632
|
+
country: Country.Belgium,
|
|
1633
|
+
}),
|
|
1634
|
+
nationalRegisterNumber: '93042012348',
|
|
1635
|
+
createdAt: new Date(3000),
|
|
1636
|
+
updatedAt: new Date(),
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
const oldestParent = Parent.create({
|
|
1640
|
+
id: latestParent.id,
|
|
1641
|
+
firstName: 'Linda',
|
|
1642
|
+
lastName: 'Doe',
|
|
1643
|
+
email: 'ignored@example.com',
|
|
1644
|
+
createdAt: new Date(3000),
|
|
1645
|
+
updatedAt: new Date(10_000),
|
|
1646
|
+
});
|
|
1647
|
+
|
|
1648
|
+
const member1 = await new MemberFactory({
|
|
1649
|
+
user,
|
|
1650
|
+
details: MemberDetails.create({
|
|
1651
|
+
firstName: 'John',
|
|
1652
|
+
lastName: 'Doe',
|
|
1653
|
+
parents: [latestParent],
|
|
1654
|
+
}),
|
|
1655
|
+
}).create();
|
|
1656
|
+
|
|
1657
|
+
const member2 = await new MemberFactory({
|
|
1658
|
+
user,
|
|
1659
|
+
details: MemberDetails.create({
|
|
1660
|
+
firstName: 'Jane',
|
|
1661
|
+
lastName: 'Doe',
|
|
1662
|
+
parents: [],
|
|
1663
|
+
}),
|
|
1664
|
+
}).create();
|
|
1665
|
+
|
|
1666
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
1667
|
+
const admin = await new UserFactory({
|
|
1668
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1669
|
+
}).create();
|
|
1670
|
+
const token = await Token.createToken(admin);
|
|
1671
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1672
|
+
nonEmtpyArray.addPut(oldestParent);
|
|
1673
|
+
|
|
1674
|
+
const arr: Body = new PatchableArray();
|
|
1675
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1676
|
+
id: member2.id,
|
|
1677
|
+
details: MemberDetails.patch({
|
|
1678
|
+
parents: nonEmtpyArray,
|
|
1679
|
+
}),
|
|
1680
|
+
});
|
|
1681
|
+
arr.addPatch(patch);
|
|
1682
|
+
|
|
1683
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1684
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1685
|
+
const response = await testServer.test(endpoint, request);
|
|
1686
|
+
|
|
1687
|
+
// Check returned
|
|
1688
|
+
expect(response.status).toBe(200);
|
|
1689
|
+
expect(response.body.members.length).toBe(1);
|
|
1690
|
+
|
|
1691
|
+
// Load contacts again
|
|
1692
|
+
await member1.refresh();
|
|
1693
|
+
await member2.refresh();
|
|
1694
|
+
|
|
1695
|
+
// The contact should be equal to contact1, and ignore other changes
|
|
1696
|
+
const expectedParent = Parent.create({
|
|
1697
|
+
...latestParent,
|
|
1698
|
+
});
|
|
1699
|
+
|
|
1700
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1701
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1702
|
+
});
|
|
1703
|
+
|
|
1704
|
+
test('It is possible to change the name of a parent without setting updatedAt', async () => {
|
|
1705
|
+
const user = await new UserFactory({}).create();
|
|
1706
|
+
|
|
1707
|
+
/**
|
|
1708
|
+
* This one is the oldest and has been reviewed the most recent
|
|
1709
|
+
*/
|
|
1710
|
+
const latestParent = Parent.create({
|
|
1711
|
+
firstName: 'Linda',
|
|
1712
|
+
lastName: 'Doe',
|
|
1713
|
+
email: 'linda@example.com',
|
|
1714
|
+
alternativeEmails: ['linda@work2.com'],
|
|
1715
|
+
phone: '+32412345679',
|
|
1716
|
+
address: Address.create({
|
|
1717
|
+
street: 'Main street 2',
|
|
1718
|
+
postalCode: '1000',
|
|
1719
|
+
city: 'Brussels',
|
|
1720
|
+
country: Country.Belgium,
|
|
1721
|
+
}),
|
|
1722
|
+
nationalRegisterNumber: '93042012348',
|
|
1723
|
+
createdAt: new Date(3000),
|
|
1724
|
+
updatedAt: new Date(),
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
const oldestParent = Parent.create({
|
|
1728
|
+
id: latestParent.id,
|
|
1729
|
+
firstName: 'Linda',
|
|
1730
|
+
lastName: 'Doe',
|
|
1731
|
+
email: 'ignored@example.com',
|
|
1732
|
+
createdAt: new Date(3000),
|
|
1733
|
+
updatedAt: new Date(10_000),
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
const member1 = await new MemberFactory({
|
|
1737
|
+
user,
|
|
1738
|
+
details: MemberDetails.create({
|
|
1739
|
+
firstName: 'John',
|
|
1740
|
+
lastName: 'Doe',
|
|
1741
|
+
parents: [latestParent],
|
|
1742
|
+
}),
|
|
1743
|
+
}).create();
|
|
1744
|
+
|
|
1745
|
+
const member2 = await new MemberFactory({
|
|
1746
|
+
user,
|
|
1747
|
+
details: MemberDetails.create({
|
|
1748
|
+
firstName: 'Jane',
|
|
1749
|
+
lastName: 'Doe',
|
|
1750
|
+
parents: [oldestParent],
|
|
1751
|
+
}),
|
|
1752
|
+
}).create();
|
|
1753
|
+
|
|
1754
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
1755
|
+
const admin = await new UserFactory({
|
|
1756
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1757
|
+
}).create();
|
|
1758
|
+
const token = await Token.createToken(admin);
|
|
1759
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<Parent>;
|
|
1760
|
+
nonEmtpyArray.addPatch(Parent.patch({
|
|
1761
|
+
id: latestParent.id,
|
|
1762
|
+
firstName: 'Linda2',
|
|
1763
|
+
lastName: 'Doe2',
|
|
1764
|
+
// Note that 'by accident' the frontend did not pass the updatedAt value correctly - this should still work as expected
|
|
1765
|
+
}));
|
|
1766
|
+
|
|
1767
|
+
const arr: Body = new PatchableArray();
|
|
1768
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1769
|
+
id: member2.id,
|
|
1770
|
+
details: MemberDetails.patch({
|
|
1771
|
+
parents: nonEmtpyArray,
|
|
1772
|
+
}),
|
|
1773
|
+
});
|
|
1774
|
+
arr.addPatch(patch);
|
|
1775
|
+
|
|
1776
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1777
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1778
|
+
const response = await testServer.test(endpoint, request);
|
|
1779
|
+
|
|
1780
|
+
// Check returned
|
|
1781
|
+
expect(response.status).toBe(200);
|
|
1782
|
+
expect(response.body.members.length).toBe(1);
|
|
1783
|
+
|
|
1784
|
+
// Load contacts again
|
|
1785
|
+
await member1.refresh();
|
|
1786
|
+
await member2.refresh();
|
|
1787
|
+
|
|
1788
|
+
// The contact should be equal to contact1, and ignore other changes
|
|
1789
|
+
const expectedParent = Parent.create({
|
|
1790
|
+
...latestParent,
|
|
1791
|
+
firstName: 'Linda2',
|
|
1792
|
+
lastName: 'Doe2',
|
|
1793
|
+
});
|
|
1794
|
+
|
|
1795
|
+
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1796
|
+
expect(member2.details.parents).toEqual([expectedParent]);
|
|
1797
|
+
});
|
|
1798
|
+
});
|
|
1799
|
+
|
|
1800
|
+
describe('Emergency contacts', () => {
|
|
1801
|
+
test('Duplicate emergency contacts are merged in a family', async () => {
|
|
1802
|
+
const user = await new UserFactory({}).create();
|
|
1803
|
+
|
|
1804
|
+
const contact1 = EmergencyContact.create({
|
|
1805
|
+
name: 'Linda Doe',
|
|
1806
|
+
title: 'Grandmother',
|
|
1807
|
+
phone: '+32412345678',
|
|
1808
|
+
createdAt: new Date(0),
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
// Create two clones of this contact with a different ID
|
|
1812
|
+
const contact2 = EmergencyContact.create({
|
|
1813
|
+
name: 'Linda Doe',
|
|
1814
|
+
createdAt: new Date(2000),
|
|
1815
|
+
});
|
|
1816
|
+
|
|
1817
|
+
const contact3 = EmergencyContact.create({
|
|
1818
|
+
name: 'Linda Doe',
|
|
1819
|
+
title: 'Oma',
|
|
1820
|
+
phone: '+32412345679',
|
|
1821
|
+
createdAt: new Date(4000),
|
|
1822
|
+
});
|
|
1823
|
+
|
|
1824
|
+
const member1 = await new MemberFactory({
|
|
1825
|
+
user,
|
|
1826
|
+
details: MemberDetails.create({
|
|
1827
|
+
firstName: 'John',
|
|
1828
|
+
lastName: 'Doe',
|
|
1829
|
+
emergencyContacts: [contact1],
|
|
1830
|
+
reviewTimes: ReviewTimes.create({
|
|
1831
|
+
times: [
|
|
1832
|
+
ReviewTime.create({
|
|
1833
|
+
name: 'emergencyContacts',
|
|
1834
|
+
reviewedAt: new Date(0),
|
|
1835
|
+
}),
|
|
1836
|
+
],
|
|
1837
|
+
}),
|
|
1838
|
+
}),
|
|
1839
|
+
}).create();
|
|
1840
|
+
|
|
1841
|
+
const member2 = await new MemberFactory({
|
|
1842
|
+
user,
|
|
1843
|
+
details: MemberDetails.create({
|
|
1844
|
+
firstName: 'Jane',
|
|
1845
|
+
lastName: 'Doe',
|
|
1846
|
+
emergencyContacts: [contact2],
|
|
1847
|
+
reviewTimes: ReviewTimes.create({
|
|
1848
|
+
times: [
|
|
1849
|
+
ReviewTime.create({
|
|
1850
|
+
name: 'emergencyContacts',
|
|
1851
|
+
reviewedAt: new Date(1000),
|
|
1852
|
+
}),
|
|
1853
|
+
],
|
|
1854
|
+
}),
|
|
1855
|
+
}),
|
|
1856
|
+
}).create();
|
|
1857
|
+
|
|
1858
|
+
// Parent3 was reviewed last, so has priority
|
|
1859
|
+
const member3 = await new MemberFactory({
|
|
1860
|
+
user,
|
|
1861
|
+
details: MemberDetails.create({
|
|
1862
|
+
firstName: 'Bob',
|
|
1863
|
+
lastName: 'Doe',
|
|
1864
|
+
emergencyContacts: [contact3],
|
|
1865
|
+
reviewTimes: ReviewTimes.create({
|
|
1866
|
+
times: [
|
|
1867
|
+
ReviewTime.create({
|
|
1868
|
+
name: 'emergencyContacts',
|
|
1869
|
+
reviewedAt: new Date(2000),
|
|
1870
|
+
}),
|
|
1871
|
+
],
|
|
1872
|
+
}),
|
|
1873
|
+
}),
|
|
1874
|
+
}).create();
|
|
1875
|
+
|
|
1876
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
1877
|
+
const admin = await new UserFactory({
|
|
1878
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1879
|
+
}).create();
|
|
1880
|
+
const token = await Token.createToken(admin);
|
|
1881
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
1882
|
+
nonEmtpyArray.addPatch(EmergencyContact.patch({
|
|
1883
|
+
id: contact1.id,
|
|
1884
|
+
// no changes
|
|
1885
|
+
}));
|
|
1886
|
+
const arr: Body = new PatchableArray();
|
|
1887
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
1888
|
+
id: member1.id,
|
|
1889
|
+
details: MemberDetails.patch({
|
|
1890
|
+
emergencyContacts: nonEmtpyArray,
|
|
1891
|
+
}),
|
|
1892
|
+
});
|
|
1893
|
+
arr.addPatch(patch);
|
|
1894
|
+
|
|
1895
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
1896
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
1897
|
+
const response = await testServer.test(endpoint, request);
|
|
1898
|
+
|
|
1899
|
+
// Check returned
|
|
1900
|
+
expect(response.status).toBe(200);
|
|
1901
|
+
expect(response.body.members.length).toBe(1);
|
|
1902
|
+
|
|
1903
|
+
// Load contacts again
|
|
1904
|
+
await member1.refresh();
|
|
1905
|
+
await member2.refresh();
|
|
1906
|
+
await member3.refresh();
|
|
1907
|
+
|
|
1908
|
+
// Check all contacts equal
|
|
1909
|
+
const expectedParent = EmergencyContact.create({
|
|
1910
|
+
...contact3,
|
|
1911
|
+
id: contact1.id, // the oldest contact id is used
|
|
1912
|
+
createdAt: contact1.createdAt,
|
|
1913
|
+
});
|
|
1914
|
+
|
|
1915
|
+
expect(member1.details.emergencyContacts).toEqual([expectedParent]);
|
|
1916
|
+
expect(member2.details.emergencyContacts).toEqual([expectedParent]);
|
|
1917
|
+
expect(member3.details.emergencyContacts).toEqual([expectedParent]);
|
|
1918
|
+
});
|
|
1919
|
+
|
|
1920
|
+
test('Deleting a contact title and phone is possible in a family if all contacts have the same ID', async () => {
|
|
1921
|
+
const user = await new UserFactory({}).create();
|
|
1922
|
+
|
|
1923
|
+
const contact1 = EmergencyContact.create({
|
|
1924
|
+
name: 'Linda Doe',
|
|
1925
|
+
title: 'Grandmother',
|
|
1926
|
+
phone: '+32412345678',
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1929
|
+
// Create two clones of this contact with a different ID
|
|
1930
|
+
const contact2 = EmergencyContact.create({
|
|
1931
|
+
id: contact1.id,
|
|
1932
|
+
name: 'Linda Doe',
|
|
1933
|
+
});
|
|
1934
|
+
|
|
1935
|
+
const contact3 = EmergencyContact.create({
|
|
1936
|
+
id: contact1.id,
|
|
1937
|
+
name: 'Linda Doe',
|
|
1938
|
+
title: 'Oma',
|
|
1939
|
+
phone: '+32412345679',
|
|
1940
|
+
});
|
|
1941
|
+
|
|
1942
|
+
const member1 = await new MemberFactory({
|
|
1943
|
+
user,
|
|
1944
|
+
details: MemberDetails.create({
|
|
1945
|
+
firstName: 'John',
|
|
1946
|
+
lastName: 'Doe',
|
|
1947
|
+
emergencyContacts: [contact1],
|
|
1948
|
+
reviewTimes: ReviewTimes.create({
|
|
1949
|
+
times: [
|
|
1950
|
+
ReviewTime.create({
|
|
1951
|
+
name: 'emergencyContacts',
|
|
1952
|
+
reviewedAt: new Date(0),
|
|
1953
|
+
}),
|
|
1954
|
+
],
|
|
1955
|
+
}),
|
|
1956
|
+
}),
|
|
1957
|
+
}).create();
|
|
1958
|
+
|
|
1959
|
+
const member2 = await new MemberFactory({
|
|
1960
|
+
user,
|
|
1961
|
+
details: MemberDetails.create({
|
|
1962
|
+
firstName: 'Jane',
|
|
1963
|
+
lastName: 'Doe',
|
|
1964
|
+
emergencyContacts: [contact2],
|
|
1965
|
+
reviewTimes: ReviewTimes.create({
|
|
1966
|
+
times: [
|
|
1967
|
+
ReviewTime.create({
|
|
1968
|
+
name: 'emergencyContacts',
|
|
1969
|
+
reviewedAt: new Date(1000),
|
|
1970
|
+
}),
|
|
1971
|
+
],
|
|
1972
|
+
}),
|
|
1973
|
+
}),
|
|
1974
|
+
}).create();
|
|
1975
|
+
|
|
1976
|
+
// Parent3 was reviewed last, so has priority
|
|
1977
|
+
const member3 = await new MemberFactory({
|
|
1978
|
+
user,
|
|
1979
|
+
details: MemberDetails.create({
|
|
1980
|
+
firstName: 'Bob',
|
|
1981
|
+
lastName: 'Doe',
|
|
1982
|
+
emergencyContacts: [contact3],
|
|
1983
|
+
reviewTimes: ReviewTimes.create({
|
|
1984
|
+
times: [
|
|
1985
|
+
ReviewTime.create({
|
|
1986
|
+
name: 'emergencyContacts',
|
|
1987
|
+
reviewedAt: new Date(2000),
|
|
1988
|
+
}),
|
|
1989
|
+
],
|
|
1990
|
+
}),
|
|
1991
|
+
}),
|
|
1992
|
+
}).create();
|
|
1993
|
+
|
|
1994
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
1995
|
+
const admin = await new UserFactory({
|
|
1996
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
1997
|
+
}).create();
|
|
1998
|
+
const token = await Token.createToken(admin);
|
|
1999
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2000
|
+
nonEmtpyArray.addPatch(EmergencyContact.patch({
|
|
2001
|
+
id: contact1.id,
|
|
2002
|
+
// no changes
|
|
2003
|
+
}));
|
|
2004
|
+
const arr: Body = new PatchableArray();
|
|
2005
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2006
|
+
id: member2.id,
|
|
2007
|
+
details: MemberDetails.patch({
|
|
2008
|
+
emergencyContacts: nonEmtpyArray,
|
|
2009
|
+
// Mark these contacts as reviewed last, so it overrides all the same contacts
|
|
2010
|
+
reviewTimes: ReviewTimes.patch({
|
|
2011
|
+
times: [
|
|
2012
|
+
ReviewTime.create({
|
|
2013
|
+
name: 'emergencyContacts',
|
|
2014
|
+
reviewedAt: new Date(),
|
|
2015
|
+
}),
|
|
2016
|
+
],
|
|
2017
|
+
}),
|
|
2018
|
+
}),
|
|
2019
|
+
});
|
|
2020
|
+
arr.addPatch(patch);
|
|
2021
|
+
|
|
2022
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2023
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2024
|
+
const response = await testServer.test(endpoint, request);
|
|
2025
|
+
|
|
2026
|
+
// Check returned
|
|
2027
|
+
expect(response.status).toBe(200);
|
|
2028
|
+
expect(response.body.members.length).toBe(1);
|
|
2029
|
+
|
|
2030
|
+
// Load contacts again
|
|
2031
|
+
await member1.refresh();
|
|
2032
|
+
await member2.refresh();
|
|
2033
|
+
await member3.refresh();
|
|
2034
|
+
|
|
2035
|
+
// Check all contacts equal
|
|
2036
|
+
const expectedParent = contact2;
|
|
2037
|
+
|
|
2038
|
+
expect(member1.details.emergencyContacts).toEqual([expectedParent]);
|
|
2039
|
+
expect(member2.details.emergencyContacts).toEqual([expectedParent]);
|
|
2040
|
+
expect(member3.details.emergencyContacts).toEqual([expectedParent]);
|
|
2041
|
+
});
|
|
2042
|
+
|
|
2043
|
+
test('When adding a new emergency contact it is automatically merged with existing contacts', async () => {
|
|
2044
|
+
const user = await new UserFactory({}).create();
|
|
2045
|
+
|
|
2046
|
+
const contact1 = EmergencyContact.create({
|
|
2047
|
+
name: 'Linda Doe',
|
|
2048
|
+
title: 'Grandmother',
|
|
2049
|
+
phone: '+32412345678',
|
|
2050
|
+
createdAt: new Date(0),
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
const member1 = await new MemberFactory({
|
|
2054
|
+
user,
|
|
2055
|
+
details: MemberDetails.create({
|
|
2056
|
+
firstName: 'John',
|
|
2057
|
+
lastName: 'Doe',
|
|
2058
|
+
emergencyContacts: [contact1],
|
|
2059
|
+
}),
|
|
2060
|
+
}).create();
|
|
2061
|
+
|
|
2062
|
+
const member2 = await new MemberFactory({
|
|
2063
|
+
user,
|
|
2064
|
+
details: MemberDetails.create({
|
|
2065
|
+
firstName: 'Jane',
|
|
2066
|
+
lastName: 'Doe',
|
|
2067
|
+
emergencyContacts: [],
|
|
2068
|
+
}),
|
|
2069
|
+
}).create();
|
|
2070
|
+
|
|
2071
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
2072
|
+
const admin = await new UserFactory({
|
|
2073
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2074
|
+
}).create();
|
|
2075
|
+
const token = await Token.createToken(admin);
|
|
2076
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2077
|
+
nonEmtpyArray.addPut(EmergencyContact.create({
|
|
2078
|
+
name: 'Linda Doe',
|
|
2079
|
+
title: 'Oma',
|
|
2080
|
+
}));
|
|
2081
|
+
|
|
2082
|
+
const arr: Body = new PatchableArray();
|
|
2083
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2084
|
+
id: member2.id,
|
|
2085
|
+
details: MemberDetails.patch({
|
|
2086
|
+
emergencyContacts: nonEmtpyArray,
|
|
2087
|
+
}),
|
|
2088
|
+
});
|
|
2089
|
+
arr.addPatch(patch);
|
|
2090
|
+
|
|
2091
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2092
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2093
|
+
const response = await testServer.test(endpoint, request);
|
|
2094
|
+
|
|
2095
|
+
// Check returned
|
|
2096
|
+
expect(response.status).toBe(200);
|
|
2097
|
+
expect(response.body.members.length).toBe(1);
|
|
2098
|
+
|
|
2099
|
+
// Load contacts again
|
|
2100
|
+
await member1.refresh();
|
|
2101
|
+
await member2.refresh();
|
|
2102
|
+
|
|
2103
|
+
// Check all contacts equal
|
|
2104
|
+
const expectedParent = EmergencyContact.create({
|
|
2105
|
+
...contact1,
|
|
2106
|
+
title: 'Oma',
|
|
2107
|
+
});
|
|
2108
|
+
|
|
2109
|
+
expect(member1.details.emergencyContacts).toEqual([expectedParent]);
|
|
2110
|
+
expect(member2.details.emergencyContacts).toEqual([expectedParent]);
|
|
2111
|
+
});
|
|
2112
|
+
|
|
2113
|
+
test('When adding a new emergency contact that is an old copy, the most recent copy is added instead', async () => {
|
|
2114
|
+
const user = await new UserFactory({}).create();
|
|
2115
|
+
|
|
2116
|
+
/**
|
|
2117
|
+
* This one is the oldest and has been reviewed the most recent
|
|
2118
|
+
*/
|
|
2119
|
+
const contact1 = EmergencyContact.create({
|
|
2120
|
+
name: 'Linda Doe',
|
|
2121
|
+
title: 'Grandmother',
|
|
2122
|
+
phone: '+32412345678',
|
|
2123
|
+
createdAt: new Date(0),
|
|
2124
|
+
updatedAt: new Date(),
|
|
2125
|
+
});
|
|
2126
|
+
|
|
2127
|
+
// The frontend for some reason got and old version of this contact
|
|
2128
|
+
const oldVersionContact = EmergencyContact.create({
|
|
2129
|
+
id: contact1.id,
|
|
2130
|
+
name: 'Linda Doe',
|
|
2131
|
+
title: 'Oma',
|
|
2132
|
+
phone: '+32412345676',
|
|
2133
|
+
createdAt: new Date(0),
|
|
2134
|
+
updatedAt: new Date(10_000), // This one is older
|
|
2135
|
+
});
|
|
2136
|
+
|
|
2137
|
+
const member1 = await new MemberFactory({
|
|
2138
|
+
user,
|
|
2139
|
+
details: MemberDetails.create({
|
|
2140
|
+
firstName: 'John',
|
|
2141
|
+
lastName: 'Doe',
|
|
2142
|
+
emergencyContacts: [contact1],
|
|
2143
|
+
}),
|
|
2144
|
+
}).create();
|
|
2145
|
+
|
|
2146
|
+
const member2 = await new MemberFactory({
|
|
2147
|
+
user,
|
|
2148
|
+
details: MemberDetails.create({
|
|
2149
|
+
firstName: 'Jane',
|
|
2150
|
+
lastName: 'Doe',
|
|
2151
|
+
emergencyContacts: [],
|
|
2152
|
+
}),
|
|
2153
|
+
}).create();
|
|
2154
|
+
|
|
2155
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
2156
|
+
const admin = await new UserFactory({
|
|
2157
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2158
|
+
}).create();
|
|
2159
|
+
const token = await Token.createToken(admin);
|
|
2160
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2161
|
+
nonEmtpyArray.addPut(oldVersionContact);
|
|
2162
|
+
|
|
2163
|
+
const arr: Body = new PatchableArray();
|
|
2164
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2165
|
+
id: member2.id,
|
|
2166
|
+
details: MemberDetails.patch({
|
|
2167
|
+
emergencyContacts: nonEmtpyArray,
|
|
2168
|
+
}),
|
|
2169
|
+
});
|
|
2170
|
+
arr.addPatch(patch);
|
|
2171
|
+
|
|
2172
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2173
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2174
|
+
const response = await testServer.test(endpoint, request);
|
|
2175
|
+
|
|
2176
|
+
// Check returned
|
|
2177
|
+
expect(response.status).toBe(200);
|
|
2178
|
+
expect(response.body.members.length).toBe(1);
|
|
2179
|
+
|
|
2180
|
+
// Load contacts again
|
|
2181
|
+
await member1.refresh();
|
|
2182
|
+
await member2.refresh();
|
|
2183
|
+
|
|
2184
|
+
// The contact should be equal to contact1, and ignore other changes
|
|
2185
|
+
const expectedParent = EmergencyContact.create({
|
|
2186
|
+
...contact1,
|
|
2187
|
+
});
|
|
2188
|
+
|
|
2189
|
+
expect(member1.details.emergencyContacts).toEqual([expectedParent]);
|
|
2190
|
+
expect(member2.details.emergencyContacts).toEqual([expectedParent]);
|
|
2191
|
+
});
|
|
2192
|
+
|
|
2193
|
+
test('It is possible to change the name of an emergency contact without setting updatedAt', async () => {
|
|
2194
|
+
const user = await new UserFactory({}).create();
|
|
2195
|
+
|
|
2196
|
+
/**
|
|
2197
|
+
* This one is the oldest and has been reviewed the most recent
|
|
2198
|
+
*/
|
|
2199
|
+
const contact1 = EmergencyContact.create({
|
|
2200
|
+
name: 'Linda Doe',
|
|
2201
|
+
title: 'Grandmother',
|
|
2202
|
+
phone: '+32412345678',
|
|
2203
|
+
createdAt: new Date(0),
|
|
2204
|
+
updatedAt: new Date(),
|
|
2205
|
+
});
|
|
2206
|
+
|
|
2207
|
+
const member1 = await new MemberFactory({
|
|
2208
|
+
user,
|
|
2209
|
+
details: MemberDetails.create({
|
|
2210
|
+
firstName: 'John',
|
|
2211
|
+
lastName: 'Doe',
|
|
2212
|
+
emergencyContacts: [contact1],
|
|
2213
|
+
}),
|
|
2214
|
+
}).create();
|
|
2215
|
+
|
|
2216
|
+
const member2 = await new MemberFactory({
|
|
2217
|
+
user,
|
|
2218
|
+
details: MemberDetails.create({
|
|
2219
|
+
firstName: 'Jane',
|
|
2220
|
+
lastName: 'Doe',
|
|
2221
|
+
emergencyContacts: [contact1],
|
|
2222
|
+
}),
|
|
2223
|
+
}).create();
|
|
2224
|
+
|
|
2225
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
2226
|
+
const admin = await new UserFactory({
|
|
2227
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2228
|
+
}).create();
|
|
2229
|
+
const token = await Token.createToken(admin);
|
|
2230
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2231
|
+
nonEmtpyArray.addPatch(EmergencyContact.patch({
|
|
2232
|
+
id: contact1.id,
|
|
2233
|
+
name: 'Linda2 Doe2',
|
|
2234
|
+
// Note that 'by accident' the frontend did not pass the updatedAt value correctly - this should still work as expected
|
|
2235
|
+
}));
|
|
2236
|
+
|
|
2237
|
+
const arr: Body = new PatchableArray();
|
|
2238
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2239
|
+
id: member2.id,
|
|
2240
|
+
details: MemberDetails.patch({
|
|
2241
|
+
emergencyContacts: nonEmtpyArray,
|
|
2242
|
+
}),
|
|
2243
|
+
});
|
|
2244
|
+
arr.addPatch(patch);
|
|
2245
|
+
|
|
2246
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2247
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2248
|
+
const response = await testServer.test(endpoint, request);
|
|
2249
|
+
|
|
2250
|
+
// Check returned
|
|
2251
|
+
expect(response.status).toBe(200);
|
|
2252
|
+
expect(response.body.members.length).toBe(1);
|
|
2253
|
+
|
|
2254
|
+
// Load contacts again
|
|
2255
|
+
await member1.refresh();
|
|
2256
|
+
await member2.refresh();
|
|
2257
|
+
|
|
2258
|
+
// The contact should be equal to contact1, and ignore other changes
|
|
2259
|
+
const expectedContact = EmergencyContact.create({
|
|
2260
|
+
...contact1,
|
|
2261
|
+
name: 'Linda2 Doe2',
|
|
2262
|
+
});
|
|
2263
|
+
|
|
2264
|
+
expect(member1.details.emergencyContacts).toEqual([expectedContact]);
|
|
2265
|
+
expect(member2.details.emergencyContacts).toEqual([expectedContact]);
|
|
2266
|
+
});
|
|
2267
|
+
|
|
2268
|
+
test('It is possible to change the name of an emergency contact with setting updatedAt', async () => {
|
|
2269
|
+
const user = await new UserFactory({}).create();
|
|
2270
|
+
|
|
2271
|
+
/**
|
|
2272
|
+
* This one is the oldest and has been reviewed the most recent
|
|
2273
|
+
*/
|
|
2274
|
+
const contact1 = EmergencyContact.create({
|
|
2275
|
+
name: 'Linda Doe',
|
|
2276
|
+
title: 'Grandmother',
|
|
2277
|
+
phone: '+32412345678',
|
|
2278
|
+
createdAt: new Date(0),
|
|
2279
|
+
updatedAt: new Date(Date.now() - 5_000),
|
|
2280
|
+
});
|
|
2281
|
+
|
|
2282
|
+
const member1 = await new MemberFactory({
|
|
2283
|
+
user,
|
|
2284
|
+
details: MemberDetails.create({
|
|
2285
|
+
firstName: 'John',
|
|
2286
|
+
lastName: 'Doe',
|
|
2287
|
+
emergencyContacts: [contact1],
|
|
2288
|
+
}),
|
|
2289
|
+
}).create();
|
|
2290
|
+
|
|
2291
|
+
const member2 = await new MemberFactory({
|
|
2292
|
+
user,
|
|
2293
|
+
details: MemberDetails.create({
|
|
2294
|
+
firstName: 'Jane',
|
|
2295
|
+
lastName: 'Doe',
|
|
2296
|
+
emergencyContacts: [contact1],
|
|
2297
|
+
}),
|
|
2298
|
+
}).create();
|
|
2299
|
+
|
|
2300
|
+
// Now simulate a change to member1's contacts, and check if all contacts are updated to the same id and details
|
|
2301
|
+
const admin = await new UserFactory({
|
|
2302
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2303
|
+
}).create();
|
|
2304
|
+
const token = await Token.createToken(admin);
|
|
2305
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2306
|
+
const d = new Date();
|
|
2307
|
+
nonEmtpyArray.addPatch(EmergencyContact.patch({
|
|
2308
|
+
id: contact1.id,
|
|
2309
|
+
name: 'Linda2 Doe2',
|
|
2310
|
+
title: 'Changed',
|
|
2311
|
+
updatedAt: d,
|
|
2312
|
+
}));
|
|
2313
|
+
|
|
2314
|
+
const arr: Body = new PatchableArray();
|
|
2315
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2316
|
+
id: member2.id,
|
|
2317
|
+
details: MemberDetails.patch({
|
|
2318
|
+
emergencyContacts: nonEmtpyArray,
|
|
2319
|
+
}),
|
|
2320
|
+
});
|
|
2321
|
+
arr.addPatch(patch);
|
|
2322
|
+
|
|
2323
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2324
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2325
|
+
const response = await testServer.test(endpoint, request);
|
|
2326
|
+
|
|
2327
|
+
// Check returned
|
|
2328
|
+
expect(response.status).toBe(200);
|
|
2329
|
+
expect(response.body.members.length).toBe(1);
|
|
2330
|
+
|
|
2331
|
+
// Load contacts again
|
|
2332
|
+
await member1.refresh();
|
|
2333
|
+
await member2.refresh();
|
|
2334
|
+
|
|
2335
|
+
// The contact should be equal to contact1, and ignore other changes
|
|
2336
|
+
const expectedContact = EmergencyContact.create({
|
|
2337
|
+
...contact1,
|
|
2338
|
+
name: 'Linda2 Doe2',
|
|
2339
|
+
title: 'Changed',
|
|
2340
|
+
updatedAt: d,
|
|
2341
|
+
});
|
|
2342
|
+
|
|
2343
|
+
expect(member1.details.emergencyContacts).toEqual([expectedContact]);
|
|
2344
|
+
expect(member2.details.emergencyContacts).toEqual([expectedContact]);
|
|
2345
|
+
});
|
|
2346
|
+
|
|
2347
|
+
test('Adding a completely new emergency contact works correctly', async () => {
|
|
2348
|
+
const user = await new UserFactory({}).create();
|
|
2349
|
+
|
|
2350
|
+
const existing = EmergencyContact.create({
|
|
2351
|
+
name: 'Existing friend',
|
|
2352
|
+
title: 'Friend',
|
|
2353
|
+
phone: '+32412345111',
|
|
2354
|
+
});
|
|
2355
|
+
const member1 = await new MemberFactory({
|
|
2356
|
+
user,
|
|
2357
|
+
details: MemberDetails.create({
|
|
2358
|
+
firstName: 'John',
|
|
2359
|
+
lastName: 'Doe',
|
|
2360
|
+
emergencyContacts: [
|
|
2361
|
+
existing,
|
|
2362
|
+
],
|
|
2363
|
+
}),
|
|
2364
|
+
}).create();
|
|
2365
|
+
|
|
2366
|
+
const newContact = EmergencyContact.create({
|
|
2367
|
+
name: 'New Contact',
|
|
2368
|
+
title: 'Friend',
|
|
2369
|
+
phone: '+32412345670',
|
|
2370
|
+
});
|
|
2371
|
+
|
|
2372
|
+
const admin = await new UserFactory({
|
|
2373
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2374
|
+
}).create();
|
|
2375
|
+
const token = await Token.createToken(admin);
|
|
2376
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2377
|
+
nonEmtpyArray.addPut(newContact);
|
|
2378
|
+
|
|
2379
|
+
const arr: Body = new PatchableArray();
|
|
2380
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2381
|
+
id: member1.id,
|
|
2382
|
+
details: MemberDetails.patch({
|
|
2383
|
+
emergencyContacts: nonEmtpyArray,
|
|
2384
|
+
}),
|
|
2385
|
+
});
|
|
2386
|
+
arr.addPatch(patch);
|
|
2387
|
+
|
|
2388
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2389
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2390
|
+
const response = await testServer.test(endpoint, request);
|
|
2391
|
+
|
|
2392
|
+
// Check returned
|
|
2393
|
+
expect(response.status).toBe(200);
|
|
2394
|
+
expect(response.body.members.length).toBe(1);
|
|
2395
|
+
|
|
2396
|
+
// Load contacts again
|
|
2397
|
+
await member1.refresh();
|
|
2398
|
+
|
|
2399
|
+
// Check the new contact is added
|
|
2400
|
+
expect(member1.details.emergencyContacts).toEqual([
|
|
2401
|
+
existing,
|
|
2402
|
+
newContact,
|
|
2403
|
+
]);
|
|
2404
|
+
});
|
|
2405
|
+
|
|
2406
|
+
test('Updating an existing emergency contact\'s details works correctly', async () => {
|
|
2407
|
+
const user = await new UserFactory({}).create();
|
|
2408
|
+
|
|
2409
|
+
const contact1 = EmergencyContact.create({
|
|
2410
|
+
name: 'Linda Doe',
|
|
2411
|
+
title: 'Grandmother',
|
|
2412
|
+
phone: '+32412345678',
|
|
2413
|
+
createdAt: new Date(0),
|
|
2414
|
+
});
|
|
2415
|
+
|
|
2416
|
+
const member1 = await new MemberFactory({
|
|
2417
|
+
user,
|
|
2418
|
+
details: MemberDetails.create({
|
|
2419
|
+
firstName: 'John',
|
|
2420
|
+
lastName: 'Doe',
|
|
2421
|
+
emergencyContacts: [contact1],
|
|
2422
|
+
}),
|
|
2423
|
+
}).create();
|
|
2424
|
+
|
|
2425
|
+
const updatedContact = EmergencyContact.patch({
|
|
2426
|
+
id: contact1.id,
|
|
2427
|
+
phone: '+32412345679',
|
|
2428
|
+
});
|
|
2429
|
+
|
|
2430
|
+
const admin = await new UserFactory({
|
|
2431
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2432
|
+
}).create();
|
|
2433
|
+
const token = await Token.createToken(admin);
|
|
2434
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2435
|
+
nonEmtpyArray.addPatch(updatedContact);
|
|
2436
|
+
|
|
2437
|
+
const arr: Body = new PatchableArray();
|
|
2438
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2439
|
+
id: member1.id,
|
|
2440
|
+
details: MemberDetails.patch({
|
|
2441
|
+
emergencyContacts: nonEmtpyArray,
|
|
2442
|
+
}),
|
|
2443
|
+
});
|
|
2444
|
+
arr.addPatch(patch);
|
|
2445
|
+
|
|
2446
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2447
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2448
|
+
const response = await testServer.test(endpoint, request);
|
|
2449
|
+
|
|
2450
|
+
// Check returned
|
|
2451
|
+
expect(response.status).toBe(200);
|
|
2452
|
+
expect(response.body.members.length).toBe(1);
|
|
2453
|
+
|
|
2454
|
+
// Load contacts again
|
|
2455
|
+
await member1.refresh();
|
|
2456
|
+
|
|
2457
|
+
// Check the contact is updated
|
|
2458
|
+
const expectedContact = EmergencyContact.create({
|
|
2459
|
+
...contact1,
|
|
2460
|
+
phone: '+32412345679',
|
|
2461
|
+
});
|
|
2462
|
+
|
|
2463
|
+
expect(member1.details.emergencyContacts).toEqual([expectedContact]);
|
|
2464
|
+
});
|
|
2465
|
+
|
|
2466
|
+
test('Removing an emergency contact works correctly', async () => {
|
|
2467
|
+
const user = await new UserFactory({}).create();
|
|
2468
|
+
|
|
2469
|
+
const contact1 = EmergencyContact.create({
|
|
2470
|
+
name: 'Linda Doe',
|
|
2471
|
+
title: 'Grandmother',
|
|
2472
|
+
phone: '+32412345678',
|
|
2473
|
+
createdAt: new Date(0),
|
|
2474
|
+
});
|
|
2475
|
+
|
|
2476
|
+
const member1 = await new MemberFactory({
|
|
2477
|
+
user,
|
|
2478
|
+
details: MemberDetails.create({
|
|
2479
|
+
firstName: 'John',
|
|
2480
|
+
lastName: 'Doe',
|
|
2481
|
+
emergencyContacts: [contact1],
|
|
2482
|
+
}),
|
|
2483
|
+
}).create();
|
|
2484
|
+
|
|
2485
|
+
const admin = await new UserFactory({
|
|
2486
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2487
|
+
}).create();
|
|
2488
|
+
const token = await Token.createToken(admin);
|
|
2489
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2490
|
+
nonEmtpyArray.addDelete(contact1.id);
|
|
2491
|
+
|
|
2492
|
+
const arr: Body = new PatchableArray();
|
|
2493
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2494
|
+
id: member1.id,
|
|
2495
|
+
details: MemberDetails.patch({
|
|
2496
|
+
emergencyContacts: nonEmtpyArray,
|
|
2497
|
+
}),
|
|
2498
|
+
});
|
|
2499
|
+
arr.addPatch(patch);
|
|
2500
|
+
|
|
2501
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2502
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2503
|
+
const response = await testServer.test(endpoint, request);
|
|
2504
|
+
|
|
2505
|
+
// Check returned
|
|
2506
|
+
expect(response.status).toBe(200);
|
|
2507
|
+
expect(response.body.members.length).toBe(1);
|
|
2508
|
+
|
|
2509
|
+
// Load contacts again
|
|
2510
|
+
await member1.refresh();
|
|
2511
|
+
|
|
2512
|
+
// Check the contact is removed
|
|
2513
|
+
expect(member1.details.emergencyContacts).toEqual([]);
|
|
2514
|
+
});
|
|
2515
|
+
|
|
2516
|
+
test('Handling multiple members with different emergency contacts works correctly', async () => {
|
|
2517
|
+
const user = await new UserFactory({}).create();
|
|
2518
|
+
|
|
2519
|
+
const contact1 = EmergencyContact.create({
|
|
2520
|
+
name: 'Linda Doe',
|
|
2521
|
+
title: 'Grandmother',
|
|
2522
|
+
phone: '+32412345678',
|
|
2523
|
+
createdAt: new Date(0),
|
|
2524
|
+
});
|
|
2525
|
+
|
|
2526
|
+
const contact2 = EmergencyContact.create({
|
|
2527
|
+
name: 'John Doe',
|
|
2528
|
+
title: 'Uncle',
|
|
2529
|
+
phone: '+32412345679',
|
|
2530
|
+
createdAt: new Date(1000),
|
|
2531
|
+
});
|
|
2532
|
+
|
|
2533
|
+
const member1 = await new MemberFactory({
|
|
2534
|
+
user,
|
|
2535
|
+
details: MemberDetails.create({
|
|
2536
|
+
firstName: 'John',
|
|
2537
|
+
lastName: 'Doe',
|
|
2538
|
+
emergencyContacts: [contact1],
|
|
2539
|
+
}),
|
|
2540
|
+
}).create();
|
|
2541
|
+
|
|
2542
|
+
const member2 = await new MemberFactory({
|
|
2543
|
+
user,
|
|
2544
|
+
details: MemberDetails.create({
|
|
2545
|
+
firstName: 'Jane',
|
|
2546
|
+
lastName: 'Doe',
|
|
2547
|
+
emergencyContacts: [contact2],
|
|
2548
|
+
}),
|
|
2549
|
+
}).create();
|
|
2550
|
+
|
|
2551
|
+
const admin = await new UserFactory({
|
|
2552
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2553
|
+
}).create();
|
|
2554
|
+
const token = await Token.createToken(admin);
|
|
2555
|
+
const nonEmtpyArray1 = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2556
|
+
nonEmtpyArray1.addPatch(EmergencyContact.patch({
|
|
2557
|
+
id: contact1.id,
|
|
2558
|
+
phone: '+32412345680',
|
|
2559
|
+
}));
|
|
2560
|
+
|
|
2561
|
+
const nonEmtpyArray2 = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2562
|
+
nonEmtpyArray2.addPatch(EmergencyContact.patch({
|
|
2563
|
+
id: contact2.id,
|
|
2564
|
+
phone: '+32412345681',
|
|
2565
|
+
}));
|
|
2566
|
+
|
|
2567
|
+
const arr: Body = new PatchableArray();
|
|
2568
|
+
const patch1 = MemberWithRegistrationsBlob.patch({
|
|
2569
|
+
id: member1.id,
|
|
2570
|
+
details: MemberDetails.patch({
|
|
2571
|
+
emergencyContacts: nonEmtpyArray1,
|
|
2572
|
+
}),
|
|
2573
|
+
});
|
|
2574
|
+
const patch2 = MemberWithRegistrationsBlob.patch({
|
|
2575
|
+
id: member2.id,
|
|
2576
|
+
details: MemberDetails.patch({
|
|
2577
|
+
emergencyContacts: nonEmtpyArray2,
|
|
2578
|
+
}),
|
|
2579
|
+
});
|
|
2580
|
+
arr.addPatch(patch1);
|
|
2581
|
+
arr.addPatch(patch2);
|
|
2582
|
+
|
|
2583
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2584
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2585
|
+
const response = await testServer.test(endpoint, request);
|
|
2586
|
+
|
|
2587
|
+
// Check returned
|
|
2588
|
+
expect(response.status).toBe(200);
|
|
2589
|
+
expect(response.body.members.length).toBe(2);
|
|
2590
|
+
|
|
2591
|
+
// Load contacts again
|
|
2592
|
+
await member1.refresh();
|
|
2593
|
+
await member2.refresh();
|
|
2594
|
+
|
|
2595
|
+
// Check the contacts are updated independently
|
|
2596
|
+
const expectedContact1 = EmergencyContact.create({
|
|
2597
|
+
...contact1,
|
|
2598
|
+
phone: '+32412345680',
|
|
2599
|
+
});
|
|
2600
|
+
|
|
2601
|
+
const expectedContact2 = EmergencyContact.create({
|
|
2602
|
+
...contact2,
|
|
2603
|
+
phone: '+32412345681',
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
expect(member1.details.emergencyContacts).toEqual([expectedContact1]);
|
|
2607
|
+
expect(member2.details.emergencyContacts).toEqual([expectedContact2]);
|
|
2608
|
+
});
|
|
2609
|
+
|
|
2610
|
+
test('Handling emergency contacts with different IDs but same details works correctly', async () => {
|
|
2611
|
+
const user = await new UserFactory({}).create();
|
|
2612
|
+
|
|
2613
|
+
const contact1 = EmergencyContact.create({
|
|
2614
|
+
name: 'Linda Doe',
|
|
2615
|
+
title: 'Grandmother',
|
|
2616
|
+
phone: '+32412345678',
|
|
2617
|
+
createdAt: new Date(0),
|
|
2618
|
+
});
|
|
2619
|
+
|
|
2620
|
+
const contact2 = EmergencyContact.create({
|
|
2621
|
+
name: 'Linda Doe',
|
|
2622
|
+
title: 'Grandmother',
|
|
2623
|
+
phone: '+32412345678',
|
|
2624
|
+
createdAt: new Date(1000),
|
|
2625
|
+
});
|
|
2626
|
+
|
|
2627
|
+
const member1 = await new MemberFactory({
|
|
2628
|
+
user,
|
|
2629
|
+
details: MemberDetails.create({
|
|
2630
|
+
firstName: 'John',
|
|
2631
|
+
lastName: 'Doe',
|
|
2632
|
+
emergencyContacts: [contact1],
|
|
2633
|
+
}),
|
|
2634
|
+
}).create();
|
|
2635
|
+
|
|
2636
|
+
const member2 = await new MemberFactory({
|
|
2637
|
+
user,
|
|
2638
|
+
details: MemberDetails.create({
|
|
2639
|
+
firstName: 'Jane',
|
|
2640
|
+
lastName: 'Doe',
|
|
2641
|
+
emergencyContacts: [contact2],
|
|
2642
|
+
}),
|
|
2643
|
+
}).create();
|
|
2644
|
+
|
|
2645
|
+
const admin = await new UserFactory({
|
|
2646
|
+
globalPermissions: Permissions.create({ level: PermissionLevel.Full }),
|
|
2647
|
+
}).create();
|
|
2648
|
+
const token = await Token.createToken(admin);
|
|
2649
|
+
const nonEmtpyArray = new PatchableArray() as PatchableArrayAutoEncoder<EmergencyContact>;
|
|
2650
|
+
nonEmtpyArray.addPatch(EmergencyContact.patch({
|
|
2651
|
+
id: contact1.id,
|
|
2652
|
+
phone: '+32412345679',
|
|
2653
|
+
}));
|
|
2654
|
+
|
|
2655
|
+
const arr: Body = new PatchableArray();
|
|
2656
|
+
const patch = MemberWithRegistrationsBlob.patch({
|
|
2657
|
+
id: member1.id,
|
|
2658
|
+
details: MemberDetails.patch({
|
|
2659
|
+
emergencyContacts: nonEmtpyArray,
|
|
2660
|
+
}),
|
|
2661
|
+
});
|
|
2662
|
+
arr.addPatch(patch);
|
|
2663
|
+
|
|
2664
|
+
const request = Request.buildJson('PATCH', baseUrl, undefined, arr);
|
|
2665
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
2666
|
+
const response = await testServer.test(endpoint, request);
|
|
2667
|
+
|
|
2668
|
+
// Check returned
|
|
2669
|
+
expect(response.status).toBe(200);
|
|
2670
|
+
expect(response.body.members.length).toBe(1);
|
|
2671
|
+
|
|
2672
|
+
// Load contacts again
|
|
2673
|
+
await member1.refresh();
|
|
2674
|
+
await member2.refresh();
|
|
2675
|
+
|
|
2676
|
+
// Check the contacts are updated correctly
|
|
2677
|
+
const expectedContact = EmergencyContact.create({
|
|
2678
|
+
...contact1,
|
|
2679
|
+
phone: '+32412345679',
|
|
2680
|
+
});
|
|
2681
|
+
|
|
2682
|
+
expect(member1.details.emergencyContacts).toEqual([expectedContact]);
|
|
2683
|
+
expect(member2.details.emergencyContacts).toEqual([expectedContact]);
|
|
2684
|
+
});
|
|
2685
|
+
});
|
|
726
2686
|
});
|