@@ -455,14 +455,14 @@ describe('query opportunityById', () => {
455455 } ) ;
456456} ) ;
457457
458- describe ( 'query getOpportunities ' , ( ) => {
458+ describe ( 'query opportunities ' , ( ) => {
459459 const GET_OPPORTUNITIES_QUERY = /* GraphQL */ `
460460 query GetOpportunities(
461461 $state: ProtoEnumValue
462462 $first: Int
463463 $after: String
464464 ) {
465- getOpportunities (state: $state, first: $first, after: $after) {
465+ opportunities (state: $state, first: $first, after: $after) {
466466 pageInfo {
467467 hasNextPage
468468 hasPreviousPage
@@ -515,8 +515,8 @@ describe('query getOpportunities', () => {
515515 } ) ;
516516
517517 expect ( res . errors ) . toBeFalsy ( ) ;
518- expect ( res . data . getOpportunities . edges ) . toHaveLength ( 3 ) ;
519- expect ( res . data . getOpportunities . pageInfo . hasNextPage ) . toBe ( false ) ;
518+ expect ( res . data . opportunities . edges ) . toHaveLength ( 3 ) ;
519+ expect ( res . data . opportunities . pageInfo . hasNextPage ) . toBe ( false ) ;
520520 } ) ;
521521
522522 it ( 'should return only recruiter DRAFT opportunities for authenticated non-team member' , async ( ) => {
@@ -527,8 +527,8 @@ describe('query getOpportunities', () => {
527527 } ) ;
528528
529529 expect ( res . errors ) . toBeFalsy ( ) ;
530- expect ( res . data . getOpportunities . edges ) . toHaveLength ( 1 ) ;
531- expect ( res . data . getOpportunities . edges [ 0 ] . node ) . toEqual (
530+ expect ( res . data . opportunities . edges ) . toHaveLength ( 1 ) ;
531+ expect ( res . data . opportunities . edges [ 0 ] . node ) . toEqual (
532532 expect . objectContaining ( {
533533 id : '550e8400-e29b-41d4-a716-446655440003' ,
534534 state : OpportunityState . DRAFT ,
@@ -544,8 +544,8 @@ describe('query getOpportunities', () => {
544544 } ) ;
545545
546546 expect ( res . errors ) . toBeFalsy ( ) ;
547- expect ( res . data . getOpportunities . edges ) . toHaveLength ( 1 ) ;
548- expect ( res . data . getOpportunities . edges [ 0 ] . node ) . toEqual (
547+ expect ( res . data . opportunities . edges ) . toHaveLength ( 1 ) ;
548+ expect ( res . data . opportunities . edges [ 0 ] . node ) . toEqual (
549549 expect . objectContaining ( {
550550 id : '550e8400-e29b-41d4-a716-446655440004' ,
551551 state : OpportunityState . DRAFT ,
@@ -562,8 +562,8 @@ describe('query getOpportunities', () => {
562562 } ) ;
563563
564564 expect ( res . errors ) . toBeFalsy ( ) ;
565- expect ( res . data . getOpportunities . edges ) . toHaveLength ( 2 ) ;
566- const nodes = res . data . getOpportunities . edges . map (
565+ expect ( res . data . opportunities . edges ) . toHaveLength ( 2 ) ;
566+ const nodes = res . data . opportunities . edges . map (
567567 ( e : { node : unknown } ) => e . node ,
568568 ) ;
569569 expect ( nodes ) . toEqual (
@@ -590,9 +590,9 @@ describe('query getOpportunities', () => {
590590 } ) ;
591591
592592 expect ( res . errors ) . toBeFalsy ( ) ;
593- expect ( res . data . getOpportunities . edges ) . toHaveLength ( 2 ) ;
594- expect ( res . data . getOpportunities . pageInfo . hasNextPage ) . toBe ( true ) ;
595- expect ( res . data . getOpportunities . pageInfo . endCursor ) . toBeTruthy ( ) ;
593+ expect ( res . data . opportunities . edges ) . toHaveLength ( 2 ) ;
594+ expect ( res . data . opportunities . pageInfo . hasNextPage ) . toBe ( true ) ;
595+ expect ( res . data . opportunities . pageInfo . endCursor ) . toBeTruthy ( ) ;
596596 } ) ;
597597
598598 it ( 'should support pagination with after cursor' , async ( ) => {
@@ -604,19 +604,17 @@ describe('query getOpportunities', () => {
604604 } ) ;
605605
606606 expect ( firstPage . errors ) . toBeFalsy ( ) ;
607- const endCursor = firstPage . data . getOpportunities . pageInfo . endCursor ;
607+ const endCursor = firstPage . data . opportunities . pageInfo . endCursor ;
608608
609609 // Get second page
610610 const secondPage = await client . query ( GET_OPPORTUNITIES_QUERY , {
611611 variables : { state : OpportunityState . LIVE , first : 2 , after : endCursor } ,
612612 } ) ;
613613
614614 expect ( secondPage . errors ) . toBeFalsy ( ) ;
615- expect ( secondPage . data . getOpportunities . edges ) . toHaveLength ( 1 ) ;
616- expect ( secondPage . data . getOpportunities . pageInfo . hasNextPage ) . toBe ( false ) ;
617- expect ( secondPage . data . getOpportunities . pageInfo . hasPreviousPage ) . toBe (
618- true ,
619- ) ;
615+ expect ( secondPage . data . opportunities . edges ) . toHaveLength ( 1 ) ;
616+ expect ( secondPage . data . opportunities . pageInfo . hasNextPage ) . toBe ( false ) ;
617+ expect ( secondPage . data . opportunities . pageInfo . hasPreviousPage ) . toBe ( true ) ;
620618 } ) ;
621619} ) ;
622620
@@ -736,14 +734,14 @@ describe('query getOpportunityMatch', () => {
736734 } ) ;
737735} ) ;
738736
739- describe ( 'query getOpportunityMatches ' , ( ) => {
737+ describe ( 'query opportunityMatches ' , ( ) => {
740738 const GET_OPPORTUNITY_MATCHES_QUERY = /* GraphQL */ `
741739 query GetOpportunityMatches(
742740 $opportunityId: ID!
743741 $first: Int
744742 $after: String
745743 ) {
746- getOpportunityMatches (
744+ opportunityMatches (
747745 opportunityId: $opportunityId
748746 first: $first
749747 after: $after
@@ -827,9 +825,9 @@ describe('query getOpportunityMatches', () => {
827825 } ) ;
828826
829827 expect ( res . errors ) . toBeFalsy ( ) ;
830- expect ( res . data . getOpportunityMatches . edges ) . toHaveLength ( 3 ) ;
828+ expect ( res . data . opportunityMatches . edges ) . toHaveLength ( 3 ) ;
831829
832- const statuses = res . data . getOpportunityMatches . edges . map (
830+ const statuses = res . data . opportunityMatches . edges . map (
833831 ( e : { node : { status : string } } ) => e . node . status ,
834832 ) ;
835833
@@ -856,7 +854,7 @@ describe('query getOpportunityMatches', () => {
856854
857855 expect ( res . errors ) . toBeFalsy ( ) ;
858856
859- const acceptedMatch = res . data . getOpportunityMatches . edges . find (
857+ const acceptedMatch = res . data . opportunityMatches . edges . find (
860858 ( e : { node : { status : string } } ) =>
861859 e . node . status === 'candidate_accepted' ,
862860 ) ;
@@ -884,7 +882,7 @@ describe('query getOpportunityMatches', () => {
884882
885883 expect ( res . errors ) . toBeFalsy ( ) ;
886884
887- const acceptedMatch = res . data . getOpportunityMatches . edges . find (
885+ const acceptedMatch = res . data . opportunityMatches . edges . find (
888886 ( e : { node : { status : string } } ) =>
889887 e . node . status === 'candidate_accepted' ,
890888 ) ;
@@ -915,9 +913,9 @@ describe('query getOpportunityMatches', () => {
915913 } ) ;
916914
917915 expect ( res . errors ) . toBeFalsy ( ) ;
918- expect ( res . data . getOpportunityMatches . edges ) . toHaveLength ( 2 ) ;
919- expect ( res . data . getOpportunityMatches . pageInfo . hasNextPage ) . toBe ( true ) ;
920- expect ( res . data . getOpportunityMatches . pageInfo . endCursor ) . toBeTruthy ( ) ;
916+ expect ( res . data . opportunityMatches . edges ) . toHaveLength ( 2 ) ;
917+ expect ( res . data . opportunityMatches . pageInfo . hasNextPage ) . toBe ( true ) ;
918+ expect ( res . data . opportunityMatches . pageInfo . endCursor ) . toBeTruthy ( ) ;
921919 } ) ;
922920
923921 it ( 'should support pagination with after cursor' , async ( ) => {
@@ -932,14 +930,12 @@ describe('query getOpportunityMatches', () => {
932930 } ) ;
933931
934932 expect ( firstPage . errors ) . toBeFalsy ( ) ;
935- expect ( firstPage . data . getOpportunityMatches . edges ) . toHaveLength ( 2 ) ;
936- expect ( firstPage . data . getOpportunityMatches . pageInfo . hasNextPage ) . toBe (
937- true ,
938- ) ;
939- const firstUserIds = firstPage . data . getOpportunityMatches . edges . map (
933+ expect ( firstPage . data . opportunityMatches . edges ) . toHaveLength ( 2 ) ;
934+ expect ( firstPage . data . opportunityMatches . pageInfo . hasNextPage ) . toBe ( true ) ;
935+ const firstUserIds = firstPage . data . opportunityMatches . edges . map (
940936 ( e : { node : { userId : string } } ) => e . node . userId ,
941937 ) ;
942- const endCursor = firstPage . data . getOpportunityMatches . pageInfo . endCursor ;
938+ const endCursor = firstPage . data . opportunityMatches . pageInfo . endCursor ;
943939
944940 // Get second page
945941 const secondPage = await client . query ( GET_OPPORTUNITY_MATCHES_QUERY , {
@@ -951,15 +947,13 @@ describe('query getOpportunityMatches', () => {
951947 } ) ;
952948
953949 expect ( secondPage . errors ) . toBeFalsy ( ) ;
954- expect ( secondPage . data . getOpportunityMatches . edges ) . toHaveLength ( 1 ) ;
955- expect ( secondPage . data . getOpportunityMatches . pageInfo . hasNextPage ) . toBe (
956- false ,
957- ) ;
950+ expect ( secondPage . data . opportunityMatches . edges ) . toHaveLength ( 1 ) ;
951+ expect ( secondPage . data . opportunityMatches . pageInfo . hasNextPage ) . toBe ( false ) ;
958952 // Verify we got different results
959953 expect ( firstUserIds ) . not . toContain (
960- secondPage . data . getOpportunityMatches . edges [ 0 ] . node . userId ,
954+ secondPage . data . opportunityMatches . edges [ 0 ] . node . userId ,
961955 ) ;
962- expect ( secondPage . data . getOpportunityMatches . pageInfo . hasPreviousPage ) . toBe (
956+ expect ( secondPage . data . opportunityMatches . pageInfo . hasPreviousPage ) . toBe (
963957 true ,
964958 ) ;
965959 } ) ;
@@ -1014,8 +1008,63 @@ describe('query getOpportunityMatches', () => {
10141008 } ) ;
10151009
10161010 expect ( res . errors ) . toBeFalsy ( ) ;
1017- expect ( res . data . getOpportunityMatches . edges ) . toHaveLength ( 0 ) ;
1018- expect ( res . data . getOpportunityMatches . pageInfo . hasNextPage ) . toBe ( false ) ;
1011+ expect ( res . data . opportunityMatches . edges ) . toHaveLength ( 0 ) ;
1012+ expect ( res . data . opportunityMatches . pageInfo . hasNextPage ) . toBe ( false ) ;
1013+ } ) ;
1014+
1015+ it ( 'should not expose salaryExpectation to recruiters viewing other candidates' , async ( ) => {
1016+ loggedUser = '1' ; // Recruiter
1017+
1018+ // Add salaryExpectation to user 2's candidate preferences
1019+ await con . getRepository ( UserCandidatePreference ) . update (
1020+ { userId : usersFixture [ 1 ] . id } ,
1021+ {
1022+ salaryExpectation : {
1023+ min : 120000 ,
1024+ period : SalaryPeriod . ANNUALLY ,
1025+ } ,
1026+ } ,
1027+ ) ;
1028+
1029+ const GET_OPPORTUNITY_MATCHES_WITH_SALARY_QUERY = /* GraphQL */ `
1030+ query GetOpportunityMatchesWithSalary($opportunityId: ID!, $first: Int) {
1031+ opportunityMatches(opportunityId: $opportunityId, first: $first) {
1032+ edges {
1033+ node {
1034+ userId
1035+ updatedAt
1036+ candidatePreferences {
1037+ status
1038+ role
1039+ salaryExpectation {
1040+ min
1041+ period
1042+ }
1043+ }
1044+ }
1045+ }
1046+ }
1047+ }
1048+ ` ;
1049+
1050+ const res = await client . query ( GET_OPPORTUNITY_MATCHES_WITH_SALARY_QUERY , {
1051+ variables : {
1052+ opportunityId : '550e8400-e29b-41d4-a716-446655440001' ,
1053+ first : 10 ,
1054+ } ,
1055+ } ) ;
1056+
1057+ expect ( res . errors ) . toBeFalsy ( ) ;
1058+
1059+ // Find the match for user 2 (candidate with salaryExpectation)
1060+ const user2Match = res . data . opportunityMatches . edges . find (
1061+ ( e : { node : { userId : string } } ) => e . node . userId === '2' ,
1062+ ) ;
1063+
1064+ expect ( user2Match ) . toBeDefined ( ) ;
1065+ expect ( user2Match . node . candidatePreferences . role ) . toBe ( 'Senior Developer' ) ;
1066+ // salaryExpectation should be null for recruiter viewing another candidate
1067+ expect ( user2Match . node . candidatePreferences . salaryExpectation ) . toBeNull ( ) ;
10191068 } ) ;
10201069} ) ;
10211070
@@ -1874,22 +1923,6 @@ describe('mutation acceptOpportunityMatch', () => {
18741923 'Access denied! Match is not pending' ,
18751924 ) ;
18761925 } ) ;
1877-
1878- it ( 'should return error when the opportunity is not live' , async ( ) => {
1879- loggedUser = '1' ;
1880-
1881- await testMutationErrorCode (
1882- client ,
1883- {
1884- mutation : MUTATION ,
1885- variables : {
1886- id : '550e8400-e29b-41d4-a716-446655440003' ,
1887- } ,
1888- } ,
1889- 'FORBIDDEN' ,
1890- 'Access denied! Opportunity is not live' ,
1891- ) ;
1892- } ) ;
18931926} ) ;
18941927
18951928describe ( 'mutation rejectOpportunityMatch' , ( ) => {
@@ -1990,22 +2023,6 @@ describe('mutation rejectOpportunityMatch', () => {
19902023 'Access denied! Match is not pending' ,
19912024 ) ;
19922025 } ) ;
1993-
1994- it ( 'should return error when the opportunity is not live' , async ( ) => {
1995- loggedUser = '1' ;
1996-
1997- await testMutationErrorCode (
1998- client ,
1999- {
2000- mutation : MUTATION ,
2001- variables : {
2002- id : '550e8400-e29b-41d4-a716-446655440003' ,
2003- } ,
2004- } ,
2005- 'FORBIDDEN' ,
2006- 'Access denied! Opportunity is not live' ,
2007- ) ;
2008- } ) ;
20092026} ) ;
20102027
20112028describe ( 'mutation recruiterAcceptOpportunityMatch' , ( ) => {
@@ -2107,40 +2124,6 @@ describe('mutation recruiterAcceptOpportunityMatch', () => {
21072124 ) ;
21082125 } ) ;
21092126
2110- it ( 'should return error when the opportunity is not live' , async ( ) => {
2111- loggedUser = '1' ;
2112-
2113- await saveFixtures ( con , OpportunityUser , [
2114- {
2115- opportunityId : opportunitiesFixture [ 2 ] . id ,
2116- userId : usersFixture [ 0 ] . id ,
2117- type : OpportunityUserType . Recruiter ,
2118- } ,
2119- ] ) ;
2120-
2121- // Update the existing Pending match to CandidateAccepted
2122- await con . getRepository ( OpportunityMatch ) . update (
2123- {
2124- opportunityId : opportunitiesFixture [ 2 ] . id ,
2125- userId : usersFixture [ 0 ] . id ,
2126- } ,
2127- { status : OpportunityMatchStatus . CandidateAccepted } ,
2128- ) ;
2129-
2130- await testMutationErrorCode (
2131- client ,
2132- {
2133- mutation : MUTATION ,
2134- variables : {
2135- opportunityId : '550e8400-e29b-41d4-a716-446655440003' , // DRAFT opportunity
2136- candidateUserId : '1' ,
2137- } ,
2138- } ,
2139- 'FORBIDDEN' ,
2140- 'Access denied! Opportunity is not live' ,
2141- ) ;
2142- } ) ;
2143-
21442127 it ( 'should return error when match does not exist' , async ( ) => {
21452128 loggedUser = '1' ;
21462129
@@ -2427,40 +2410,6 @@ describe('mutation recruiterRejectOpportunityMatch', () => {
24272410 ) ;
24282411 } ) ;
24292412
2430- it ( 'should return error when the opportunity is not live' , async ( ) => {
2431- loggedUser = '1' ;
2432-
2433- await saveFixtures ( con , OpportunityUser , [
2434- {
2435- opportunityId : opportunitiesFixture [ 2 ] . id ,
2436- userId : usersFixture [ 0 ] . id ,
2437- type : OpportunityUserType . Recruiter ,
2438- } ,
2439- ] ) ;
2440-
2441- // Update the existing Pending match to CandidateAccepted
2442- await con . getRepository ( OpportunityMatch ) . update (
2443- {
2444- opportunityId : opportunitiesFixture [ 2 ] . id ,
2445- userId : usersFixture [ 0 ] . id ,
2446- } ,
2447- { status : OpportunityMatchStatus . CandidateAccepted } ,
2448- ) ;
2449-
2450- await testMutationErrorCode (
2451- client ,
2452- {
2453- mutation : MUTATION ,
2454- variables : {
2455- opportunityId : '550e8400-e29b-41d4-a716-446655440003' , // DRAFT opportunity
2456- candidateUserId : '1' ,
2457- } ,
2458- } ,
2459- 'FORBIDDEN' ,
2460- 'Access denied! Opportunity is not live' ,
2461- ) ;
2462- } ) ;
2463-
24642413 it ( 'should return error when match does not exist' , async ( ) => {
24652414 loggedUser = '1' ;
24662415
0 commit comments