Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: no validation for combined length of org, number, run #1262

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/data/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ export const VisibilityTypes = /** @type {const} */ ({
UNSCHEDULED: 'unscheduled',
NEEDS_ATTENTION: 'needs_attention',
});

export const TOTAL_LENGTH_KEY = 'total-length';

export const MAX_TOTAL_LENGTH = 65;
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import TypeaheadDropdown from '../../editors/sharedComponents/TypeaheadDropdown'

import AlertMessage from '../alert-message';
import { STATEFUL_BUTTON_STATES } from '../../constants';
import { RequestStatus } from '../../data/constants';
import { RequestStatus, TOTAL_LENGTH_KEY } from '../../data/constants';
import { getSavingStatus } from '../data/selectors';
import { getStudioHomeData } from '../../studio-home/data/selectors';
import { updatePostErrors } from '../data/slice';
Expand Down Expand Up @@ -132,6 +132,8 @@ const CreateOrRerunCourseForm = ({
},
];

const errorMessage = errors[TOTAL_LENGTH_KEY] || postErrors?.errMsg;

const createButtonState = {
labels: {
default: intl.formatMessage(isCreateNewCourse ? messages.createButton : messages.rerunCreateButton),
Expand Down Expand Up @@ -202,11 +204,11 @@ const CreateOrRerunCourseForm = ({
return (
<div className="create-or-rerun-course-form">
<TransitionReplace>
{showErrorBanner ? (
{(errors[TOTAL_LENGTH_KEY] || showErrorBanner) ? (
<AlertMessage
variant="danger"
icon={InfoIcon}
title={postErrors.errMsg}
title={errorMessage}
aria-hidden="true"
aria-labelledby={intl.formatMessage(
messages.alertErrorExistsAriaLabelledBy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,28 @@ describe('<CreateOrRerunCourseForm />', () => {
expect(rerunBtn).toBeDisabled();
});

it('shows error message when total length exceeds 65 characters', async () => {
const updatedProps = {
...props,
initialValues: {
displayName: 'Long Title Course',
org: 'long-org',
number: 'number',
run: '2024',
},
};

render(<RootWrapper {...updatedProps} />);
await mockStore();
const numberInput = screen.getByPlaceholderText(messages.courseNumberPlaceholder.defaultMessage);

fireEvent.change(numberInput, { target: { value: 'long-name-which-is-longer-than-65-characters-to-check-for-errors' } });

waitFor(() => {
expect(screen.getByText(messages.totalLengthError)).toBeInTheDocument();
});
});

it('should be disabled create button if form has error', async () => {
render(<RootWrapper {...props} />);
await mockStore();
Expand Down
8 changes: 7 additions & 1 deletion src/generic/create-or-rerun-course/hooks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as Yup from 'yup';
import { useNavigate } from 'react-router-dom';

import { REGEX_RULES } from '../../constants';
import { RequestStatus } from '../../data/constants';
import { RequestStatus, MAX_TOTAL_LENGTH, TOTAL_LENGTH_KEY } from '../../data/constants';
import { getStudioHomeData } from '../../studio-home/data/selectors';
import {
getRedirectUrlObj,
Expand Down Expand Up @@ -60,6 +60,12 @@ const useCreateOrRerunCourse = (initialValues) => {
intl.formatMessage(messages.disallowedCharsError),
)
.matches(noSpaceRule, intl.formatMessage(messages.noSpaceError)),
}).test(TOTAL_LENGTH_KEY, intl.formatMessage(messages.totalLengthError), function validateTotalLength() {
const { org, number, run } = this?.options.originalValue || {};
if ((org?.length || 0) + (number?.length || 0) + (run?.length || 0) > MAX_TOTAL_LENGTH) {
return this.createError({ path: TOTAL_LENGTH_KEY, message: intl.formatMessage(messages.totalLengthError) });
}
return true;
});

const {
Expand Down
5 changes: 5 additions & 0 deletions src/generic/create-or-rerun-course/messages.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
import { MAX_TOTAL_LENGTH } from '../../data/constants';

const messages = defineMessages({
courseDisplayNameLabel: {
Expand Down Expand Up @@ -117,6 +118,10 @@ const messages = defineMessages({
id: 'course-authoring.create-or-rerun-course.no-space.error',
defaultMessage: 'Please do not use any spaces in this field.',
},
totalLengthError: {
id: 'course-authoring.create-or-rerun-course.total-length-error.error',
defaultMessage: `The combined length of the organization, course number and course run fields cannot be more than ${MAX_TOTAL_LENGTH} characters.`,
},
alertErrorExistsAriaLabelledBy: {
id: 'course-authoring.create-or-rerun-course.error.already-exists.labelledBy',
defaultMessage: 'alert-already-exists-title',
Expand Down