@@ -142,6 +142,12 @@ import * as googleCloud from '../src/common/googleCloud';
142142import { RESUMES_BUCKET_NAME } from '../src/common/googleCloud' ;
143143import { fileTypeFromBuffer } from './setup' ;
144144import { Bucket } from '@google-cloud/storage' ;
145+ import { UserWorkExperience } from '../src/entity/user/experiences/UserWorkExperience' ;
146+ import { ExperienceStatus } from '../src/entity/user/experiences/types' ;
147+ import {
148+ UserJobPreferences ,
149+ WorkLocationType ,
150+ } from '../src/entity/user/UserJobPreferences' ;
145151
146152jest . mock ( '../src/common/geo' , ( ) => ( {
147153 ...( jest . requireActual ( '../src/common/geo' ) as Record < string , unknown > ) ,
@@ -6991,3 +6997,301 @@ describe('mutation uploadResume', () => {
69916997 expect ( body . errors [ 0 ] . message ) . toEqual ( 'File type not supported' ) ;
69926998 } ) ;
69936999} ) ;
7000+
7001+ describe ( 'user job preferences' , ( ) => {
7002+ const QUERY = `
7003+ query UserJobPreferences {
7004+ userJobPreferences {
7005+ openToOpportunities
7006+ preferredRoles
7007+ preferredLocationType
7008+ openToRelocation
7009+ currentTotalComp {
7010+ currency
7011+ amount
7012+ }
7013+ }
7014+ }
7015+ ` ;
7016+
7017+ beforeEach ( async ( ) => {
7018+ // Set up a user with job preferences
7019+ await con . getRepository ( UserJobPreferences ) . save ( {
7020+ userId : '1' ,
7021+ openToOpportunities : true ,
7022+ preferredRoles : [ 'Software Engineer' , 'Frontend Developer' ] ,
7023+ preferredLocationType : 'remote' ,
7024+ openToRelocation : false ,
7025+ currentTotalComp : {
7026+ currency : 'USD' ,
7027+ amount : 10 ,
7028+ } ,
7029+ } ) ;
7030+
7031+ await saveFixtures ( con , UserJobPreferences , [
7032+ {
7033+ userId : '1' ,
7034+ openToOpportunities : true ,
7035+ preferredRoles : [ 'Software Engineer' , 'Frontend Developer' ] ,
7036+ preferredLocationType : WorkLocationType . Remote ,
7037+ openToRelocation : false ,
7038+ currentTotalComp : {
7039+ currency : 'USD' ,
7040+ amount : 10 ,
7041+ } ,
7042+ } ,
7043+ {
7044+ userId : '2' ,
7045+ openToOpportunities : true ,
7046+ preferredRoles : [ ] ,
7047+ preferredLocationType : WorkLocationType . Remote ,
7048+ openToRelocation : false ,
7049+ currentTotalComp : {
7050+ currency : 'USD' ,
7051+ amount : 10 ,
7052+ } ,
7053+ } ,
7054+ ] ) ;
7055+
7056+ // Set up a user with a complete profile
7057+ await con . getRepository ( User ) . update ( '1' , {
7058+ flags : {
7059+ country : 'US' ,
7060+ } ,
7061+ } ) ;
7062+
7063+ // Add work experience to make sure profile is complete
7064+ await saveFixtures ( con , UserWorkExperience , [
7065+ {
7066+ userId : '1' ,
7067+ title : 'Software Engineer' ,
7068+ status : ExperienceStatus . Published ,
7069+ description : '' ,
7070+ startDate : new Date ( ) ,
7071+ } ,
7072+ {
7073+ userId : '1' ,
7074+ title : 'Senior Software Engineer' ,
7075+ status : ExperienceStatus . Published ,
7076+ description : '' ,
7077+ startDate : new Date ( ) ,
7078+ } ,
7079+ {
7080+ userId : '1' ,
7081+ title : 'Software Developer' ,
7082+ status : ExperienceStatus . Published ,
7083+ description : '' ,
7084+ startDate : new Date ( ) ,
7085+ } ,
7086+ {
7087+ userId : '1' ,
7088+ title : 'Frontend Developer' ,
7089+ status : ExperienceStatus . Published ,
7090+ description : '' ,
7091+ startDate : new Date ( ) ,
7092+ } ,
7093+ {
7094+ userId : '1' ,
7095+ title : 'Draft Job Title' ,
7096+ status : ExperienceStatus . Draft ,
7097+ description : '' ,
7098+ startDate : new Date ( ) ,
7099+ } ,
7100+ ] ) ;
7101+ } ) ;
7102+
7103+ describe ( 'query userJobPreferences' , ( ) => {
7104+ it ( 'should throw error on query as guest' , async ( ) => {
7105+ return testQueryErrorCode ( client , { query : QUERY } , 'UNAUTHENTICATED' ) ;
7106+ } ) ;
7107+
7108+ it ( 'should return user job preferences' , async ( ) => {
7109+ loggedUser = '1' ;
7110+ const res = await client . query ( QUERY ) ;
7111+ expect ( res . errors ) . toBeFalsy ( ) ;
7112+ expect ( res . data . userJobPreferences ) . toMatchObject ( {
7113+ openToOpportunities : true ,
7114+ preferredRoles : [ 'Software Engineer' , 'Frontend Developer' ] ,
7115+ preferredLocationType : 'remote' ,
7116+ openToRelocation : false ,
7117+ currentTotalComp : {
7118+ currency : 'USD' ,
7119+ amount : 10 ,
7120+ } ,
7121+ } ) ;
7122+ } ) ;
7123+
7124+ it ( 'should force openToOpportunities to false if profile is not complete' , async ( ) => {
7125+ loggedUser = '2' ; // User without job preferences
7126+ const res = await client . query ( QUERY ) ;
7127+ expect ( res . errors ) . toBeFalsy ( ) ;
7128+ expect ( res . data . userJobPreferences ) . toMatchObject ( {
7129+ // fetched as false even if is true on preferences since have no experiences
7130+ openToOpportunities : false ,
7131+ preferredRoles : [ ] ,
7132+ preferredLocationType : WorkLocationType . Remote ,
7133+ openToRelocation : false ,
7134+ currentTotalComp : { } ,
7135+ } ) ;
7136+ } ) ;
7137+ } ) ;
7138+
7139+ describe ( 'mutation updateUserJobPreferences' , ( ) => {
7140+ const MUTATION = `
7141+ mutation UpdateUserJobPreferences(
7142+ $openToOpportunities: Boolean!
7143+ $preferredRoles: [String!]!
7144+ $preferredLocationType: String
7145+ $openToRelocation: Boolean!
7146+ $currentTotalComp: UserTotalCompensationInput!
7147+ ) {
7148+ updateUserJobPreferences(
7149+ openToOpportunities: $openToOpportunities
7150+ preferredRoles: $preferredRoles
7151+ preferredLocationType: $preferredLocationType
7152+ openToRelocation: $openToRelocation
7153+ currentTotalComp: $currentTotalComp
7154+ ) {
7155+ openToOpportunities
7156+ preferredRoles
7157+ preferredLocationType
7158+ openToRelocation
7159+ currentTotalComp {
7160+ currency
7161+ amount
7162+ }
7163+ }
7164+ }
7165+ ` ;
7166+
7167+ it ( 'should throw error on mutation as guest' , async ( ) => {
7168+ return testMutationErrorCode (
7169+ client ,
7170+ {
7171+ mutation : MUTATION ,
7172+ variables : {
7173+ openToOpportunities : true ,
7174+ preferredRoles : [ 'Software Engineer' ] ,
7175+ preferredLocationType : 'remote' ,
7176+ openToRelocation : false ,
7177+ currentTotalComp : { } ,
7178+ } ,
7179+ } ,
7180+ 'UNAUTHENTICATED' ,
7181+ ) ;
7182+ } ) ;
7183+
7184+ it ( 'should update user job preferences' , async ( ) => {
7185+ loggedUser = '1' ;
7186+ const variables = {
7187+ openToOpportunities : false ,
7188+ preferredRoles : [ 'Product Manager' , 'Project Manager' ] ,
7189+ preferredLocationType : WorkLocationType . Remote ,
7190+ openToRelocation : true ,
7191+ currentTotalComp : {
7192+ currency : 'EUR' ,
7193+ amount : 10 ,
7194+ } ,
7195+ } ;
7196+
7197+ const res = await client . mutate ( MUTATION , { variables } ) ;
7198+ expect ( res . errors ) . toBeFalsy ( ) ;
7199+ expect ( res . data . updateUserJobPreferences ) . toMatchObject ( {
7200+ openToOpportunities : false ,
7201+ preferredRoles : [ 'Product Manager' , 'Project Manager' ] ,
7202+ preferredLocationType : WorkLocationType . Remote ,
7203+ openToRelocation : true ,
7204+ currentTotalComp : {
7205+ currency : 'EUR' ,
7206+ amount : 10 ,
7207+ } ,
7208+ } ) ;
7209+
7210+ // Verify database state
7211+ const updatedPrefs = await con
7212+ . getRepository ( 'UserJobPreferences' )
7213+ . findOne ( {
7214+ where : { userId : '1' } ,
7215+ } ) ;
7216+ expect ( updatedPrefs ) . toMatchObject ( {
7217+ openToOpportunities : false ,
7218+ preferredRoles : [ 'Product Manager' , 'Project Manager' ] ,
7219+ preferredLocationType : WorkLocationType . Remote ,
7220+ openToRelocation : true ,
7221+ currentTotalComp : {
7222+ currency : 'EUR' ,
7223+ amount : 10 ,
7224+ } ,
7225+ } ) ;
7226+ } ) ;
7227+
7228+ it ( 'should throw error on invalid job preferences' , async ( ) => {
7229+ loggedUser = '1' ;
7230+
7231+ // Test with too many preferred roles
7232+ const variables = {
7233+ openToOpportunities : true ,
7234+ preferredRoles : [
7235+ 'Role 1' ,
7236+ 'Role 2' ,
7237+ 'Role 3' ,
7238+ 'Role 4' ,
7239+ 'Role 5' ,
7240+ 'Role 6' ,
7241+ ] ,
7242+ preferredLocationType : 'remote' ,
7243+ openToRelocation : false ,
7244+ currentTotalComp : { } ,
7245+ } ;
7246+
7247+ return testMutationErrorCode (
7248+ client ,
7249+ { mutation : MUTATION , variables } ,
7250+ 'GRAPHQL_VALIDATION_FAILED' ,
7251+ 'Invalid job preferences data. Please check your input.' ,
7252+ ) ;
7253+ } ) ;
7254+
7255+ it ( 'should not update user job preferences of other user' , async ( ) => {
7256+ // Create job preferences for user 2
7257+ await con . getRepository ( 'UserJobPreferences' ) . save ( {
7258+ userId : '2' ,
7259+ openToOpportunities : false ,
7260+ preferredRoles : [ 'Designer' ] ,
7261+ preferredLocationType : 'on_site' ,
7262+ openToRelocation : true ,
7263+ currentTotalComp : {
7264+ currency : 'GBP' ,
7265+ amount : 20 ,
7266+ } ,
7267+ } ) ;
7268+
7269+ // Log in as user 1
7270+ loggedUser = '1' ;
7271+
7272+ // Try to update user 2's preferences by setting userId
7273+ const variables = {
7274+ userId : '2' , // This should be ignored
7275+ openToOpportunities : true ,
7276+ preferredRoles : [ 'Hacker' ] ,
7277+ preferredLocationType : 'remote' ,
7278+ openToRelocation : false ,
7279+ currentTotalComp : { } ,
7280+ } ;
7281+
7282+ const res = await client . mutate ( MUTATION , { variables } ) ;
7283+ expect ( res . errors ) . toBeFalsy ( ) ;
7284+
7285+ // Verify that user 1's preferences were updated, not user 2's
7286+ const user1Prefs = await con . getRepository ( 'UserJobPreferences' ) . findOne ( {
7287+ where : { userId : '1' } ,
7288+ } ) ;
7289+ expect ( user1Prefs ?. preferredRoles ) . toContain ( 'Hacker' ) ;
7290+
7291+ const user2Prefs = await con . getRepository ( 'UserJobPreferences' ) . findOne ( {
7292+ where : { userId : '2' } ,
7293+ } ) ;
7294+ expect ( user2Prefs ?. preferredRoles ) . toEqual ( [ 'Designer' ] ) ;
7295+ } ) ;
7296+ } ) ;
7297+ } ) ;
0 commit comments