mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(client): add job experience widget to profile (#63503)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
+22
-10
@@ -55,17 +55,28 @@ type Portfolio {
|
||||
url String
|
||||
}
|
||||
|
||||
type Experience {
|
||||
id String
|
||||
title String
|
||||
company String
|
||||
location String?
|
||||
startDate String
|
||||
endDate String?
|
||||
description String
|
||||
}
|
||||
|
||||
type ProfileUI {
|
||||
isLocked Boolean? // Undefined
|
||||
showAbout Boolean? // Undefined
|
||||
showCerts Boolean? // Undefined
|
||||
showDonation Boolean? // Undefined
|
||||
showHeatMap Boolean? // Undefined
|
||||
showLocation Boolean? // Undefined
|
||||
showName Boolean? // Undefined
|
||||
showPoints Boolean? // Undefined
|
||||
showPortfolio Boolean? // Undefined
|
||||
showTimeLine Boolean? // Undefined
|
||||
isLocked Boolean? // Undefined
|
||||
showAbout Boolean? // Undefined
|
||||
showCerts Boolean? // Undefined
|
||||
showDonation Boolean? // Undefined
|
||||
showHeatMap Boolean? // Undefined
|
||||
showLocation Boolean? // Undefined
|
||||
showName Boolean? // Undefined
|
||||
showPoints Boolean? // Undefined
|
||||
showPortfolio Boolean? // Undefined
|
||||
showExperience Boolean? // Undefined
|
||||
showTimeLine Boolean? // Undefined
|
||||
}
|
||||
|
||||
type SavedChallengeFile {
|
||||
@@ -152,6 +163,7 @@ model user {
|
||||
password String? // Undefined
|
||||
picture String?
|
||||
portfolio Portfolio[]
|
||||
experience Experience[]
|
||||
profileUI ProfileUI? // Undefined
|
||||
progressTimestamps Json? // ProgressTimestamp[] | Null[] | Int64[] | Double[] - TODO: NORMALIZE
|
||||
/// A random number between 0 and 1.
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ type FastifyInstanceWithTypeProvider = FastifyInstance<
|
||||
const ajv = new Ajv({
|
||||
coerceTypes: 'array', // change data type of data to match type keyword
|
||||
useDefaults: true, // replace missing properties and items with the values from corresponding default keyword
|
||||
removeAdditional: true, // remove additional properties
|
||||
removeAdditional: 'all', // remove additional properties
|
||||
uriResolver,
|
||||
addUsedSchema: false,
|
||||
// Explicitly set allErrors to `false`.
|
||||
|
||||
@@ -21,6 +21,7 @@ export const newUser = (email: string) => ({
|
||||
emailAuthLinkTTL: null,
|
||||
emailVerified: true,
|
||||
emailVerifyTTL: null,
|
||||
experience: [],
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
externalId: expect.stringMatching(uuidRe),
|
||||
githubProfile: null,
|
||||
@@ -80,6 +81,7 @@ export const newUser = (email: string) => ({
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showExperience: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
|
||||
@@ -32,6 +32,7 @@ const baseProfileUI = {
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showExperience: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
@@ -1192,6 +1193,234 @@ Happy coding!
|
||||
});
|
||||
});
|
||||
|
||||
describe('/update-my-experience', () => {
|
||||
test('PUT returns 200 status code with "success" message and saves experience', async () => {
|
||||
const payload = {
|
||||
experience: [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Software Engineer',
|
||||
company: 'Tech Corp',
|
||||
location: 'Remote',
|
||||
startDate: '2020-01',
|
||||
endDate: '2022-06',
|
||||
description: 'Worked on various projects'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const response = await superPut('/update-my-experience').send(payload);
|
||||
|
||||
expect(response.body).toEqual({
|
||||
message: 'flash.experience-updated',
|
||||
type: 'success'
|
||||
});
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
|
||||
expect(user?.experience).toEqual(payload.experience);
|
||||
});
|
||||
|
||||
test('rejects extraneous keys on entries', async () => {
|
||||
const res = await superPut('/update-my-experience').send({
|
||||
experience: [
|
||||
{
|
||||
id: 'x',
|
||||
title: 'Dev',
|
||||
company: 'Co',
|
||||
startDate: '',
|
||||
description: '',
|
||||
foo: 'bar'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
|
||||
expect(user?.experience).toEqual([
|
||||
{
|
||||
id: 'x',
|
||||
title: 'Dev',
|
||||
company: 'Co',
|
||||
location: null,
|
||||
startDate: '',
|
||||
endDate: null,
|
||||
description: ''
|
||||
}
|
||||
]);
|
||||
expect(res.statusCode).toBe(200);
|
||||
});
|
||||
|
||||
test('returns 400 when experience is not an array', async () => {
|
||||
const response = await superPut('/update-my-experience').send({
|
||||
experience: { not: 'an array' } as unknown as []
|
||||
});
|
||||
expect(response.body).toEqual(updateErrorResponse);
|
||||
expect(response.statusCode).toEqual(400);
|
||||
});
|
||||
|
||||
test('supports current position (omitted endDate becomes null)', async () => {
|
||||
const response = await superPut('/update-my-experience').send({
|
||||
experience: [
|
||||
{
|
||||
id: 'cur',
|
||||
title: 'Engineer',
|
||||
company: 'Now Co',
|
||||
startDate: '2023-01',
|
||||
description: ''
|
||||
// endDate omitted
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
expect(user?.experience?.[0]).toEqual({
|
||||
id: 'cur',
|
||||
title: 'Engineer',
|
||||
company: 'Now Co',
|
||||
location: null,
|
||||
startDate: '2023-01',
|
||||
endDate: null,
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
test('accepts long descriptions', async () => {
|
||||
const long = 'x'.repeat(1000);
|
||||
const response = await superPut('/update-my-experience').send({
|
||||
experience: [
|
||||
{
|
||||
id: '',
|
||||
title: 'Writer',
|
||||
company: 'Docs Inc',
|
||||
startDate: '2020-01',
|
||||
endDate: '2020-12',
|
||||
description: long
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
expect(user?.experience?.[0]?.description).toEqual(long);
|
||||
});
|
||||
test('PUT accepts empty array and clears experience', async () => {
|
||||
// seed with one item first
|
||||
await superPut('/update-my-experience').send({
|
||||
experience: [
|
||||
{
|
||||
id: 'seed',
|
||||
title: 'Seed Title',
|
||||
company: 'Seed Co',
|
||||
location: 'Seed City',
|
||||
startDate: '2019-01',
|
||||
endDate: '2019-12',
|
||||
description: 'Seed desc'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const response = await superPut('/update-my-experience').send({
|
||||
experience: []
|
||||
});
|
||||
|
||||
expect(response.body).toEqual({
|
||||
message: 'flash.experience-updated',
|
||||
type: 'success'
|
||||
});
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
expect(user?.experience).toEqual([]);
|
||||
});
|
||||
|
||||
test('PUT saves multiple experiences and preserves order', async () => {
|
||||
const payload = {
|
||||
experience: [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Junior Dev',
|
||||
company: 'A Inc',
|
||||
location: 'NY',
|
||||
startDate: '2018-01',
|
||||
endDate: '2019-01',
|
||||
description: 'Did stuff'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Senior Dev',
|
||||
company: 'B LLC',
|
||||
location: 'SF',
|
||||
startDate: '2019-02',
|
||||
endDate: '2021-03',
|
||||
description: 'Did more stuff'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const response = await superPut('/update-my-experience').send(payload);
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
const user = await fastifyTestInstance.prisma.user.findFirst({
|
||||
where: { email: developerUserEmail },
|
||||
select: { experience: true }
|
||||
});
|
||||
expect(user?.experience).toEqual(payload.experience);
|
||||
});
|
||||
|
||||
test('PUT returns 400 status code when the experience property is missing', async () => {
|
||||
const response = await superPut('/update-my-experience').send({});
|
||||
|
||||
expect(response.body).toEqual(updateErrorResponse);
|
||||
expect(response.statusCode).toEqual(400);
|
||||
});
|
||||
|
||||
test('PUT returns 400 status code when any data is the wrong type', async () => {
|
||||
const response = await superPut('/update-my-experience').send({
|
||||
experience: [
|
||||
{
|
||||
id: '',
|
||||
title: '',
|
||||
company: '',
|
||||
location: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
title: {},
|
||||
company: '',
|
||||
location: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
description: ''
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(response.body).toEqual(updateErrorResponse);
|
||||
expect(response.statusCode).toEqual(400);
|
||||
});
|
||||
});
|
||||
|
||||
describe('/update-my-classroom-mode', () => {
|
||||
test('PUT returns 200 status code with "success" message', async () => {
|
||||
const response = await superPut('/update-my-classroom-mode').send({
|
||||
@@ -1263,7 +1492,8 @@ Happy coding!
|
||||
{ path: '/update-my-about', method: 'PUT' },
|
||||
{ path: '/update-my-honesty', method: 'PUT' },
|
||||
{ path: '/update-privacy-terms', method: 'PUT' },
|
||||
{ path: '/update-my-portfolio', method: 'PUT' }
|
||||
{ path: '/update-my-portfolio', method: 'PUT' },
|
||||
{ path: '/update-my-experience', method: 'PUT' }
|
||||
];
|
||||
|
||||
endpoints.forEach(({ path, method }) => {
|
||||
|
||||
@@ -166,6 +166,7 @@ export const settingRoutes: FastifyPluginCallbackTypebox = (
|
||||
showName: req.body.profileUI.showName,
|
||||
showPoints: req.body.profileUI.showPoints,
|
||||
showPortfolio: req.body.profileUI.showPortfolio,
|
||||
showExperience: req.body.profileUI.showExperience,
|
||||
showTimeLine: req.body.profileUI.showTimeLine
|
||||
}
|
||||
}
|
||||
@@ -711,6 +712,36 @@ ${isLinkSentWithinLimitTTL}`
|
||||
}
|
||||
);
|
||||
|
||||
fastify.put(
|
||||
'/update-my-experience',
|
||||
{
|
||||
schema: schemas.updateMyExperience
|
||||
},
|
||||
async (req, reply) => {
|
||||
const logger = fastify.log.child({ req, res: reply });
|
||||
try {
|
||||
const { experience } = req.body;
|
||||
|
||||
await fastify.prisma.user.update({
|
||||
where: { id: req.user?.id },
|
||||
data: {
|
||||
experience
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: 'flash.experience-updated',
|
||||
type: 'success'
|
||||
} as const;
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
fastify.Sentry.captureException(err);
|
||||
void reply.code(500);
|
||||
return { message: 'flash.wrong-updating', type: 'danger' } as const;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
fastify.put(
|
||||
'/update-my-classroom-mode',
|
||||
{
|
||||
|
||||
@@ -177,6 +177,7 @@ const lockedProfileUI = {
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showExperience: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
@@ -271,6 +272,7 @@ const publicUserData = {
|
||||
completedExams: testUserData.completedExams,
|
||||
completedSurveys: [], // TODO: add surveys
|
||||
quizAttempts: testUserData.quizAttempts,
|
||||
experience: [],
|
||||
githubProfile: testUserData.githubProfile,
|
||||
is2018DataVisCert: testUserData.is2018DataVisCert,
|
||||
is2018FullStackCert: testUserData.is2018FullStackCert, // TODO: should this be returned? The client doesn't use it at the moment.
|
||||
@@ -1005,6 +1007,7 @@ describe('userRoutes', () => {
|
||||
completedDailyCodingChallenges: [],
|
||||
completedExams: [],
|
||||
completedSurveys: [],
|
||||
experience: [],
|
||||
partiallyCompletedChallenges: [],
|
||||
portfolio: [],
|
||||
savedChallenges: [],
|
||||
|
||||
@@ -722,6 +722,7 @@ export const userGetRoutes: FastifyPluginCallbackTypebox = (
|
||||
partiallyCompletedChallenges: true,
|
||||
picture: true,
|
||||
portfolio: true,
|
||||
experience: true,
|
||||
profileUI: true,
|
||||
progressTimestamps: true,
|
||||
savedChallenges: true,
|
||||
@@ -781,6 +782,7 @@ export const userGetRoutes: FastifyPluginCallbackTypebox = (
|
||||
location,
|
||||
name,
|
||||
theme,
|
||||
experience,
|
||||
...publicUser
|
||||
} = rest;
|
||||
|
||||
@@ -818,6 +820,7 @@ export const userGetRoutes: FastifyPluginCallbackTypebox = (
|
||||
usernameDisplay: usernameDisplay || username,
|
||||
userToken: encodedToken,
|
||||
completedSurveys: normalizeSurveys(completedSurveys),
|
||||
experience: experience.map(removeNulls),
|
||||
msUsername: msUsername?.msUsername
|
||||
}
|
||||
},
|
||||
|
||||
@@ -127,6 +127,7 @@ const lockedProfileUI = {
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showExperience: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
@@ -253,6 +254,7 @@ describe('userRoutes', () => {
|
||||
showAbout: true,
|
||||
showCerts: true,
|
||||
showDonation: true,
|
||||
showExperience: false,
|
||||
showHeatMap: true,
|
||||
showLocation: true,
|
||||
showName: true,
|
||||
@@ -485,6 +487,7 @@ describe('get-public-profile helpers', () => {
|
||||
description: 'description'
|
||||
}
|
||||
],
|
||||
experience: [],
|
||||
profileUI: {
|
||||
isLocked: false,
|
||||
showAbout: true,
|
||||
@@ -495,7 +498,8 @@ describe('get-public-profile helpers', () => {
|
||||
showName: true,
|
||||
showPoints: true,
|
||||
showPortfolio: true,
|
||||
showTimeLine: true
|
||||
showTimeLine: true,
|
||||
showExperience: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Portfolio } from '@prisma/client';
|
||||
import { Experience, Portfolio } from '@prisma/client';
|
||||
import { type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { omit } from 'lodash-es';
|
||||
@@ -33,6 +33,7 @@ type ProfileUI = Partial<{
|
||||
showName: boolean;
|
||||
showPoints: boolean;
|
||||
showPortfolio: boolean;
|
||||
showExperience: boolean;
|
||||
showTimeLine: boolean;
|
||||
}>;
|
||||
|
||||
@@ -47,6 +48,7 @@ type RawUser = {
|
||||
name: string;
|
||||
points: number;
|
||||
portfolio: Portfolio[];
|
||||
experience: Experience[];
|
||||
profileUI: ProfileUI;
|
||||
};
|
||||
|
||||
@@ -65,6 +67,7 @@ export const replacePrivateData = (user: RawUser) => {
|
||||
showName,
|
||||
showPoints,
|
||||
showPortfolio,
|
||||
showExperience,
|
||||
showTimeLine
|
||||
} = user.profileUI;
|
||||
|
||||
@@ -83,7 +86,8 @@ export const replacePrivateData = (user: RawUser) => {
|
||||
location: showLocation ? user.location : '',
|
||||
name: showName ? user.name : '',
|
||||
points: showPoints ? user.points : null,
|
||||
portfolio: showPortfolio ? user.portfolio : []
|
||||
portfolio: showPortfolio ? user.portfolio : [],
|
||||
experience: showExperience ? user.experience : []
|
||||
};
|
||||
};
|
||||
|
||||
@@ -185,7 +189,8 @@ export const userPublicGetRoutes: FastifyPluginCallbackTypebox = (
|
||||
joinDate: new ObjectId(user.id).getTimestamp().toISOString(),
|
||||
name: user.name ?? '',
|
||||
points: getPoints(progressTimestamps),
|
||||
profileUI: normalizedProfileUI
|
||||
profileUI: normalizedProfileUI,
|
||||
experience: user.experience ?? []
|
||||
});
|
||||
|
||||
const returnedUser = {
|
||||
|
||||
@@ -24,6 +24,7 @@ export { updateMyAbout } from './schemas/settings/update-my-about.js';
|
||||
export { confirmEmail } from './schemas/settings/confirm-email.js';
|
||||
export { updateMyClassroomMode } from './schemas/settings/update-my-classroom-mode.js';
|
||||
export { updateMyEmail } from './schemas/settings/update-my-email.js';
|
||||
export { updateMyExperience } from './schemas/settings/update-my-experience.js';
|
||||
export { updateMyHonesty } from './schemas/settings/update-my-honesty.js';
|
||||
export { updateMyKeyboardShortcuts } from './schemas/settings/update-my-keyboard-shortcuts.js';
|
||||
export { updateMyPortfolio } from './schemas/settings/update-my-portfolio.js';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Type } from '@fastify/type-provider-typebox';
|
||||
|
||||
export const updateMyExperience = {
|
||||
body: Type.Object({
|
||||
experience: Type.Array(
|
||||
Type.Object(
|
||||
{
|
||||
id: Type.String(),
|
||||
title: Type.String(),
|
||||
company: Type.String(),
|
||||
location: Type.Optional(Type.String()),
|
||||
startDate: Type.String(),
|
||||
endDate: Type.Optional(Type.String()),
|
||||
description: Type.String()
|
||||
},
|
||||
{ additionalProperties: false }
|
||||
)
|
||||
)
|
||||
}),
|
||||
response: {
|
||||
200: Type.Object({
|
||||
message: Type.Literal('flash.experience-updated'),
|
||||
type: Type.Literal('success')
|
||||
}),
|
||||
400: Type.Object({
|
||||
message: Type.Literal('flash.wrong-updating'),
|
||||
type: Type.Literal('danger')
|
||||
}),
|
||||
500: Type.Object({
|
||||
message: Type.Literal('flash.wrong-updating'),
|
||||
type: Type.Literal('danger')
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -12,6 +12,7 @@ export const updateMyProfileUI = {
|
||||
showName: Type.Boolean(),
|
||||
showPoints: Type.Boolean(),
|
||||
showPortfolio: Type.Boolean(),
|
||||
showExperience: Type.Boolean(),
|
||||
showTimeLine: Type.Boolean()
|
||||
})
|
||||
}),
|
||||
|
||||
@@ -79,5 +79,16 @@ export const profileUI = Type.Object({
|
||||
showName: Type.Optional(Type.Boolean()),
|
||||
showPoints: Type.Optional(Type.Boolean()),
|
||||
showPortfolio: Type.Optional(Type.Boolean()),
|
||||
showTimeLine: Type.Optional(Type.Boolean())
|
||||
showTimeLine: Type.Optional(Type.Boolean()),
|
||||
showExperience: Type.Optional(Type.Boolean())
|
||||
});
|
||||
|
||||
export const experience = Type.Object({
|
||||
id: Type.String(),
|
||||
title: Type.String(),
|
||||
company: Type.String(),
|
||||
location: Type.Optional(Type.String()),
|
||||
startDate: Type.String(),
|
||||
endDate: Type.Optional(Type.String()),
|
||||
description: Type.String()
|
||||
});
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { Type } from '@fastify/type-provider-typebox';
|
||||
import { examResults, profileUI, savedChallenge } from '../types.js';
|
||||
import {
|
||||
examResults,
|
||||
profileUI,
|
||||
savedChallenge,
|
||||
experience
|
||||
} from '../types.js';
|
||||
|
||||
const languages = Type.Array(
|
||||
Type.Union([Type.Literal('javascript'), Type.Literal('python')])
|
||||
@@ -118,6 +123,7 @@ export const getSessionUser = {
|
||||
url: Type.String()
|
||||
})
|
||||
),
|
||||
experience: Type.Optional(Type.Array(experience)),
|
||||
profileUI: Type.Optional(profileUI),
|
||||
sendQuincyEmail: Type.Union([Type.Null(), Type.Boolean()]), // // Tri-state: null (likely new user), true (subscribed), false (unsubscribed)
|
||||
theme: Type.String(),
|
||||
|
||||
@@ -87,6 +87,7 @@ export function createUserInput(email: string) {
|
||||
showAbout: false,
|
||||
showCerts: false,
|
||||
showDonation: false,
|
||||
showExperience: false,
|
||||
showHeatMap: false,
|
||||
showLocation: false,
|
||||
showName: false,
|
||||
|
||||
@@ -50,7 +50,8 @@ describe('normalize', () => {
|
||||
showName: true,
|
||||
showPoints: true,
|
||||
showPortfolio: true,
|
||||
showTimeLine: true
|
||||
showTimeLine: true,
|
||||
showExperience: true
|
||||
};
|
||||
|
||||
const defaultProfileUI = {
|
||||
@@ -63,7 +64,8 @@ describe('normalize', () => {
|
||||
showName: false,
|
||||
showPoints: false,
|
||||
showPortfolio: false,
|
||||
showTimeLine: false
|
||||
showTimeLine: false,
|
||||
showExperience: false
|
||||
};
|
||||
|
||||
describe('normalizeProfileUI', () => {
|
||||
@@ -87,7 +89,8 @@ describe('normalize', () => {
|
||||
showName: null,
|
||||
showPoints: null,
|
||||
showPortfolio: null,
|
||||
showTimeLine: null
|
||||
showTimeLine: null,
|
||||
showExperience: null
|
||||
};
|
||||
expect(normalizeProfileUI(input)).toEqual({
|
||||
isLocked: undefined,
|
||||
@@ -99,7 +102,8 @@ describe('normalize', () => {
|
||||
showName: undefined,
|
||||
showPoints: undefined,
|
||||
showPortfolio: undefined,
|
||||
showTimeLine: undefined
|
||||
showTimeLine: undefined,
|
||||
showExperience: undefined
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -137,7 +137,8 @@ export const normalizeProfileUI = (
|
||||
showName: false,
|
||||
showPoints: false,
|
||||
showPortfolio: false,
|
||||
showTimeLine: false
|
||||
showTimeLine: false,
|
||||
showExperience: false
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user