feat(client): show and execute backend project tests (#35673)
This commit is contained in:
parent
1abe4971f4
commit
839e81426e
@ -12,6 +12,7 @@ import {
|
|||||||
consoleOutputSelector,
|
consoleOutputSelector,
|
||||||
initTests,
|
initTests,
|
||||||
updateChallengeMeta,
|
updateChallengeMeta,
|
||||||
|
updateProjectFormValues,
|
||||||
backendNS
|
backendNS
|
||||||
} from '../redux';
|
} from '../redux';
|
||||||
import { createGuideUrl } from '../utils';
|
import { createGuideUrl } from '../utils';
|
||||||
@ -24,6 +25,7 @@ import Output from '../components/Output';
|
|||||||
import CompletionModal from '../components/CompletionModal';
|
import CompletionModal from '../components/CompletionModal';
|
||||||
import HelpModal from '../components/HelpModal';
|
import HelpModal from '../components/HelpModal';
|
||||||
import ProjectToolPanel from '../project/Tool-Panel';
|
import ProjectToolPanel from '../project/Tool-Panel';
|
||||||
|
import ProjectForm from '../project/ProjectForm';
|
||||||
import {
|
import {
|
||||||
createFormValidator,
|
createFormValidator,
|
||||||
isValidURL,
|
isValidURL,
|
||||||
@ -32,6 +34,8 @@ import {
|
|||||||
} from '../../../components/formHelpers';
|
} from '../../../components/formHelpers';
|
||||||
import Spacer from '../../../components/helpers/Spacer';
|
import Spacer from '../../../components/helpers/Spacer';
|
||||||
|
|
||||||
|
import { backend } from '../../../../utils/challengeTypes';
|
||||||
|
|
||||||
import '../components/test-frame.css';
|
import '../components/test-frame.css';
|
||||||
|
|
||||||
// provided by redux form
|
// provided by redux form
|
||||||
@ -52,6 +56,7 @@ const propTypes = {
|
|||||||
tests: PropTypes.array,
|
tests: PropTypes.array,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
updateChallengeMeta: PropTypes.func.isRequired,
|
updateChallengeMeta: PropTypes.func.isRequired,
|
||||||
|
updateProjectFormValues: PropTypes.func.isRequired,
|
||||||
...reduxFormPropTypes
|
...reduxFormPropTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,7 +79,8 @@ const mapDispatchToActions = {
|
|||||||
challengeMounted,
|
challengeMounted,
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
initTests,
|
initTests,
|
||||||
updateChallengeMeta
|
updateChallengeMeta,
|
||||||
|
updateProjectFormValues
|
||||||
};
|
};
|
||||||
|
|
||||||
const formFields = ['solution'];
|
const formFields = ['solution'];
|
||||||
@ -150,6 +156,7 @@ export class BackEnd extends Component {
|
|||||||
data: {
|
data: {
|
||||||
challengeNode: {
|
challengeNode: {
|
||||||
fields: { blockName, slug },
|
fields: { blockName, slug },
|
||||||
|
challengeType,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
instructions
|
instructions
|
||||||
@ -158,7 +165,8 @@ export class BackEnd extends Component {
|
|||||||
output,
|
output,
|
||||||
tests,
|
tests,
|
||||||
submitting,
|
submitting,
|
||||||
executeChallenge
|
executeChallenge,
|
||||||
|
updateProjectFormValues
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// TODO: Should be tied to user.isSignedIn
|
// TODO: Should be tied to user.isSignedIn
|
||||||
@ -177,13 +185,21 @@ export class BackEnd extends Component {
|
|||||||
description={description}
|
description={description}
|
||||||
instructions={instructions}
|
instructions={instructions}
|
||||||
/>
|
/>
|
||||||
<Form
|
{challengeType === backend ? (
|
||||||
buttonText={`${buttonCopy} (Ctrl + Enter)`}
|
<Form
|
||||||
formFields={formFields}
|
buttonText={`${buttonCopy}`}
|
||||||
id={backendNS}
|
formFields={formFields}
|
||||||
options={options}
|
id={backendNS}
|
||||||
submit={executeChallenge}
|
options={options}
|
||||||
/>
|
submit={executeChallenge}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ProjectForm
|
||||||
|
isFrontEnd={false}
|
||||||
|
onSubmit={executeChallenge}
|
||||||
|
updateProjectForm={updateProjectFormValues}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<ProjectToolPanel guideUrl={createGuideUrl(slug)} />
|
<ProjectToolPanel guideUrl={createGuideUrl(slug)} />
|
||||||
<br />
|
<br />
|
||||||
<Output
|
<Output
|
||||||
|
@ -1,32 +1,18 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import {
|
import { Form } from '../../../components/formHelpers';
|
||||||
Form
|
|
||||||
// isValidURL,
|
|
||||||
// makeRequired,
|
|
||||||
// createFormValidator
|
|
||||||
} from '../../../components/formHelpers';
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
isFrontEnd: PropTypes.bool,
|
isFrontEnd: PropTypes.bool,
|
||||||
isSubmitting: PropTypes.bool,
|
isSubmitting: PropTypes.bool,
|
||||||
openModal: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
updateProjectForm: PropTypes.func.isRequired
|
updateProjectForm: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const frontEndFields = ['solution'];
|
const frontEndFields = ['solution'];
|
||||||
const backEndFields = ['solution', 'githubLink'];
|
const backEndFields = ['solution', 'githubLink'];
|
||||||
|
|
||||||
// const fieldValidators = {
|
|
||||||
// solution: makeRequired(isValidURL)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const backEndFieldValidators = {
|
|
||||||
// ...fieldValidators,
|
|
||||||
// githubLink: makeRequired(isValidURL)
|
|
||||||
// };
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
types: {
|
types: {
|
||||||
solution: 'url',
|
solution: 'url',
|
||||||
@ -38,64 +24,20 @@ const options = {
|
|||||||
export class ProjectForm extends Component {
|
export class ProjectForm extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
keysDown: {
|
|
||||||
Control: false,
|
|
||||||
Enter: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
||||||
this.handleKeyUp = this.handleKeyUp.bind(this);
|
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.updateProjectForm({});
|
this.props.updateProjectForm({});
|
||||||
window.addEventListener('keydown', this.handleKeyDown);
|
|
||||||
window.addEventListener('keyup', this.handleKeyUp);
|
|
||||||
}
|
}
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
this.props.updateProjectForm({});
|
this.props.updateProjectForm({});
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener('keydown', this.handleKeyDown);
|
this.props.updateProjectForm({});
|
||||||
window.removeEventListener('keyup', this.handleKeyUp);
|
|
||||||
}
|
|
||||||
handleKeyDown(e) {
|
|
||||||
if (e.key === 'Control') {
|
|
||||||
this.setState(state => ({
|
|
||||||
...state,
|
|
||||||
keysDown: { ...state.keysDown, Control: true }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
this.setState(state => ({
|
|
||||||
...state,
|
|
||||||
keysDown: { ...state.keysDown, Enter: true }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleKeyUp(e) {
|
|
||||||
if (e.key === 'Control') {
|
|
||||||
this.setState(state => ({
|
|
||||||
...state,
|
|
||||||
keysDown: { ...state.keysDown, Control: false }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
this.setState(state => ({
|
|
||||||
...state,
|
|
||||||
keysDown: { ...state.keysDown, Enter: false }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
handleSubmit(values) {
|
handleSubmit(values) {
|
||||||
const {
|
this.props.updateProjectForm(values);
|
||||||
keysDown: { Control, Enter }
|
this.props.onSubmit();
|
||||||
} = this.state;
|
|
||||||
if ((Control && Enter) || !Enter) {
|
|
||||||
this.props.openModal('completion');
|
|
||||||
this.props.updateProjectForm(values);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { isSubmitting, isFrontEnd } = this.props;
|
const { isSubmitting, isFrontEnd } = this.props;
|
||||||
@ -104,14 +46,11 @@ export class ProjectForm extends Component {
|
|||||||
: "I've completed this challenge";
|
: "I've completed this challenge";
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
buttonText={`${buttonCopy} (Ctrl + Enter)`}
|
buttonText={`${buttonCopy}`}
|
||||||
formFields={isFrontEnd ? frontEndFields : backEndFields}
|
formFields={isFrontEnd ? frontEndFields : backEndFields}
|
||||||
id={isFrontEnd ? 'front-end-form' : 'back-end-form'}
|
id={isFrontEnd ? 'front-end-form' : 'back-end-form'}
|
||||||
options={options}
|
options={options}
|
||||||
submit={this.handleSubmit}
|
submit={this.handleSubmit}
|
||||||
// validate={createFormValidator(
|
|
||||||
// isFrontEnd ? fieldValidators : backEndFieldValidators
|
|
||||||
// )}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ export class Project extends Component {
|
|||||||
/>
|
/>
|
||||||
<ProjectForm
|
<ProjectForm
|
||||||
isFrontEnd={isFrontEnd}
|
isFrontEnd={isFrontEnd}
|
||||||
openModal={openCompletionModal}
|
onSubmit={openCompletionModal}
|
||||||
updateProjectForm={updateProjectFormValues}
|
updateProjectForm={updateProjectFormValues}
|
||||||
/>
|
/>
|
||||||
<ToolPanel guideUrl={createGuideUrl(slug)} />
|
<ToolPanel guideUrl={createGuideUrl(slug)} />
|
||||||
|
@ -192,10 +192,15 @@ export const challengeDataSelector = state => {
|
|||||||
...challengeData,
|
...challengeData,
|
||||||
url
|
url
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (challengeType === challengeTypes.backEndProject) {
|
||||||
challengeType === challengeTypes.frontEndProject ||
|
const values = projectFormValuesSelector(state);
|
||||||
challengeType === challengeTypes.backendEndProject
|
const { solution: url } = values;
|
||||||
) {
|
challengeData = {
|
||||||
|
...challengeData,
|
||||||
|
...values,
|
||||||
|
url
|
||||||
|
};
|
||||||
|
} else if (challengeType === challengeTypes.frontEndProject) {
|
||||||
challengeData = {
|
challengeData = {
|
||||||
...challengeData,
|
...challengeData,
|
||||||
...projectFormValuesSelector(state)
|
...projectFormValuesSelector(state)
|
||||||
|
@ -61,7 +61,8 @@ const buildFunctions = {
|
|||||||
[challengeTypes.bonfire]: buildJSChallenge,
|
[challengeTypes.bonfire]: buildJSChallenge,
|
||||||
[challengeTypes.html]: buildDOMChallenge,
|
[challengeTypes.html]: buildDOMChallenge,
|
||||||
[challengeTypes.modern]: buildDOMChallenge,
|
[challengeTypes.modern]: buildDOMChallenge,
|
||||||
[challengeTypes.backend]: buildBackendChallenge
|
[challengeTypes.backend]: buildBackendChallenge,
|
||||||
|
[challengeTypes.backEndProject]: buildBackendChallenge
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function buildChallenge(challengeData) {
|
export async function buildChallenge(challengeData) {
|
||||||
|
@ -40,7 +40,7 @@ exports.viewTypes = {
|
|||||||
[js]: 'classic',
|
[js]: 'classic',
|
||||||
[bonfire]: 'classic',
|
[bonfire]: 'classic',
|
||||||
[frontEndProject]: 'project',
|
[frontEndProject]: 'project',
|
||||||
[backEndProject]: 'project',
|
[backEndProject]: 'backend',
|
||||||
[modern]: 'modern',
|
[modern]: 'modern',
|
||||||
[step]: 'step',
|
[step]: 'step',
|
||||||
[quiz]: 'quiz',
|
[quiz]: 'quiz',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user