refactor: test output -> arrays (#39178)
This commit is contained in:
committed by
GitHub
parent
bb019b2b0f
commit
7269894a86
@ -74,7 +74,7 @@ const propTypes = {
|
|||||||
}),
|
}),
|
||||||
initConsole: PropTypes.func.isRequired,
|
initConsole: PropTypes.func.isRequired,
|
||||||
initTests: PropTypes.func.isRequired,
|
initTests: PropTypes.func.isRequired,
|
||||||
output: PropTypes.string,
|
output: PropTypes.arrayOf(PropTypes.string),
|
||||||
pageContext: PropTypes.shape({
|
pageContext: PropTypes.shape({
|
||||||
challengeMeta: PropTypes.shape({
|
challengeMeta: PropTypes.shape({
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
|
@ -3,18 +3,23 @@ import PropTypes from 'prop-types';
|
|||||||
import sanitizeHtml from 'sanitize-html';
|
import sanitizeHtml from 'sanitize-html';
|
||||||
|
|
||||||
import './output.css';
|
import './output.css';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
defaultOutput: PropTypes.string,
|
defaultOutput: PropTypes.string,
|
||||||
output: PropTypes.string
|
output: PropTypes.arrayOf(PropTypes.string)
|
||||||
};
|
};
|
||||||
|
|
||||||
class Output extends Component {
|
class Output extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { output, defaultOutput } = this.props;
|
const { output, defaultOutput } = this.props;
|
||||||
const message = sanitizeHtml(output ? output : defaultOutput, {
|
console.log('output', output);
|
||||||
allowedTags: ['b', 'i', 'em', 'strong', 'code', 'wbr']
|
const message = sanitizeHtml(
|
||||||
});
|
!isEmpty(output) ? output.join('\n') : defaultOutput,
|
||||||
|
{
|
||||||
|
allowedTags: ['b', 'i', 'em', 'strong', 'code', 'wbr']
|
||||||
|
}
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<pre
|
<pre
|
||||||
className='output-text'
|
className='output-text'
|
||||||
|
@ -46,7 +46,7 @@ const propTypes = {
|
|||||||
initConsole: PropTypes.func.isRequired,
|
initConsole: PropTypes.func.isRequired,
|
||||||
initTests: PropTypes.func.isRequired,
|
initTests: PropTypes.func.isRequired,
|
||||||
isSignedIn: PropTypes.bool,
|
isSignedIn: PropTypes.bool,
|
||||||
output: PropTypes.string,
|
output: PropTypes.arrayOf(PropTypes.string),
|
||||||
pageContext: PropTypes.shape({
|
pageContext: PropTypes.shape({
|
||||||
challengeMeta: PropTypes.object
|
challengeMeta: PropTypes.object
|
||||||
}),
|
}),
|
||||||
@ -128,7 +128,7 @@ export class BackEnd extends Component {
|
|||||||
},
|
},
|
||||||
pageContext: { challengeMeta }
|
pageContext: { challengeMeta }
|
||||||
} = this.props;
|
} = this.props;
|
||||||
initConsole('');
|
initConsole();
|
||||||
initTests(tests);
|
initTests(tests);
|
||||||
updateChallengeMeta({ ...challengeMeta, title, challengeType });
|
updateChallengeMeta({ ...challengeMeta, title, challengeType });
|
||||||
challengeMounted(challengeMeta.id);
|
challengeMounted(challengeMeta.id);
|
||||||
|
@ -13,6 +13,7 @@ import { createExecuteChallengeSaga } from './execute-challenge-saga';
|
|||||||
import { createCurrentChallengeSaga } from './current-challenge-saga';
|
import { createCurrentChallengeSaga } from './current-challenge-saga';
|
||||||
import { challengeTypes } from '../../../../utils/challengeTypes';
|
import { challengeTypes } from '../../../../utils/challengeTypes';
|
||||||
import { completedChallengesSelector } from '../../../redux';
|
import { completedChallengesSelector } from '../../../redux';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
|
||||||
export const ns = 'challenge';
|
export const ns = 'challenge';
|
||||||
export const backendNS = 'backendChallenge';
|
export const backendNS = 'backendChallenge';
|
||||||
@ -30,11 +31,12 @@ const initialState = {
|
|||||||
challengeType: -1
|
challengeType: -1
|
||||||
},
|
},
|
||||||
challengeTests: [],
|
challengeTests: [],
|
||||||
consoleOut: '',
|
consoleOut: [],
|
||||||
hasCompletedBlock: false,
|
hasCompletedBlock: false,
|
||||||
inAccessibilityMode: false,
|
inAccessibilityMode: false,
|
||||||
isCodeLocked: false,
|
isCodeLocked: false,
|
||||||
isBuildEnabled: true,
|
isBuildEnabled: true,
|
||||||
|
logsOut: [],
|
||||||
modal: {
|
modal: {
|
||||||
completion: false,
|
completion: false,
|
||||||
help: false,
|
help: false,
|
||||||
@ -241,8 +243,6 @@ export const canFocusEditorSelector = state => state[ns].canFocusEditor;
|
|||||||
export const inAccessibilityModeSelector = state =>
|
export const inAccessibilityModeSelector = state =>
|
||||||
state[ns].inAccessibilityMode;
|
state[ns].inAccessibilityMode;
|
||||||
|
|
||||||
const MAX_LOGS_SIZE = 64 * 1024;
|
|
||||||
|
|
||||||
export const reducer = handleActions(
|
export const reducer = handleActions(
|
||||||
{
|
{
|
||||||
[types.createFiles]: (state, { payload }) => ({
|
[types.createFiles]: (state, { payload }) => ({
|
||||||
@ -275,25 +275,25 @@ export const reducer = handleActions(
|
|||||||
|
|
||||||
[types.initConsole]: (state, { payload }) => ({
|
[types.initConsole]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
consoleOut: payload
|
consoleOut: payload ? [payload] : []
|
||||||
}),
|
}),
|
||||||
[types.updateConsole]: (state, { payload }) => ({
|
[types.updateConsole]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
consoleOut: state.consoleOut + '\n' + payload
|
consoleOut: state.consoleOut.concat(payload)
|
||||||
}),
|
}),
|
||||||
[types.initLogs]: state => ({
|
[types.initLogs]: state => ({
|
||||||
...state,
|
...state,
|
||||||
logsOut: ''
|
logsOut: []
|
||||||
}),
|
}),
|
||||||
[types.updateLogs]: (state, { payload }) => ({
|
[types.updateLogs]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
logsOut: (state.logsOut + '\n' + payload).slice(-MAX_LOGS_SIZE)
|
logsOut: state.logsOut.concat(payload)
|
||||||
}),
|
}),
|
||||||
[types.logsToConsole]: (state, { payload }) => ({
|
[types.logsToConsole]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
consoleOut:
|
consoleOut: isEmpty(state.logsOut)
|
||||||
state.consoleOut +
|
? state.consoleOut
|
||||||
(state.logsOut ? '\n' + payload + '\n' + state.logsOut : '')
|
: state.consoleOut.concat(payload, state.logsOut)
|
||||||
}),
|
}),
|
||||||
[types.updateChallengeMeta]: (state, { payload }) => ({
|
[types.updateChallengeMeta]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
@ -321,7 +321,7 @@ export const reducer = handleActions(
|
|||||||
text,
|
text,
|
||||||
testString
|
testString
|
||||||
})),
|
})),
|
||||||
consoleOut: ''
|
consoleOut: []
|
||||||
}),
|
}),
|
||||||
[types.updateSolutionFormValues]: (state, { payload }) => ({
|
[types.updateSolutionFormValues]: (state, { payload }) => ({
|
||||||
...state,
|
...state,
|
||||||
|
61
cypress/integration/learn/challenges/output.js
Normal file
61
cypress/integration/learn/challenges/output.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* global cy */
|
||||||
|
|
||||||
|
const selectors = {
|
||||||
|
defaultOutput: '.output-text',
|
||||||
|
hotkeys: '.default-layout > div',
|
||||||
|
runTestsButton: 'button:contains("Run the Tests")'
|
||||||
|
};
|
||||||
|
|
||||||
|
const locations = {
|
||||||
|
index:
|
||||||
|
'/learn/responsive-web-design/basic-html-and-html5/' +
|
||||||
|
'say-hello-to-html-elements'
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultOutput = `
|
||||||
|
/**
|
||||||
|
* Your test output will go here.
|
||||||
|
*/`;
|
||||||
|
|
||||||
|
const runningOutput = '// running tests';
|
||||||
|
const finishedOutput = '// tests completed';
|
||||||
|
|
||||||
|
describe('Classic challenge', function() {
|
||||||
|
it('renders', () => {
|
||||||
|
cy.visit(locations.index);
|
||||||
|
|
||||||
|
cy.title().should(
|
||||||
|
'eq',
|
||||||
|
'Learn Basic HTML and HTML5: Say Hello to HTML Elements |' +
|
||||||
|
' freeCodeCamp.org'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the default output text', () => {
|
||||||
|
cy.visit(locations.index);
|
||||||
|
cy.get(selectors.defaultOutput).contains(defaultOutput);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows test output when the tests are run', () => {
|
||||||
|
cy.visit(locations.index);
|
||||||
|
cy.get(selectors.runTestsButton)
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get(selectors.defaultOutput)
|
||||||
|
.contains(runningOutput)
|
||||||
|
.contains(finishedOutput);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows test output when the tests are triggered by the keyboard', () => {
|
||||||
|
cy.visit(locations.index);
|
||||||
|
cy.get(selectors.hotkeys)
|
||||||
|
.focus()
|
||||||
|
.type('{ctrl}{enter}')
|
||||||
|
.then(() => {
|
||||||
|
cy.get(selectors.defaultOutput)
|
||||||
|
.contains(runningOutput)
|
||||||
|
.contains(finishedOutput);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user