fix(client): display legacy certs like current ones (#42038)
* fix: display legacy certs like the current ones * fix: link projects in legacy certs to project pages * fix: update tests to changed legacy cert display * fix: update tests for removed legacy certs forms * fix: display legacy certs like the current ones * fix: submit projects for cert on projects pages * fix: remove legacy certs form submitting handling * fix: move claiming cert setup before both tests * fix: remove legacy cert update props and actions * fix: remove legacy cert updates from api * fix: correct merge conflict
This commit is contained in:
@ -28,7 +28,6 @@ export default function settingsController(app) {
|
|||||||
updateMyCurrentChallenge
|
updateMyCurrentChallenge
|
||||||
);
|
);
|
||||||
api.post('/update-my-portfolio', ifNoUser401, updateMyPortfolio);
|
api.post('/update-my-portfolio', ifNoUser401, updateMyPortfolio);
|
||||||
api.post('/update-my-projects', ifNoUser401, updateMyProjects);
|
|
||||||
api.post(
|
api.post(
|
||||||
'/update-my-theme',
|
'/update-my-theme',
|
||||||
ifNoUser401,
|
ifNoUser401,
|
||||||
@ -159,16 +158,6 @@ function updateMyProfileUI(req, res, next) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMyProjects(req, res, next) {
|
|
||||||
const {
|
|
||||||
user,
|
|
||||||
body: { projects: project }
|
|
||||||
} = req;
|
|
||||||
return user
|
|
||||||
.updateMyProjects(project)
|
|
||||||
.subscribe(message => res.json({ message }), next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMyAbout(req, res, next) {
|
function updateMyAbout(req, res, next) {
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
|
@ -80,7 +80,6 @@ let blocklist = [
|
|||||||
'unsubscribed',
|
'unsubscribed',
|
||||||
'update-my-portfolio',
|
'update-my-portfolio',
|
||||||
'update-my-profile-ui',
|
'update-my-profile-ui',
|
||||||
'update-my-projects',
|
|
||||||
'update-my-theme',
|
'update-my-theme',
|
||||||
'update-my-username',
|
'update-my-username',
|
||||||
'user',
|
'user',
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
import { find, first } from 'lodash-es';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { find, first, values, isString } from 'lodash-es';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
Button,
|
Button,
|
||||||
@ -21,16 +19,10 @@ import {
|
|||||||
import SectionHeader from './SectionHeader';
|
import SectionHeader from './SectionHeader';
|
||||||
import ProjectModal from '../SolutionViewer/ProjectModal';
|
import ProjectModal from '../SolutionViewer/ProjectModal';
|
||||||
import { FullWidthRow, Spacer } from '../helpers';
|
import { FullWidthRow, Spacer } from '../helpers';
|
||||||
import { Form } from '../formHelpers';
|
|
||||||
|
|
||||||
import { maybeUrlRE } from '../../utils';
|
import { maybeUrlRE } from '../../utils';
|
||||||
import reallyWeirdErrorMessage from '../../utils/reallyWeirdErrorMessage';
|
|
||||||
|
|
||||||
import './certification.css';
|
import './certification.css';
|
||||||
import { updateLegacyCert } from '../../redux/settings';
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch =>
|
|
||||||
bindActionCreators({ updateLegacyCert }, dispatch);
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
completedChallenges: PropTypes.arrayOf(
|
completedChallenges: PropTypes.arrayOf(
|
||||||
@ -61,7 +53,6 @@ const propTypes = {
|
|||||||
isRespWebDesignCert: PropTypes.bool,
|
isRespWebDesignCert: PropTypes.bool,
|
||||||
isSciCompPyCertV7: PropTypes.bool,
|
isSciCompPyCertV7: PropTypes.bool,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
updateLegacyCert: PropTypes.func.isRequired,
|
|
||||||
username: PropTypes.string,
|
username: PropTypes.string,
|
||||||
verifyCert: PropTypes.func.isRequired
|
verifyCert: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
@ -156,7 +147,6 @@ export class CertificationSettings extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = { ...initialState };
|
this.state = { ...initialState };
|
||||||
this.handleSubmitLegacy = this.handleSubmitLegacy.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createHandleLinkButtonClick = to => e => {
|
createHandleLinkButtonClick = to => e => {
|
||||||
@ -258,9 +248,9 @@ export class CertificationSettings extends Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderCertifications = certName => {
|
renderCertifications = (certName, projectsMap) => {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
const { certSlug } = first(projectMap[certName]);
|
const { certSlug } = first(projectsMap[certName]);
|
||||||
return (
|
return (
|
||||||
<FullWidthRow key={certName}>
|
<FullWidthRow key={certName}>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
@ -277,17 +267,18 @@ export class CertificationSettings extends Component {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{this.renderProjectsFor(
|
{this.renderProjectsFor(
|
||||||
certName,
|
certName,
|
||||||
this.getUserIsCertMap()[certName]
|
this.getUserIsCertMap()[certName],
|
||||||
|
projectsMap
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</FullWidthRow>
|
</FullWidthRow>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
renderProjectsFor = (certName, isCert) => {
|
renderProjectsFor = (certName, isCert, projectsMap) => {
|
||||||
const { username, isHonest, createFlashMessage, t, verifyCert } =
|
const { username, isHonest, createFlashMessage, t, verifyCert } =
|
||||||
this.props;
|
this.props;
|
||||||
const { certSlug } = first(projectMap[certName]);
|
const { certSlug } = first(projectsMap[certName]);
|
||||||
const certLocation = `/certification/${username}/${certSlug}`;
|
const certLocation = `/certification/${username}/${certSlug}`;
|
||||||
const createClickHandler = certSlug => e => {
|
const createClickHandler = certSlug => e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -298,7 +289,7 @@ export class CertificationSettings extends Component {
|
|||||||
? verifyCert(certSlug)
|
? verifyCert(certSlug)
|
||||||
: createFlashMessage(honestyInfoMessage);
|
: createFlashMessage(honestyInfoMessage);
|
||||||
};
|
};
|
||||||
return projectMap[certName]
|
return projectsMap[certName]
|
||||||
.map(({ link, title, id }) => (
|
.map(({ link, title, id }) => (
|
||||||
<tr className='project-row' key={id}>
|
<tr className='project-row' key={id}>
|
||||||
<td className='project-title col-sm-8'>
|
<td className='project-title col-sm-8'>
|
||||||
@ -325,160 +316,6 @@ export class CertificationSettings extends Component {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// legacy projects rendering
|
|
||||||
handleSubmitLegacy({ values: formChalObj }) {
|
|
||||||
const { isHonest, createFlashMessage, verifyCert, updateLegacyCert } =
|
|
||||||
this.props;
|
|
||||||
let legacyTitle;
|
|
||||||
let certSlug;
|
|
||||||
let certs = Object.keys(legacyProjectMap);
|
|
||||||
let loopBreak = false;
|
|
||||||
for (let certTitle of certs) {
|
|
||||||
for (let chalTitle of legacyProjectMap[certTitle]) {
|
|
||||||
if (chalTitle.title === Object.keys(formChalObj)[0]) {
|
|
||||||
certSlug = chalTitle.certSlug;
|
|
||||||
loopBreak = true;
|
|
||||||
legacyTitle = certTitle;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (loopBreak) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make an object with keys as challenge ids and values as solutions
|
|
||||||
let idsToSolutions = {};
|
|
||||||
for (let i of Object.keys(formChalObj)) {
|
|
||||||
for (let j of legacyProjectMap[legacyTitle]) {
|
|
||||||
if (i === j.title) {
|
|
||||||
idsToSolutions[j.id] = formChalObj[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter the new solutions that need to be updated
|
|
||||||
const completedChallenges = this.props.completedChallenges;
|
|
||||||
let challengesToUpdate = {};
|
|
||||||
let newChallengeFound = true;
|
|
||||||
let oldSubmissions = 0;
|
|
||||||
for (let submittedChal of Object.keys(idsToSolutions)) {
|
|
||||||
for (let i of completedChallenges) {
|
|
||||||
if (i.id === submittedChal) {
|
|
||||||
if (idsToSolutions[submittedChal] !== i.solution) {
|
|
||||||
challengesToUpdate[submittedChal] = idsToSolutions[submittedChal];
|
|
||||||
}
|
|
||||||
oldSubmissions++;
|
|
||||||
newChallengeFound = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newChallengeFound && idsToSolutions[submittedChal] !== '') {
|
|
||||||
challengesToUpdate[submittedChal] = idsToSolutions[submittedChal];
|
|
||||||
}
|
|
||||||
newChallengeFound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const valuesSaved = values(formChalObj).filter(Boolean).filter(isString);
|
|
||||||
|
|
||||||
const isProjectSectionComplete = valuesSaved.length === oldSubmissions;
|
|
||||||
|
|
||||||
if (isProjectSectionComplete) {
|
|
||||||
return isHonest
|
|
||||||
? verifyCert(certSlug)
|
|
||||||
: createFlashMessage(honestyInfoMessage);
|
|
||||||
}
|
|
||||||
return updateLegacyCert({ challengesToUpdate, certSlug });
|
|
||||||
}
|
|
||||||
|
|
||||||
renderLegacyCertifications = certName => {
|
|
||||||
const { username, createFlashMessage, completedChallenges, t } = this.props;
|
|
||||||
const { certSlug } = first(legacyProjectMap[certName]);
|
|
||||||
const certLocation = `/certification/${username}/${certSlug}`;
|
|
||||||
const challengeTitles = legacyProjectMap[certName].map(item => item.title);
|
|
||||||
const isCertClaimed = this.getUserIsCertMap()[certName];
|
|
||||||
const initialObject = {};
|
|
||||||
let filledforms = 0;
|
|
||||||
legacyProjectMap[certName].forEach(project => {
|
|
||||||
let completedProject = find(completedChallenges, function (challenge) {
|
|
||||||
return challenge['id'] === project['id'];
|
|
||||||
});
|
|
||||||
if (!completedProject) {
|
|
||||||
initialObject[project.title] = '';
|
|
||||||
} else {
|
|
||||||
initialObject[project.title] = completedProject.solution;
|
|
||||||
filledforms++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const options = challengeTitles.reduce(
|
|
||||||
(options, current) => {
|
|
||||||
options.types[current] = 'url';
|
|
||||||
return options;
|
|
||||||
},
|
|
||||||
{ types: {} }
|
|
||||||
);
|
|
||||||
|
|
||||||
const formFields = challengeTitles.map(title => ({
|
|
||||||
name: title,
|
|
||||||
label: title
|
|
||||||
}));
|
|
||||||
|
|
||||||
const fullForm = filledforms === challengeTitles.length;
|
|
||||||
|
|
||||||
const createClickHandler = certLocation => e => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (isCertClaimed) {
|
|
||||||
return navigate(certLocation);
|
|
||||||
}
|
|
||||||
return createFlashMessage(reallyWeirdErrorMessage);
|
|
||||||
};
|
|
||||||
|
|
||||||
const buttonStyle = {
|
|
||||||
marginBottom: '1.45rem'
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FullWidthRow key={certSlug}>
|
|
||||||
<Spacer />
|
|
||||||
<h3 className='text-center' id={`cert-${certSlug}`}>
|
|
||||||
{certName}
|
|
||||||
</h3>
|
|
||||||
<Form
|
|
||||||
buttonText={
|
|
||||||
fullForm ? t('buttons.claim-cert') : t('buttons.save-progress')
|
|
||||||
}
|
|
||||||
enableSubmit={fullForm}
|
|
||||||
formFields={formFields}
|
|
||||||
hideButton={isCertClaimed}
|
|
||||||
id={certSlug}
|
|
||||||
initialValues={{
|
|
||||||
...initialObject
|
|
||||||
}}
|
|
||||||
options={options}
|
|
||||||
submit={this.handleSubmitLegacy}
|
|
||||||
/>
|
|
||||||
{isCertClaimed ? (
|
|
||||||
<div className={'col-xs-12'}>
|
|
||||||
<Button
|
|
||||||
bsSize='sm'
|
|
||||||
bsStyle='primary'
|
|
||||||
className={'col-xs-12'}
|
|
||||||
href={certLocation}
|
|
||||||
id={'button-' + certSlug}
|
|
||||||
onClick={createClickHandler(certLocation)}
|
|
||||||
style={buttonStyle}
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
{t('buttons.show-cert')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</FullWidthRow>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
renderLegacyFullStack = () => {
|
renderLegacyFullStack = () => {
|
||||||
const {
|
const {
|
||||||
isFullStackCert,
|
isFullStackCert,
|
||||||
@ -587,10 +424,14 @@ export class CertificationSettings extends Component {
|
|||||||
return (
|
return (
|
||||||
<section id='certification-settings'>
|
<section id='certification-settings'>
|
||||||
<SectionHeader>{t('settings.headings.certs')}</SectionHeader>
|
<SectionHeader>{t('settings.headings.certs')}</SectionHeader>
|
||||||
{certifications.map(this.renderCertifications)}
|
{certifications.map(certName =>
|
||||||
|
this.renderCertifications(certName, projectMap)
|
||||||
|
)}
|
||||||
<SectionHeader>{t('settings.headings.legacy-certs')}</SectionHeader>
|
<SectionHeader>{t('settings.headings.legacy-certs')}</SectionHeader>
|
||||||
{this.renderLegacyFullStack()}
|
{this.renderLegacyFullStack()}
|
||||||
{legacyCertifications.map(this.renderLegacyCertifications)}
|
{legacyCertifications.map(certName =>
|
||||||
|
this.renderCertifications(certName, legacyProjectMap)
|
||||||
|
)}
|
||||||
{isOpen ? (
|
{isOpen ? (
|
||||||
<ProjectModal
|
<ProjectModal
|
||||||
files={files}
|
files={files}
|
||||||
@ -609,7 +450,4 @@ export class CertificationSettings extends Component {
|
|||||||
CertificationSettings.displayName = 'CertificationSettings';
|
CertificationSettings.displayName = 'CertificationSettings';
|
||||||
CertificationSettings.propTypes = propTypes;
|
CertificationSettings.propTypes = propTypes;
|
||||||
|
|
||||||
export default connect(
|
export default withTranslation()(CertificationSettings);
|
||||||
null,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(withTranslation()(CertificationSettings));
|
|
||||||
|
@ -22,7 +22,9 @@ describe('<certification />', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
container.querySelector('#button-legacy-data-visualization')
|
container.querySelector(
|
||||||
|
'a[href="/certification/developmentuser/legacy-data-visualization"]'
|
||||||
|
)
|
||||||
).toHaveTextContent('buttons.show-cert');
|
).toHaveTextContent('buttons.show-cert');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -32,33 +34,36 @@ describe('<certification />', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
container.querySelector('#button-legacy-data-visualization')
|
container.querySelector(
|
||||||
).toHaveAttribute(
|
'a[href="/certification/developmentuser/legacy-data-visualization"]'
|
||||||
'href',
|
)
|
||||||
'/certification/developmentuser/legacy-data-visualization'
|
).toBeInTheDocument();
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// full forms with unclaimed certs should should not shallow render button
|
// full forms with unclaimed certs should not shallow render show cert button
|
||||||
it('Should not render show cert button for unclaimed full form', () => {
|
it('Should not render show cert button for unclaimed cert with completed projects', () => {
|
||||||
const { container } = renderWithRedux(
|
const { container } = renderWithRedux(
|
||||||
<CertificationSettings {...defaultTestProps} />
|
<CertificationSettings {...defaultTestProps} />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
container.querySelector('#button-legacy-back-end')
|
container.querySelector(
|
||||||
).not.toBeInTheDocument();
|
'a[href="/certification/developmentuser/legacy-back-end"]'
|
||||||
|
)
|
||||||
|
).not.toHaveTextContent('buttons.show-cert');
|
||||||
});
|
});
|
||||||
|
|
||||||
// empty forms with unclaimed certs should should not shallow render button
|
// empty forms with unclaimed certs should not shallow render show cert button
|
||||||
it('Should not render show cert button for empty form', () => {
|
it('Should not render show cert button for cert with no completed projects', () => {
|
||||||
const { container } = renderWithRedux(
|
const { container } = renderWithRedux(
|
||||||
<CertificationSettings {...defaultTestProps} />
|
<CertificationSettings {...defaultTestProps} />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
container.querySelector('#button-legacy-front-end')
|
container.querySelector(
|
||||||
).not.toBeInTheDocument();
|
'a[href="/certification/developmentuser/legacy-front-end"]'
|
||||||
|
)
|
||||||
|
).not.toHaveTextContent('buttons.show-cert');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Render button when only solution is present', () => {
|
it('Render button when only solution is present', () => {
|
||||||
@ -243,7 +248,6 @@ const defaultTestProps = {
|
|||||||
isSciCompPyCertV7: false,
|
isSciCompPyCertV7: false,
|
||||||
isDataAnalysisPyCertV7: false,
|
isDataAnalysisPyCertV7: false,
|
||||||
isMachineLearningPyCertV7: false,
|
isMachineLearningPyCertV7: false,
|
||||||
updateLegacyCert: () => {},
|
|
||||||
username: 'developmentuser',
|
username: 'developmentuser',
|
||||||
verifyCert: () => {},
|
verifyCert: () => {},
|
||||||
errors: {},
|
errors: {},
|
||||||
|
@ -5,10 +5,6 @@ import { createDangerZoneSaga } from './danger-zone-saga';
|
|||||||
import { createSettingsSagas } from './settings-sagas';
|
import { createSettingsSagas } from './settings-sagas';
|
||||||
import { createUpdateMyEmailSaga } from './update-email-saga';
|
import { createUpdateMyEmailSaga } from './update-email-saga';
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
import { createUpdateLegacyCertSaga } from
|
|
||||||
'./update-legacy-certificate-saga';
|
|
||||||
|
|
||||||
export const ns = 'settings';
|
export const ns = 'settings';
|
||||||
|
|
||||||
const defaultFetchState = {
|
const defaultFetchState = {
|
||||||
@ -31,7 +27,6 @@ export const types = createTypes(
|
|||||||
...createAsyncTypes('submitNewAbout'),
|
...createAsyncTypes('submitNewAbout'),
|
||||||
...createAsyncTypes('submitNewUsername'),
|
...createAsyncTypes('submitNewUsername'),
|
||||||
...createAsyncTypes('updateMyEmail'),
|
...createAsyncTypes('updateMyEmail'),
|
||||||
...createAsyncTypes('updateLegacyCert'),
|
|
||||||
...createAsyncTypes('updateUserFlag'),
|
...createAsyncTypes('updateUserFlag'),
|
||||||
...createAsyncTypes('submitProfileUI'),
|
...createAsyncTypes('submitProfileUI'),
|
||||||
...createAsyncTypes('verifyCert'),
|
...createAsyncTypes('verifyCert'),
|
||||||
@ -44,8 +39,7 @@ export const types = createTypes(
|
|||||||
export const sagas = [
|
export const sagas = [
|
||||||
...createSettingsSagas(types),
|
...createSettingsSagas(types),
|
||||||
...createUpdateMyEmailSaga(types),
|
...createUpdateMyEmailSaga(types),
|
||||||
...createDangerZoneSaga(types),
|
...createDangerZoneSaga(types)
|
||||||
...createUpdateLegacyCertSaga(types)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const checkForSuccessPayload = ({ type, payload }) =>
|
const checkForSuccessPayload = ({ type, payload }) =>
|
||||||
@ -78,12 +72,6 @@ export const updateMyEmail = createAction(types.updateMyEmail);
|
|||||||
export const updateMyEmailComplete = createAction(types.updateMyEmailComplete);
|
export const updateMyEmailComplete = createAction(types.updateMyEmailComplete);
|
||||||
export const updateMyEmailError = createAction(types.updateMyEmailError);
|
export const updateMyEmailError = createAction(types.updateMyEmailError);
|
||||||
|
|
||||||
export const updateLegacyCert = createAction(types.updateLegacyCert);
|
|
||||||
export const updateLegacyCertComplete = createAction(
|
|
||||||
types.updateLegacyCertComplete
|
|
||||||
);
|
|
||||||
export const updateLegacyCertError = createAction(types.updateLegacyCertError);
|
|
||||||
|
|
||||||
export const updateUserFlag = createAction(types.updateUserFlag);
|
export const updateUserFlag = createAction(types.updateUserFlag);
|
||||||
export const updateUserFlagComplete = createAction(
|
export const updateUserFlagComplete = createAction(
|
||||||
types.updateUserFlagComplete,
|
types.updateUserFlagComplete,
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
import { takeEvery, call, put } from 'redux-saga/effects';
|
|
||||||
|
|
||||||
import { putUpdateLegacyCert } from '../../utils/ajax';
|
|
||||||
import { submitComplete } from '../';
|
|
||||||
import { createFlashMessage } from '../../components/Flash/redux';
|
|
||||||
import reallyWeirdErrorMessage from '../../utils/reallyWeirdErrorMessage';
|
|
||||||
import { updateLegacyCertError } from './';
|
|
||||||
|
|
||||||
function* updateLegacyCertSaga({
|
|
||||||
payload: { superBlock, challengesToUpdate }
|
|
||||||
}) {
|
|
||||||
// shape the body of the http call so it is consumable by api
|
|
||||||
const body = {
|
|
||||||
projects: {
|
|
||||||
[superBlock]: challengesToUpdate
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// shape to update completed challenges in redux store
|
|
||||||
let reduxShape = [];
|
|
||||||
for (let obj in challengesToUpdate) {
|
|
||||||
if (challengesToUpdate.hasOwnProperty(obj)) {
|
|
||||||
reduxShape.push({ id: obj, solution: challengesToUpdate[obj] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { data: response } = yield call(putUpdateLegacyCert, body);
|
|
||||||
yield put(submitComplete({ challArray: reduxShape }));
|
|
||||||
yield put(createFlashMessage(response));
|
|
||||||
} catch (e) {
|
|
||||||
yield put(updateLegacyCertError(e));
|
|
||||||
yield put(createFlashMessage(reallyWeirdErrorMessage));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createUpdateLegacyCertSaga(types) {
|
|
||||||
return [takeEvery(types.updateLegacyCert, updateLegacyCertSaga)];
|
|
||||||
}
|
|
@ -16,10 +16,17 @@ const dataAnalysisPyBase =
|
|||||||
'/learn/data-analysis-with-python/data-analysis-with-python-projects';
|
'/learn/data-analysis-with-python/data-analysis-with-python-projects';
|
||||||
const machineLearningPyBase =
|
const machineLearningPyBase =
|
||||||
'/learn/machine-learning-with-python/machine-learning-with-python-projects';
|
'/learn/machine-learning-with-python/machine-learning-with-python-projects';
|
||||||
const legacyFrontEndBase = '';
|
const takeHomeBase = '/learn/coding-interview-prep/take-home-projects';
|
||||||
const legacyBackEndBase = '';
|
const legacyFrontEndBase = feLibsBase;
|
||||||
const legacyDataVisBase = '';
|
const legacyFrontEndResponsiveBase = responsiveWebBase;
|
||||||
const legacyInfosecQaBase = '';
|
const legacyFrontEndTakeHomeBase = takeHomeBase;
|
||||||
|
const legacyBackEndBase = apiMicroBase;
|
||||||
|
const legacyBackEndTakeHomeBase = takeHomeBase;
|
||||||
|
const legacyDataVisBase = dataVisBase;
|
||||||
|
const legacyDataVisFrontEndBase = feLibsBase;
|
||||||
|
const legacyDataVisTakeHomeBase = takeHomeBase;
|
||||||
|
const legacyInfosecQaQaBase = qaBase;
|
||||||
|
const legacyInfosecQaInfosecBase = infoSecBase;
|
||||||
|
|
||||||
// TODO: generate this automatically in a separate file
|
// TODO: generate this automatically in a separate file
|
||||||
// from the md/meta.json files for each cert and projects
|
// from the md/meta.json files for each cert and projects
|
||||||
@ -33,7 +40,7 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7158d8c242eddfaeb5bd13',
|
id: 'bd7158d8c242eddfaeb5bd13',
|
||||||
title: 'Build a Personal Portfolio Webpage',
|
title: 'Build a Personal Portfolio Webpage',
|
||||||
link: `${legacyFrontEndBase}/build-a-personal-portfolio-webpage`,
|
link: `${legacyFrontEndResponsiveBase}/build-a-personal-portfolio-webpage`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -57,37 +64,37 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7158d8c442eddfaeb5bd10',
|
id: 'bd7158d8c442eddfaeb5bd10',
|
||||||
title: 'Show the Local Weather',
|
title: 'Show the Local Weather',
|
||||||
link: `${legacyFrontEndBase}/show-the-local-weather`,
|
link: `${legacyFrontEndTakeHomeBase}/show-the-local-weather`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c442eddfaeb5bd1f',
|
id: 'bd7158d8c442eddfaeb5bd1f',
|
||||||
title: 'Use the TwitchTV JSON API',
|
title: 'Use the TwitchTV JSON API',
|
||||||
link: `${legacyFrontEndBase}/use-the-twitchtv-json-api`,
|
link: `${legacyFrontEndTakeHomeBase}/use-the-twitch-json-api`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c442eddfaeb5bd18',
|
id: 'bd7158d8c442eddfaeb5bd18',
|
||||||
title: 'Stylize Stories on Camper News',
|
title: 'Build a Tribute Page',
|
||||||
link: `${legacyFrontEndBase}/stylize-stories-on-camper-news`,
|
link: `${legacyFrontEndResponsiveBase}/build-a-tribute-page`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c442eddfaeb5bd19',
|
id: 'bd7158d8c442eddfaeb5bd19',
|
||||||
title: 'Build a Wikipedia Viewer',
|
title: 'Build a Wikipedia Viewer',
|
||||||
link: `${legacyFrontEndBase}/build-a-wikipedia-viewer`,
|
link: `${legacyFrontEndTakeHomeBase}/build-a-wikipedia-viewer`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c442eedfaeb5bd1c',
|
id: 'bd7158d8c442eedfaeb5bd1c',
|
||||||
title: 'Build a Tic Tac Toe Game',
|
title: 'Build a Tic Tac Toe Game',
|
||||||
link: `${legacyFrontEndBase}/build-a-tic-tac-toe-game`,
|
link: `${legacyFrontEndTakeHomeBase}/build-a-tic-tac-toe-game`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c442eddfaeb5bd1c',
|
id: 'bd7158d8c442eddfaeb5bd1c',
|
||||||
title: 'Build a Simon Game',
|
title: 'Build a Simon Game',
|
||||||
link: `${legacyFrontEndBase}/build-a-simon-game`,
|
link: `${legacyFrontEndTakeHomeBase}/build-a-simon-game`,
|
||||||
certSlug: 'legacy-front-end'
|
certSlug: 'legacy-front-end'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -119,7 +126,7 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7158d8c443edefaeb5bdee',
|
id: 'bd7158d8c443edefaeb5bdee',
|
||||||
title: 'Image Search Abstraction Layer',
|
title: 'Image Search Abstraction Layer',
|
||||||
link: `${legacyBackEndBase}/image-search-abstraction-layer`,
|
link: `${legacyBackEndTakeHomeBase}/build-an-image-search-abstraction-layer`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -131,31 +138,31 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7158d8c443eddfaeb5bdef',
|
id: 'bd7158d8c443eddfaeb5bdef',
|
||||||
title: 'Build a Voting App',
|
title: 'Build a Voting App',
|
||||||
link: `${legacyBackEndBase}/build-a-voting-app`,
|
link: `${legacyBackEndTakeHomeBase}/build-a-voting-app`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c443eddfaeb5bdff',
|
id: 'bd7158d8c443eddfaeb5bdff',
|
||||||
title: 'Build a Nightlife Coordination App',
|
title: 'Build a Nightlife Coordination App',
|
||||||
link: `${legacyBackEndBase}/build-a-nightlife-coordination-app`,
|
link: `${legacyBackEndTakeHomeBase}/build-a-nightlife-coordination-app`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c443eddfaeb5bd0e',
|
id: 'bd7158d8c443eddfaeb5bd0e',
|
||||||
title: 'Chart the Stock Market',
|
title: 'Chart the Stock Market',
|
||||||
link: `${legacyBackEndBase}/chart-the-stock-market`,
|
link: `${legacyBackEndTakeHomeBase}/chart-the-stock-market`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c443eddfaeb5bd0f',
|
id: 'bd7158d8c443eddfaeb5bd0f',
|
||||||
title: 'Manage a Book Trading Club',
|
title: 'Manage a Book Trading Club',
|
||||||
link: `${legacyBackEndBase}/manage-a-book-trading-club`,
|
link: `${legacyBackEndTakeHomeBase}/manage-a-book-trading-club`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7158d8c443eddfaeb5bdee',
|
id: 'bd7158d8c443eddfaeb5bdee',
|
||||||
title: 'Build a Pinterest Clone',
|
title: 'Build a Pinterest Clone',
|
||||||
link: `${legacyBackEndBase}/build-a-pinterest-clone`,
|
link: `${legacyBackEndTakeHomeBase}/build-a-pinterest-clone`,
|
||||||
certSlug: 'legacy-back-end'
|
certSlug: 'legacy-back-end'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -177,31 +184,31 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7157d8c242eddfaeb5bd13',
|
id: 'bd7157d8c242eddfaeb5bd13',
|
||||||
title: 'Build a Markdown Previewer',
|
title: 'Build a Markdown Previewer',
|
||||||
link: `${legacyDataVisBase}/build-a-markdown-previewer`,
|
link: `${legacyDataVisFrontEndBase}/build-a-markdown-previewer`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7156d8c242eddfaeb5bd13',
|
id: 'bd7156d8c242eddfaeb5bd13',
|
||||||
title: 'Build a Camper Leaderboard',
|
title: 'Build a freeCodeCamp Forum Homepage',
|
||||||
link: `${legacyDataVisBase}/build-a-camper-leaderboard`,
|
link: `${legacyDataVisTakeHomeBase}/build-a-freecodecamp-forum-homepage`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7155d8c242eddfaeb5bd13',
|
id: 'bd7155d8c242eddfaeb5bd13',
|
||||||
title: 'Build a Recipe Box',
|
title: 'Build a Recipe Box',
|
||||||
link: `${legacyDataVisBase}/build-a-recipe-box`,
|
link: `${legacyDataVisTakeHomeBase}/build-a-recipe-box`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7154d8c242eddfaeb5bd13',
|
id: 'bd7154d8c242eddfaeb5bd13',
|
||||||
title: 'Build the Game of Life',
|
title: 'Build the Game of Life',
|
||||||
link: `${legacyDataVisBase}/build-the-game-of-life`,
|
link: `${legacyDataVisTakeHomeBase}/build-the-game-of-life`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7153d8c242eddfaeb5bd13',
|
id: 'bd7153d8c242eddfaeb5bd13',
|
||||||
title: 'Build a Roguelike Dungeon Crawler Game',
|
title: 'Build a Roguelike Dungeon Crawler Game',
|
||||||
link: `${legacyDataVisBase}/build-a-roguelike-dungeon-crawler-game`,
|
link: `${legacyDataVisTakeHomeBase}/build-a-roguelike-dungeon-crawler-game`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -225,13 +232,13 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: 'bd7198d8c242eddfaeb5bd13',
|
id: 'bd7198d8c242eddfaeb5bd13',
|
||||||
title: 'Show National Contiguity with a Force Directed Graph',
|
title: 'Show National Contiguity with a Force Directed Graph',
|
||||||
link: `${legacyDataVisBase}/show-national-contiguity-with-a-force-directed-graph`,
|
link: `${legacyDataVisTakeHomeBase}/show-national-contiguity-with-a-force-directed-graph`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bd7108d8c242eddfaeb5bd13',
|
id: 'bd7108d8c242eddfaeb5bd13',
|
||||||
title: 'Map Data Across the Globe',
|
title: 'Map Data Across the Globe',
|
||||||
link: `${legacyDataVisBase}/map-data-across-the-globe`,
|
link: `${legacyDataVisTakeHomeBase}/map-data-across-the-globe`,
|
||||||
certSlug: 'legacy-data-visualization'
|
certSlug: 'legacy-data-visualization'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -247,31 +254,31 @@ const certMap = [
|
|||||||
{
|
{
|
||||||
id: '587d8249367417b2b2512c41',
|
id: '587d8249367417b2b2512c41',
|
||||||
title: 'Metric-Imperial Converter',
|
title: 'Metric-Imperial Converter',
|
||||||
link: `${legacyInfosecQaBase}/metric-imperial-converter`,
|
link: `${legacyInfosecQaQaBase}/metric-imperial-converter`,
|
||||||
certSlug: 'information-security-and-quality-assurance'
|
certSlug: 'information-security-and-quality-assurance'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '587d8249367417b2b2512c42',
|
id: '587d8249367417b2b2512c42',
|
||||||
title: 'Issue Tracker',
|
title: 'Issue Tracker',
|
||||||
link: `${legacyInfosecQaBase}/issue-tracker`,
|
link: `${legacyInfosecQaQaBase}/issue-tracker`,
|
||||||
certSlug: 'information-security-and-quality-assurance'
|
certSlug: 'information-security-and-quality-assurance'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '587d824a367417b2b2512c43',
|
id: '587d824a367417b2b2512c43',
|
||||||
title: 'Personal Library',
|
title: 'Personal Library',
|
||||||
link: `${legacyInfosecQaBase}/personal-library`,
|
link: `${legacyInfosecQaQaBase}/personal-library`,
|
||||||
certSlug: 'information-security-and-quality-assurance'
|
certSlug: 'information-security-and-quality-assurance'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '587d824a367417b2b2512c44',
|
id: '587d824a367417b2b2512c44',
|
||||||
title: 'Stock Price Checker',
|
title: 'Stock Price Checker',
|
||||||
link: `${legacyInfosecQaBase}/stock-price-checker`,
|
link: `${legacyInfosecQaInfosecBase}/stock-price-checker`,
|
||||||
certSlug: 'information-security-and-quality-assurance'
|
certSlug: 'information-security-and-quality-assurance'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '587d824a367417b2b2512c45',
|
id: '587d824a367417b2b2512c45',
|
||||||
title: 'Anonymous Message Board',
|
title: 'Anonymous Message Board',
|
||||||
link: `${legacyInfosecQaBase}/anonymous-message-board`,
|
link: `${legacyInfosecQaInfosecBase}/anonymous-message-board`,
|
||||||
certSlug: 'information-security-and-quality-assurance'
|
certSlug: 'information-security-and-quality-assurance'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -65,10 +65,6 @@ export function addDonation(body) {
|
|||||||
return post('/donate/add-donation', body);
|
return post('/donate/add-donation', body);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function putUpdateLegacyCert(body) {
|
|
||||||
return post('/update-my-projects', body);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function postReportUser(body) {
|
export function postReportUser(body) {
|
||||||
return post('/user/report-user', body);
|
return post('/user/report-user', body);
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,79 @@
|
|||||||
/* global cy */
|
/* global cy */
|
||||||
|
const certificationUrl = '/certification/developmentuser/responsive-web-design';
|
||||||
|
const projects = {
|
||||||
|
superBlock: 'responsive-web-design',
|
||||||
|
block: 'responsive-web-design-projects',
|
||||||
|
challenges: [
|
||||||
|
{
|
||||||
|
slug: 'build-a-tribute-page',
|
||||||
|
solution: 'https://codepen.io/moT01/pen/ZpJpKp'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'build-a-survey-form',
|
||||||
|
solution: 'https://codepen.io/moT01/pen/LrrjGz?editors=1010'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'build-a-product-landing-page',
|
||||||
|
solution: 'https://codepen.io/moT01/full/qKyKYL/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'build-a-technical-documentation-page',
|
||||||
|
solution: 'https://codepen.io/moT01/full/JBvzNL/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'build-a-personal-portfolio-webpage',
|
||||||
|
solution: 'https://codepen.io/moT01/pen/vgOaoJ'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
describe('A certification,', function () {
|
describe('A certification,', function () {
|
||||||
|
before(() => {
|
||||||
|
cy.exec('npm run seed');
|
||||||
|
cy.login();
|
||||||
|
|
||||||
|
// submit projects for certificate
|
||||||
|
const { superBlock, block, challenges } = projects;
|
||||||
|
challenges.forEach(({ slug, solution }) => {
|
||||||
|
const url = `/learn/${superBlock}/${block}/${slug}`;
|
||||||
|
cy.visit(url);
|
||||||
|
cy.get('#dynamic-front-end-form')
|
||||||
|
.get('#solution')
|
||||||
|
.type(solution, { force: true, delay: 0 });
|
||||||
|
cy.contains("I've completed this challenge")
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click();
|
||||||
|
cy.contains('Submit and go to next challenge').click().wait(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.visit('/settings');
|
||||||
|
|
||||||
|
// set user settings to public to claim a cert
|
||||||
|
cy.get('label:contains(Public)>input').each(el => {
|
||||||
|
if (!/toggle-active/.test(el[0].parentElement.className)) {
|
||||||
|
cy.wrap(el).click({ force: true });
|
||||||
|
cy.wait(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// if honest policy not accepted
|
||||||
|
cy.get('.honesty-policy button').then(btn => {
|
||||||
|
if (btn[0].innerText === 'Agree') {
|
||||||
|
btn[0].click({ force: true });
|
||||||
|
cy.wait(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// claim certificate
|
||||||
|
cy.get('a[href*="developmentuser/responsive-web-design"]').click({
|
||||||
|
force: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('while viewing your own,', function () {
|
describe('while viewing your own,', function () {
|
||||||
before(() => {
|
before(() => {
|
||||||
cy.login();
|
cy.login();
|
||||||
cy.visit('/settings');
|
cy.visit(certificationUrl);
|
||||||
|
|
||||||
// set user settings to public to claim a cert
|
|
||||||
cy.get('label:contains(Public)>input').each(el => {
|
|
||||||
if (!/toggle-active/.test(el[0].parentElement.className)) {
|
|
||||||
cy.wrap(el).click({ force: true });
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// if honest policy not accepted
|
|
||||||
cy.get('.honesty-policy button').then(btn => {
|
|
||||||
if (btn[0].innerText === 'Agree') {
|
|
||||||
btn[0].click({ force: true });
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// fill in legacy front end form
|
|
||||||
cy.get('#dynamic-legacy-front-end input').each(el => {
|
|
||||||
cy.wrap(el)
|
|
||||||
.clear({ force: true })
|
|
||||||
.type('https://nhl.com', { force: true, delay: 0 });
|
|
||||||
});
|
|
||||||
|
|
||||||
// if "Save Progress" button exists
|
|
||||||
cy.get('#dynamic-legacy-front-end').then(form => {
|
|
||||||
if (form[0][10] && form[0][10].innerHTML === 'Save Progress') {
|
|
||||||
form[0][10].click({ force: true });
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// if "Claim Certification" button exists
|
|
||||||
cy.get('#dynamic-legacy-front-end').then(form => {
|
|
||||||
if (form[0][10] && form[0][10].innerHTML === 'Claim Certification') {
|
|
||||||
form[0][10].click({ force: true });
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('#button-legacy-front-end')
|
|
||||||
.contains('Show Certification')
|
|
||||||
.click({ force: true });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render a LinkedIn button', function () {
|
it('should render a LinkedIn button', function () {
|
||||||
@ -56,7 +82,7 @@ describe('A certification,', function () {
|
|||||||
.and(
|
.and(
|
||||||
'match',
|
'match',
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/https:\/\/www\.linkedin\.com\/profile\/add\?startTask=CERTIFICATION_NAME&name=Legacy Front End&organizationId=4831032&issueYear=\d\d\d\d&issueMonth=\d\d?&certUrl=https:\/\/freecodecamp\.org\/certification\/developmentuser\/legacy-front-end/
|
/https:\/\/www\.linkedin\.com\/profile\/add\?startTask=CERTIFICATION_NAME&name=Responsive Web Design&organizationId=4831032&issueYear=\d\d\d\d&issueMonth=\d\d?&certUrl=https:\/\/freecodecamp\.org\/certification\/developmentuser\/responsive-web-design/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,7 +90,7 @@ describe('A certification,', function () {
|
|||||||
cy.contains('Share this certification on Twitter').should(
|
cy.contains('Share this certification on Twitter').should(
|
||||||
'have.attr',
|
'have.attr',
|
||||||
'href',
|
'href',
|
||||||
'https://twitter.com/intent/tweet?text=I just earned the Legacy Front End certification @freeCodeCamp! Check it out here: https://freecodecamp.org/certification/developmentuser/legacy-front-end'
|
'https://twitter.com/intent/tweet?text=I just earned the Responsive Web Design certification @freeCodeCamp! Check it out here: https://freecodecamp.org/certification/developmentuser/responsive-web-design'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,10 +105,14 @@ describe('A certification,', function () {
|
|||||||
|
|
||||||
describe("while viewing someone else's,", function () {
|
describe("while viewing someone else's,", function () {
|
||||||
before(() => {
|
before(() => {
|
||||||
cy.go('back');
|
cy.visit(certificationUrl);
|
||||||
cy.get('.toggle-button-nav').click();
|
});
|
||||||
cy.get('.nav-list').contains('Sign out').click();
|
|
||||||
cy.visit('/certification/developmentuser/legacy-front-end');
|
it('should display certificate', function () {
|
||||||
|
cy.contains('has successfully completed the freeCodeCamp.org').should(
|
||||||
|
'exist'
|
||||||
|
);
|
||||||
|
cy.contains('Responsive Web Design').should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render a LinkedIn button', function () {
|
it('should not render a LinkedIn button', function () {
|
||||||
|
@ -10,9 +10,9 @@ describe('Settings certifications area', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('initially', () => {
|
describe('initially', () => {
|
||||||
it('Should render 11 "Claim Certification" buttons', () => {
|
it('Should render 15 "Claim Certification" buttons', () => {
|
||||||
cy.findAllByText('Claim Certification').should($btns => {
|
cy.findAllByText('Claim Certification').should($btns => {
|
||||||
expect($btns).to.have.length(11);
|
expect($btns).to.have.length(15);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,49 +54,6 @@ describe('Settings certifications area', () => {
|
|||||||
'It looks like you have not completed the necessary steps. Please complete the required projects to claim the Responsive Web Design Certification'
|
'It looks like you have not completed the necessary steps. Please complete the required projects to claim the Responsive Web Design Certification'
|
||||||
).should('exist');
|
).should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should show "Your projects have been updated." message after submitting projects', () => {
|
|
||||||
cy.get(
|
|
||||||
'#dynamic-information-security-and-quality-assurance input'
|
|
||||||
).each(el => {
|
|
||||||
cy.wrap(el)
|
|
||||||
.clear({ force: true })
|
|
||||||
.type('https://nhl.com', { force: true, delay: 0 });
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('#dynamic-information-security-and-quality-assurance').then(
|
|
||||||
form => {
|
|
||||||
if (form[0][5] && form[0][5].innerHTML === 'Save Progress') {
|
|
||||||
form[0][5].click({ force: true });
|
|
||||||
cy.wait(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.contains('Your projects have been updated.').should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should render 12 "Claim Certification" buttons after submitting legacy projects', () => {
|
|
||||||
cy.findAllByText('Claim Certification').should($btns => {
|
|
||||||
expect($btns).to.have.length(12);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should show "congrats" message after claiming a cert', () => {
|
|
||||||
cy.get(
|
|
||||||
'#dynamic-information-security-and-quality-assurance button'
|
|
||||||
).click();
|
|
||||||
|
|
||||||
cy.contains(
|
|
||||||
'@developmentuser, you have successfully claimed the Legacy Information Security and Quality Assurance Certification! Congratulations on behalf of the freeCodeCamp.org team!'
|
|
||||||
).should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should render a "Show Certification" button after submitting enough projects', () => {
|
|
||||||
cy.findAllByText('Show Certification').should($btns => {
|
|
||||||
expect($btns).to.have.length(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user