mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-03-16 19:01:02 -04:00
feature(UI): Help modal form (#53824)
Co-authored-by: Bruce Blaser <bbsmooth@gmail.com> Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
@@ -383,8 +383,14 @@
|
||||
"percent-complete": "{{percent}}% complete",
|
||||
"project-complete": "Completed {{completedChallengesInBlock}} of {{totalChallengesInBlock}} certification projects",
|
||||
"tried-rsa": "If you've already tried the <0>Read-Search-Ask</0> method, then you can ask for help on the freeCodeCamp forum.",
|
||||
"read-search-ask-checkbox": "I have tried the <0>Read-Search-Ask</0> method",
|
||||
"similar-questions-checkbox": "I have searched for <0>similar questions that have already been answered on the forum</0>",
|
||||
"minimum-characters": "Add a minimum of {{characters}} characters",
|
||||
"characters-left": "{{characters}} characters left",
|
||||
"must-confirm-statements": "You must confirm the following statements before you can submit your post to the forum.",
|
||||
"min-50-max-500": "50 character minimum, 500 character maximum",
|
||||
"rsa": "Read, search, ask",
|
||||
"rsa-forum": "<strong>Before making a new post</strong> please see if your question has <0>already been answered on the forum</0>.",
|
||||
"rsa-forum": "<strong>Before making a new post</strong> please <0>check if your question has already been answered on the forum</0>.",
|
||||
"reset": "Reset this lesson?",
|
||||
"reset-warn": "Are you sure you wish to reset this lesson? The editors and tests will be reset.",
|
||||
"reset-warn-2": "This cannot be undone",
|
||||
|
||||
@@ -13,6 +13,22 @@
|
||||
word-spacing: -0.4ch;
|
||||
}
|
||||
|
||||
.help-form-legend {
|
||||
color: var(--secondary-color);
|
||||
border: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.checkbox-text {
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.help-modal .btn-lg {
|
||||
font-size: 16px;
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Modal } from '@freecodecamp/react-bootstrap';
|
||||
import React from 'react';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import { Button, FormControl } from '@freecodecamp/ui';
|
||||
import React, { useMemo, useState, useRef, useEffect } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
import { Button } from '@freecodecamp/ui';
|
||||
import { Dispatch, bindActionCreators } from 'redux';
|
||||
|
||||
import envData from '../../../../config/env.json';
|
||||
import { Spacer } from '../../../components/helpers';
|
||||
import { createQuestion, closeModal } from '../redux/actions';
|
||||
import { isHelpModalOpenSelector } from '../redux/selectors';
|
||||
import { Spacer } from '../../../components/helpers';
|
||||
|
||||
import './help-modal.css';
|
||||
import callGA from '../../../analytics/call-ga';
|
||||
|
||||
interface HelpModalProps {
|
||||
closeHelpModal: () => void;
|
||||
createQuestion: () => void;
|
||||
createQuestion: (description: string) => void;
|
||||
isOpen?: boolean;
|
||||
t: (text: string) => string;
|
||||
challengeTitle: string;
|
||||
challengeBlock: string;
|
||||
}
|
||||
|
||||
const { forumLocation } = envData;
|
||||
const DESCRIPTION_MIN_CHARS = 50;
|
||||
const DESCRIPTION_MAX_CHARS = 500;
|
||||
const RSA = forumLocation + '/t/19514';
|
||||
|
||||
const mapStateToProps = (state: unknown) => ({
|
||||
isOpen: isHelpModalOpenSelector(state) as boolean
|
||||
@@ -35,8 +37,6 @@ const mapDispatchToProps = (dispatch: Dispatch) =>
|
||||
dispatch
|
||||
);
|
||||
|
||||
const RSA = forumLocation + '/t/19514';
|
||||
|
||||
const generateSearchLink = (title: string, block: string) => {
|
||||
const query = /^step\s*\d*$/i.test(title)
|
||||
? encodeURIComponent(`${block} - ${title}`)
|
||||
@@ -45,69 +45,245 @@ const generateSearchLink = (title: string, block: string) => {
|
||||
return search;
|
||||
};
|
||||
|
||||
interface CheckboxProps {
|
||||
name: string;
|
||||
i18nkey: string;
|
||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
value: boolean;
|
||||
href: string;
|
||||
}
|
||||
|
||||
function Checkbox({ name, i18nkey, onChange, value, href }: CheckboxProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
name={name}
|
||||
type='checkbox'
|
||||
onChange={onChange}
|
||||
checked={value}
|
||||
required
|
||||
/>
|
||||
<span className='checkbox-text'>
|
||||
<Trans i18nKey={i18nkey}>
|
||||
<a href={href} rel='noopener noreferrer' target='_blank'>
|
||||
placeholder
|
||||
<span className='sr-only'>{t('aria.opens-new-window')}</span>
|
||||
</a>
|
||||
</Trans>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HelpModal({
|
||||
closeHelpModal,
|
||||
createQuestion,
|
||||
isOpen,
|
||||
t,
|
||||
challengeBlock,
|
||||
challengeTitle
|
||||
}: HelpModalProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const [showHelpForm, setShowHelpForm] = useState(false);
|
||||
const [description, setDescription] = useState('');
|
||||
const [readSearchCheckbox, setReadSearchCheckbox] = useState(false);
|
||||
const [similarQuestionsCheckbox, setSimilarQuestionsCheckbox] =
|
||||
useState(false);
|
||||
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (showHelpForm) {
|
||||
formRef.current?.querySelector('input')?.focus();
|
||||
}
|
||||
}, [showHelpForm]);
|
||||
|
||||
const canSubmitForm = useMemo(() => {
|
||||
return (
|
||||
description.length >= DESCRIPTION_MIN_CHARS &&
|
||||
readSearchCheckbox &&
|
||||
similarQuestionsCheckbox
|
||||
);
|
||||
}, [description, readSearchCheckbox, similarQuestionsCheckbox]);
|
||||
|
||||
const resetFormValues = () => {
|
||||
setDescription('');
|
||||
setReadSearchCheckbox(false);
|
||||
setSimilarQuestionsCheckbox(false);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
closeHelpModal();
|
||||
setShowHelpForm(false);
|
||||
resetFormValues();
|
||||
};
|
||||
|
||||
const handleSubmit = (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!canSubmitForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
setShowHelpForm(false);
|
||||
resetFormValues();
|
||||
createQuestion(description);
|
||||
closeHelpModal();
|
||||
};
|
||||
|
||||
if (isOpen) {
|
||||
callGA({ event: 'pageview', pagePath: '/help-modal' });
|
||||
}
|
||||
return (
|
||||
<Modal dialogClassName='help-modal' onHide={closeHelpModal} show={isOpen}>
|
||||
<Modal.Header className='help-modal-header fcc-modal' closeButton={true}>
|
||||
<Modal.Title className='text-center'>
|
||||
<Modal
|
||||
dialogClassName='help-modal'
|
||||
onHide={handleClose}
|
||||
show={isOpen}
|
||||
aria-labelledby='ask-for-help-modal'
|
||||
>
|
||||
<Modal.Header
|
||||
className='help-modal-header fcc-modal'
|
||||
closeButton={true}
|
||||
closeLabel={t('buttons.close')}
|
||||
>
|
||||
<Modal.Title id='ask-for-help-modal' className='text-center'>
|
||||
{t('buttons.ask-for-help')}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className='help-modal-body text-center'>
|
||||
<h3 className='help-modal-heading'>
|
||||
<Trans i18nKey='learn.tried-rsa'>
|
||||
<a
|
||||
href={RSA}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
title={t('learn.rsa')}
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</h3>
|
||||
<div className='alert alert-danger'>
|
||||
<FontAwesomeIcon icon={faExclamationCircle} />
|
||||
<p>
|
||||
<Trans i18nKey='learn.rsa-forum'>
|
||||
<a
|
||||
<Modal.Body className='text-center'>
|
||||
{showHelpForm ? (
|
||||
<form onSubmit={handleSubmit} ref={formRef}>
|
||||
<fieldset>
|
||||
<legend className='help-form-legend'>
|
||||
{t('learn.must-confirm-statements')}
|
||||
</legend>
|
||||
|
||||
<Checkbox
|
||||
name='read-search-ask-checkbox'
|
||||
i18nkey='learn.read-search-ask-checkbox'
|
||||
onChange={event => setReadSearchCheckbox(event.target.checked)}
|
||||
value={readSearchCheckbox}
|
||||
href={RSA}
|
||||
/>
|
||||
|
||||
<Spacer size='small' />
|
||||
|
||||
<Checkbox
|
||||
name='similar-questions-checkbox'
|
||||
i18nkey='learn.similar-questions-checkbox'
|
||||
onChange={event =>
|
||||
setSimilarQuestionsCheckbox(event.target.checked)
|
||||
}
|
||||
value={similarQuestionsCheckbox}
|
||||
href={generateSearchLink(challengeTitle, challengeBlock)}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
placeholder
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
onClick={createQuestion}
|
||||
>
|
||||
{t('buttons.create-post')}
|
||||
</Button>
|
||||
<Spacer size='xxSmall' />
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
onClick={closeHelpModal}
|
||||
>
|
||||
{t('buttons.cancel')}
|
||||
</Button>
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<Spacer size='xSmall' />
|
||||
|
||||
<label htmlFor='help-modal-form-description'>
|
||||
{t('forum-help.whats-happening')}
|
||||
<span className='sr-only'>{t('learn.min-50-max-500')}</span>
|
||||
</label>
|
||||
|
||||
<FormControl
|
||||
id='help-modal-form-description'
|
||||
name='description'
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setDescription(event.target.value);
|
||||
}}
|
||||
componentClass='textarea'
|
||||
rows={5}
|
||||
value={description}
|
||||
minLength={DESCRIPTION_MIN_CHARS}
|
||||
maxLength={DESCRIPTION_MAX_CHARS}
|
||||
required
|
||||
/>
|
||||
|
||||
<Spacer size='xSmall' />
|
||||
|
||||
{description.length < DESCRIPTION_MIN_CHARS ? (
|
||||
<p>
|
||||
{t('learn.minimum-characters', {
|
||||
characters: DESCRIPTION_MIN_CHARS - description.length
|
||||
})}
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
{t('learn.characters-left', {
|
||||
characters: DESCRIPTION_MAX_CHARS - description.length
|
||||
})}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<Spacer size='xxSmall' />
|
||||
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
type='submit'
|
||||
disabled={!canSubmitForm}
|
||||
>
|
||||
{t('buttons.submit')}
|
||||
</Button>
|
||||
<Spacer size='xxSmall' />
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
onClick={handleClose}
|
||||
>
|
||||
{t('buttons.cancel')}
|
||||
</Button>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<p>
|
||||
<Trans i18nKey='learn.tried-rsa'>
|
||||
<a href={RSA} rel='noopener noreferrer' target='_blank'>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</p>
|
||||
<div className='alert alert-danger'>
|
||||
<FontAwesomeIcon icon={faExclamationCircle} />
|
||||
<p>
|
||||
<Trans i18nKey='learn.rsa-forum'>
|
||||
<a
|
||||
href={generateSearchLink(challengeTitle, challengeBlock)}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
placeholder
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
onClick={() => setShowHelpForm(true)}
|
||||
>
|
||||
{t('buttons.create-post')}
|
||||
</Button>
|
||||
<Spacer size='xxSmall' />
|
||||
<Button
|
||||
block={true}
|
||||
size='large'
|
||||
variant='primary'
|
||||
onClick={closeHelpModal}
|
||||
>
|
||||
{t('buttons.cancel')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
@@ -115,7 +291,4 @@ function HelpModal({
|
||||
|
||||
HelpModal.displayName = 'HelpModal';
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(withTranslation()(HelpModal));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(HelpModal);
|
||||
|
||||
@@ -73,10 +73,46 @@ export function insertEditableRegions(challengeFiles = []) {
|
||||
return challengeFiles;
|
||||
}
|
||||
|
||||
function editableRegionsToMarkdown(challengeFiles = []) {
|
||||
const moreThanOneFile = challengeFiles?.length > 1;
|
||||
return challengeFiles.reduce((fileString, challengeFile) => {
|
||||
if (!challengeFile) {
|
||||
return fileString;
|
||||
}
|
||||
|
||||
const fileExtension = challengeFile.ext;
|
||||
const fileName = challengeFile.name;
|
||||
const fileType = fileExtension === 'js' ? 'javascript' : fileExtension;
|
||||
let fileDescription;
|
||||
|
||||
if (!moreThanOneFile) {
|
||||
fileDescription = '';
|
||||
} else if (fileExtension === 'html') {
|
||||
fileDescription = `<!-- file: ${fileName}.${fileExtension} -->\n`;
|
||||
} else {
|
||||
fileDescription = `/* file: ${fileName}.${fileExtension} */\n`;
|
||||
}
|
||||
|
||||
const [start, end] = challengeFile.editableRegionBoundaries;
|
||||
const lines = challengeFile.contents.split('\n');
|
||||
const editableRegion = lines.slice(start + 1, end + 4).join('\n');
|
||||
|
||||
return `${fileString}\`\`\`${fileType}\n${fileDescription}${editableRegion}\n\`\`\`\n\n`;
|
||||
}, '\n');
|
||||
}
|
||||
|
||||
function linksOrMarkdown(projectFormValues, markdown) {
|
||||
return (
|
||||
projectFormValues
|
||||
?.map(([key, val]) => `${key}: ${transformEditorLink(val)}\n\n`)
|
||||
?.join('') || markdown
|
||||
);
|
||||
}
|
||||
|
||||
function createQuestionEpic(action$, state$, { window }) {
|
||||
return action$.pipe(
|
||||
ofType(actionTypes.createQuestion),
|
||||
tap(() => {
|
||||
tap(({ payload: describe }) => {
|
||||
const state = state$.value;
|
||||
let challengeFiles = challengeFilesSelector(state);
|
||||
const {
|
||||
@@ -122,15 +158,21 @@ function createQuestionEpic(action$, state$, { window }) {
|
||||
: '### ' + i18next.t('forum-help.camper-code') + '\n\n';
|
||||
|
||||
const whatsHappeningHeading = i18next.t('forum-help.whats-happening');
|
||||
const describe = i18next.t('forum-help.describe');
|
||||
const projectOrCodeHeading = projectFormValues.length
|
||||
? `###${i18next.t('forum-help.camper-project')}\n\n`
|
||||
: camperCodeHeading;
|
||||
const markdownCodeOrLinks =
|
||||
projectFormValues
|
||||
?.map(([key, val]) => `${key}: ${transformEditorLink(val)}\n\n`)
|
||||
?.join('') || filesToMarkdown(challengeFiles);
|
||||
const textMessage = `### ${whatsHappeningHeading}\n${describe}\n\n${projectOrCodeHeading}${markdownCodeOrLinks}${endingText}`;
|
||||
|
||||
const fullCode = filesToMarkdown(challengeFiles);
|
||||
const fullCodeOrLinks = linksOrMarkdown(projectFormValues, fullCode);
|
||||
|
||||
const onlyEditableRegion = editableRegionsToMarkdown(challengeFiles);
|
||||
const editableRegionOrLinks = linksOrMarkdown(
|
||||
projectFormValues,
|
||||
onlyEditableRegion
|
||||
);
|
||||
|
||||
const textMessage = `### ${whatsHappeningHeading}\n${describe}\n\n${projectOrCodeHeading}${fullCodeOrLinks}${endingText}`;
|
||||
const textMessageOnlyEditableRegion = `### ${whatsHappeningHeading}\n${describe}\n\n${projectOrCodeHeading}${editableRegionOrLinks}${endingText}`;
|
||||
|
||||
const warning = i18next.t('forum-help.warning');
|
||||
const tooLongOne = i18next.t('forum-help.too-long-one');
|
||||
@@ -139,7 +181,7 @@ function createQuestionEpic(action$, state$, { window }) {
|
||||
const addCodeOne = i18next.t('forum-help.add-code-one');
|
||||
const addCodeTwo = i18next.t('forum-help.add-code-two');
|
||||
const addCodeThree = i18next.t('forum-help.add-code-three');
|
||||
const altTextMessage = `### ${whatsHappeningHeading}\n\n${camperCodeHeading}\n\n${warning}\n\n${tooLongOne}\n\n${tooLongTwo}\n\n${tooLongThree}\n\n\`\`\`text\n${addCodeOne}\n${addCodeTwo}\n${addCodeThree}\n\`\`\`\n\n${endingText}`;
|
||||
const altTextMessage = `### ${whatsHappeningHeading}\n${describe}\n\n${camperCodeHeading}\n\n${warning}\n\n${tooLongOne}\n\n${tooLongTwo}\n\n${tooLongThree}\n\n\`\`\`text\n${addCodeOne}\n${addCodeTwo}\n${addCodeThree}\n\`\`\`\n\n${endingText}`;
|
||||
|
||||
const titleText = window.encodeURIComponent(
|
||||
`${i18next.t(
|
||||
@@ -152,13 +194,25 @@ function createQuestionEpic(action$, state$, { window }) {
|
||||
);
|
||||
|
||||
const studentCode = window.encodeURIComponent(textMessage);
|
||||
const editableRegionCode = window.encodeURIComponent(
|
||||
textMessageOnlyEditableRegion
|
||||
);
|
||||
const altStudentCode = window.encodeURIComponent(altTextMessage);
|
||||
|
||||
const baseURI = `${forumLocation}/new-topic?category=${category}&title=${titleText}&body=`;
|
||||
const defaultURI = `${baseURI}${studentCode}`;
|
||||
const onlyEditableRegionURI = `${baseURI}${editableRegionCode}`;
|
||||
const altURI = `${baseURI}${altStudentCode}`;
|
||||
|
||||
window.open(defaultURI.length < 8000 ? defaultURI : altURI, '_blank');
|
||||
let URIToOpen = defaultURI;
|
||||
if (defaultURI.length > 8000) {
|
||||
URIToOpen = onlyEditableRegionURI;
|
||||
}
|
||||
if (onlyEditableRegionURI.length > 8000) {
|
||||
URIToOpen = altURI;
|
||||
}
|
||||
|
||||
window.open(URIToOpen, '_blank');
|
||||
}),
|
||||
mapTo(closeModal('help'))
|
||||
);
|
||||
|
||||
@@ -255,7 +255,11 @@ export const reducer = handleActions(
|
||||
[payload]: !state.visibleEditors[payload]
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
[actionTypes.createQuestion]: (state, { payload }) => ({
|
||||
...state,
|
||||
description: payload
|
||||
})
|
||||
},
|
||||
initialState
|
||||
);
|
||||
|
||||
@@ -22,13 +22,13 @@ test.describe('Help Modal component', () => {
|
||||
})
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
name: `If you've already tried the Read-Search-Ask method, then you can ask for help on the freeCodeCamp forum.`
|
||||
})
|
||||
page.getByText(
|
||||
`If you've already tried the Read-Search-Ask method, then you can ask for help on the freeCodeCamp forum.`
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText(
|
||||
`Before making a new post please see if your question has already been answered on the forum.`
|
||||
`Before making a new post please check if your question has already been answered on the forum.`
|
||||
)
|
||||
).toBeVisible();
|
||||
|
||||
@@ -43,16 +43,13 @@ test.describe('Help Modal component', () => {
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('Create Post button closes help modal and creates new page with forum url', async ({
|
||||
context,
|
||||
test('should disable the submit button if the checboxes are not checked', async ({
|
||||
page
|
||||
}) => {
|
||||
await page
|
||||
.getByRole('button', { name: translations.buttons['ask-for-help'] })
|
||||
.click();
|
||||
|
||||
const newPagePromise = context.waitForEvent('page');
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: translations.buttons['create-post']
|
||||
@@ -64,7 +61,135 @@ test.describe('Help Modal component', () => {
|
||||
name: translations.buttons['ask-for-help'],
|
||||
exact: true
|
||||
})
|
||||
).not.toBeVisible();
|
||||
).toBeVisible();
|
||||
|
||||
const rsaCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have tried the Read-Search-Ask method'
|
||||
});
|
||||
|
||||
const similarQuestionsCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have searched for similar questions that have already been answered on the forum'
|
||||
});
|
||||
|
||||
const descriptionInput = page.getByRole('textbox', {
|
||||
name: translations['forum-help']['whats-happening']
|
||||
});
|
||||
|
||||
const submitButton = page.getByRole('button', {
|
||||
name: translations.buttons['submit']
|
||||
});
|
||||
|
||||
await descriptionInput.fill(
|
||||
'Example text with a 100 characters to validate if the rules applied to block users from spamming help forum are working.'
|
||||
);
|
||||
|
||||
await expect(submitButton).toBeDisabled();
|
||||
|
||||
await rsaCheckbox.check();
|
||||
await similarQuestionsCheckbox.uncheck();
|
||||
|
||||
await expect(submitButton).toBeDisabled();
|
||||
|
||||
await rsaCheckbox.uncheck();
|
||||
await similarQuestionsCheckbox.check();
|
||||
|
||||
await expect(submitButton).toBeDisabled();
|
||||
});
|
||||
|
||||
test('should disable the submit button if the description contains less than 50 characters', async ({
|
||||
page
|
||||
}) => {
|
||||
await page
|
||||
.getByRole('button', { name: translations.buttons['ask-for-help'] })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: translations.buttons['create-post']
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
name: translations.buttons['ask-for-help'],
|
||||
exact: true
|
||||
})
|
||||
).toBeVisible();
|
||||
|
||||
const rsaCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have tried the Read-Search-Ask method'
|
||||
});
|
||||
|
||||
const similarQuestionsCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have searched for similar questions that have already been answered on the forum'
|
||||
});
|
||||
|
||||
const descriptionInput = page.getByRole('textbox', {
|
||||
name: translations['forum-help']['whats-happening']
|
||||
});
|
||||
|
||||
const submitButton = page.getByRole('button', {
|
||||
name: translations.buttons['submit']
|
||||
});
|
||||
|
||||
await rsaCheckbox.click();
|
||||
await similarQuestionsCheckbox.click();
|
||||
await descriptionInput.fill('Example text');
|
||||
|
||||
await expect(submitButton).toBeDisabled();
|
||||
});
|
||||
|
||||
test('should ask the user to fill in the help form and create a forum page', async ({
|
||||
context,
|
||||
page
|
||||
}) => {
|
||||
await page
|
||||
.getByRole('button', { name: translations.buttons['ask-for-help'] })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: translations.buttons['create-post']
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
name: translations.buttons['ask-for-help'],
|
||||
exact: true
|
||||
})
|
||||
).toBeVisible();
|
||||
|
||||
const rsaCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have tried the Read-Search-Ask method'
|
||||
});
|
||||
|
||||
const similarQuestionsCheckbox = page.getByRole('checkbox', {
|
||||
name: 'I have searched for similar questions that have already been answered on the forum'
|
||||
});
|
||||
|
||||
const descriptionInput = page.getByRole('textbox', {
|
||||
name: translations['forum-help']['whats-happening']
|
||||
});
|
||||
|
||||
const submitButton = page.getByRole('button', {
|
||||
name: translations.buttons['submit']
|
||||
});
|
||||
|
||||
await expect(rsaCheckbox).toBeVisible();
|
||||
await expect(similarQuestionsCheckbox).toBeVisible();
|
||||
await expect(descriptionInput).toBeVisible();
|
||||
|
||||
await rsaCheckbox.check();
|
||||
await similarQuestionsCheckbox.check();
|
||||
await descriptionInput.fill(
|
||||
'Example text with a 100 characters to validate if the rules applied to block users from spamming help forum are working.'
|
||||
);
|
||||
|
||||
await expect(submitButton).toBeEnabled();
|
||||
await submitButton.click();
|
||||
|
||||
const newPagePromise = context.waitForEvent('page');
|
||||
|
||||
const newPage = await newPagePromise;
|
||||
await newPage.waitForLoadState();
|
||||
|
||||
Reference in New Issue
Block a user