diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json index 62bb2094ae8..5ef409952fe 100644 --- a/client/i18n/locales/english/translations.json +++ b/client/i18n/locales/english/translations.json @@ -376,6 +376,7 @@ "tests-completed": "// tests completed", "console-output": "// console output", "syntax-error": "Your code raised an error before any tests could run. Please fix it and try again.", + "indentation-error": "Your code has an indentation error. You may need to add 'pass' on a new line to form a valid block of code.", "sign-in-save": "Sign in to save your progress", "download-solution": "Download my solution", "download-results": "Download my results", diff --git a/client/src/templates/Challenges/redux/execute-challenge-saga.js b/client/src/templates/Challenges/redux/execute-challenge-saga.js index 6fabd023b5d..67f08f455be 100644 --- a/client/src/templates/Challenges/redux/execute-challenge-saga.js +++ b/client/src/templates/Challenges/redux/execute-challenge-saga.js @@ -209,7 +209,7 @@ function* executeTests(testRunner, tests, testTimeout = 5000) { throw err; } } catch (err) { - const { actual, expected, syntaxError } = err; + const { actual, expected, errorType } = err; newTest.message = text .replace('--fcc-expected--', expected) @@ -217,14 +217,18 @@ function* executeTests(testRunner, tests, testTimeout = 5000) { if (err === 'timeout') { newTest.err = 'Test timed out'; newTest.message = `${newTest.message} (${newTest.err})`; - } else if (syntaxError) { - newTest.err = 'syntax error'; - newTest.message = `

${i18next.t('learn.syntax-error')}

`; + } else if (errorType) { + const msgKey = + errorType === 'indentation' + ? 'learn.indentation-error' + : 'learn.syntax-error'; + newTest.message = `

${i18next.t(msgKey)}

`; } else { const { message, stack } = err; newTest.err = message + '\n' + stack; newTest.stack = stack; } + console.log('newTest', newTest); yield put(updateConsole(newTest.message)); } finally { testResults.push(newTest); diff --git a/tools/client-plugins/browser-scripts/python-test-evaluator.ts b/tools/client-plugins/browser-scripts/python-test-evaluator.ts index 7191c8420fc..6fa5b554d85 100644 --- a/tools/client-plugins/browser-scripts/python-test-evaluator.ts +++ b/tools/client-plugins/browser-scripts/python-test-evaluator.ts @@ -1,7 +1,7 @@ // We have to specify pyodide.js because we need to import that file (not .mjs) // and 'import' defaults to .mjs import { loadPyodide, type PyodideInterface } from 'pyodide/pyodide.js'; -import type { PyProxy } from 'pyodide/ffi'; +import type { PyProxy, PythonError } from 'pyodide/ffi'; import pkg from 'pyodide/package.json'; import * as helpers from '@freecodecamp/curriculum-helpers'; import chai from 'chai'; @@ -135,17 +135,22 @@ input = __inputGen(${JSON.stringify(input ?? [])}) // available to the test. try { runPython(code); - } catch (err) { - // We don't, yet, want user code to raise exceptions. When they do, we - // count this as a failing test. - ctx.postMessage({ + } catch (e) { + const err = e as PythonError; + + // Quite a lot of lessons can easily lead users to write code that has + // indentation errors. In these cases we want to provide a more helpful + // error message. For other errors, we can just provide the standard + // message. + const errorType = + err.type === 'IndentationError' ? 'indentation' : 'other'; + return ctx.postMessage({ err: { - message: (err as Error).message, - stack: (err as Error).stack, - syntaxError: true + message: err.message, + stack: err.stack, + errorType } }); - return; } // TODO: remove the next line, creating __locals, once all the tests access // variables directly.