add images and varimg preview tests

This commit is contained in:
nflnkr 2023-11-04 20:04:24 +03:00
parent 87760f3498
commit 629e0c37c6
18 changed files with 198 additions and 23 deletions

@ -15,10 +15,11 @@ describe("Quiz preview", () => {
}); });
describe("Variant question", () => { describe("Variant question", () => {
beforeEach(function fillTitleAndOptions() { beforeEach(function setupQuestion() {
cy.get("[data-cy=select-questiontype-variant]").click(); cy.get("[data-cy=select-questiontype-variant]").click();
cy.get("[data-cy=quiz-question-card]").eq(0).within(() => { cy.get("[data-cy=quiz-question-card]").eq(0).within(() => {
cy.get("[data-cy=quiz-question-title]").type("Question Title"); cy.get("[data-cy=quiz-question-title]").type("Question Title");
cy.get("[data-cy=quiz-variant-question-answer]").eq(0).type("Answer 1{enter}"); cy.get("[data-cy=quiz-variant-question-answer]").eq(0).type("Answer 1{enter}");
cy.get("[data-cy=quiz-variant-question-answer]").eq(1).type("Answer 2{enter}"); cy.get("[data-cy=quiz-variant-question-answer]").eq(1).type("Answer 2{enter}");
cy.get("[data-cy=quiz-variant-question-answer]").eq(2).type("Answer 3"); cy.get("[data-cy=quiz-variant-question-answer]").eq(2).type("Answer 3");
@ -49,4 +50,153 @@ describe("Quiz preview", () => {
}); });
}); });
}); });
describe("Image question", () => {
beforeEach(function setupQuestion() {
cy.fixture("image1.png", null).as("image1");
cy.fixture("image2.png", null).as("image2");
cy.fixture("image3.png", null).as("image3");
cy.get("[data-cy=select-questiontype-images]").click();
cy.get("[data-cy=quiz-question-card]").eq(0).within(() => {
cy.get("[data-cy=quiz-question-title]").type("Question Title");
cy.get("[data-cy=quiz-variant-question-answer]").eq(0).type("Answer 1{enter}");
cy.get("[data-cy=add-variant-image-button]").eq(0).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image1", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
cy.get("[data-cy=quiz-variant-question-answer]").eq(1).type("Answer 2{enter}");
cy.get("[data-cy=add-variant-image-button]").eq(1).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image2", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
cy.get("[data-cy=quiz-variant-question-answer]").eq(2).type("Answer 3");
cy.get("[data-cy=add-variant-image-button]").eq(2).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image3", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
});
});
it("should contain title and options, and be selected properly", () => {
cy.get("[data-cy=quiz-preview-layout]").within(() => {
cy.get("[data-cy=variant-button] > img").eq(0).should("have.attr", "src").and("match", /^blob:.+/);
cy.get("[data-cy=variant-button] > img").eq(1).should("have.attr", "src").and("match", /^blob:.+/);
cy.get("[data-cy=variant-button] > img").eq(2).should("have.attr", "src").and("match", /^blob:.+/);
cy.get("[data-cy=variant-button]").eq(0).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(1).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(2).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "true");
});
});
it("should work with multiple selection mode", () => {
cy.get("[data-cy=quiz-question-card]").eq(0).within(() => {
cy.get("[data-cy=multiple-answers-checkbox]").click();
});
cy.get("[data-cy=quiz-preview-layout]").within(() => {
cy.get("[data-cy=variant-button]").eq(0).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(1).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(2).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(0).click();
cy.get("[data-cy=variant-button]").eq(0).should("have.attr", "data-checked", "false");
cy.get("[data-cy=variant-button]").eq(1).should("have.attr", "data-checked", "true");
cy.get("[data-cy=variant-button]").eq(2).should("have.attr", "data-checked", "true");
});
});
});
describe.only("Varimg question", () => {
beforeEach(function setupQuestion() {
cy.fixture("image1.png", null).as("image1");
cy.fixture("image2.png", null).as("image2");
cy.fixture("image3.png", null).as("image3");
cy.get("[data-cy=select-questiontype-varimg]").click();
cy.get("[data-cy=quiz-question-card]").eq(0).within(() => {
cy.get("[data-cy=quiz-question-title]").type("Question Title");
cy.get("[data-cy=quiz-variant-question-answer]").eq(0).type("Answer 1{enter}");
cy.get("[data-cy=add-variant-image-button]").eq(0).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image1", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
cy.get("[data-cy=quiz-variant-question-answer]").eq(1).type("Answer 2{enter}");
cy.get("[data-cy=add-variant-image-button]").eq(1).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image2", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
cy.get("[data-cy=quiz-variant-question-answer]").eq(2).type("Answer 3");
cy.get("[data-cy=add-variant-image-button]").eq(2).click();
cy.get("[data-cy=upload-image-input]", { withinSubject: null }).selectFile("@image3", { force: true });
cy.get("[data-cy=crop-modal-save-button]", { withinSubject: null }).click();
});
});
it("should contain title and options, and be selected properly", function () {
cy.get("[data-cy=quiz-preview-layout]").within(() => {
cy.get("[data-cy=variant-title]").should("have.text", "Question Title");
cy.get("[data-cy=variant-title]").should("have.text", "Question Title");
cy.get("[data-cy=variant-answer]").eq(0).should("have.text", "Answer 1");
cy.get("[data-cy=variant-answer]").eq(1).should("have.text", "Answer 2");
cy.get("[data-cy=variant-answer]").eq(2).should("have.text", "Answer 3");
cy.get("[data-cy=variant-answer]").eq(0).click();
cy.get("[data-cy=variant-radio]").eq(0).should("be.checked");
cy.get("[data-cy=variant-radio]").eq(1).should("not.be.checked");
cy.get("[data-cy=variant-radio]").eq(2).should("not.be.checked");
cy.get("[data-cy=variant-image]")
.invoke("attr", "src")
.should("match", /^blob:.+/)
.as("src1", { type: "static" });
cy.get("[data-cy=variant-answer]").eq(1).click();
cy.get("[data-cy=variant-radio]").eq(0).should("not.be.checked");
cy.get("[data-cy=variant-radio]").eq(1).should("be.checked");
cy.get("[data-cy=variant-radio]").eq(2).should("not.be.checked");
cy.get("[data-cy=variant-image]")
.invoke("attr", "src")
.should("match", /^blob:.+/)
.then(src2 => {
cy.get("@src1").should("not.equal", src2);
});
cy.get("[data-cy=variant-answer]").eq(2).click();
cy.get("[data-cy=variant-radio]").eq(0).should("not.be.checked");
cy.get("[data-cy=variant-radio]").eq(1).should("not.be.checked");
cy.get("[data-cy=variant-radio]").eq(2).should("be.checked");
cy.get("[data-cy=variant-image]")
.invoke("attr", "src")
.should("match", /^blob:.+/)
.then(src3 => {
cy.get("@src1").should("not.equal", src3);
});
});
});
});
}); });

BIN
cypress/fixtures/image1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
cypress/fixtures/image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
cypress/fixtures/image3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

@ -23,14 +23,13 @@ import type { ChangeEvent, KeyboardEvent, ReactNode } from "react";
import type { DroppableProvided } from "react-beautiful-dnd"; import type { DroppableProvided } from "react-beautiful-dnd";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant"; import type { ImageQuestionVariant, QuestionVariant } from "../../../model/questionTypes/shared";
import type { QuestionVariant } from "../../../model/questionTypes/shared";
type AnswerItemProps = { type AnswerItemProps = {
index: number; index: number;
totalIndex: number; totalIndex: number;
variants: QuestionVariant[]; variants: (QuestionVariant | ImageQuestionVariant)[];
variant: QuestionVariant; variant: QuestionVariant | ImageQuestionVariant;
provided: DroppableProvided; provided: DroppableProvided;
additionalContent?: ReactNode; additionalContent?: ReactNode;
additionalMobile?: ReactNode; additionalMobile?: ReactNode;
@ -48,12 +47,12 @@ export const AnswerItem = ({
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore(); const { listQuestions } = questionStore();
const theme = useTheme(); const theme = useTheme();
const question = listQuestions[quizId][totalIndex] as QuizQuestionVariant; const question = listQuestions[quizId][totalIndex];
const isTablet = useMediaQuery(theme.breakpoints.down(790)); const isTablet = useMediaQuery(theme.breakpoints.down(790));
const debounced = useDebouncedCallback((value) => { const debounced = useDebouncedCallback((value) => {
const answerNew = variants.slice(); const answerNew = variants.slice();
answerNew[index].answer = value; answerNew[index].answer = value;
updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { content: {
...question.content, ...question.content,
variants: answerNew, variants: answerNew,
@ -61,7 +60,6 @@ export const AnswerItem = ({
}); });
}, 1000); }, 1000);
console.log(provided)
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null); const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
@ -77,9 +75,14 @@ console.log(provided)
const addNewAnswer = () => { const addNewAnswer = () => {
const answerNew = variants.slice(); const answerNew = variants.slice();
answerNew.push({ answer: "", extendedText: "", hints: "" });
updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, { if (["images", "varimg"].includes(question.type)) {
answerNew.push({ answer: "", hints: "", extendedText: "", originalImageUrl: "" });
} else {
answerNew.push({ answer: "", extendedText: "", hints: "" });
}
updateQuestionsList(quizId, totalIndex, {
content: { ...question.content, variants: answerNew }, content: { ...question.content, variants: answerNew },
}); });
}; };
@ -88,7 +91,7 @@ console.log(provided)
const answerNew = variants.slice(); const answerNew = variants.slice();
answerNew.splice(index, 1); answerNew.splice(index, 1);
updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { ...question.content, variants: answerNew }, content: { ...question.content, variants: answerNew },
}); });
}; };
@ -97,11 +100,12 @@ console.log(provided)
const answerNew = variants.slice(); const answerNew = variants.slice();
answerNew[index].hints = event.target.value; answerNew[index].hints = event.target.value;
updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, { updateQuestionsList(quizId, totalIndex, {
content: { ...question.content, variants: answerNew }, content: { ...question.content, variants: answerNew },
}); });
}; };
const largeCheck = ("largeCheck" in question.content) ? question.content.largeCheck : false
return ( return (
<Draggable draggableId={String(index)} index={index}> <Draggable draggableId={String(index)} index={index}>
@ -123,10 +127,10 @@ console.log(provided)
fullWidth fullWidth
focused={false} focused={false}
placeholder={"Добавьте ответ"} placeholder={"Добавьте ответ"}
multiline={question.content.largeCheck} multiline={largeCheck}
onChange={({ target }) => debounced(target.value)} onChange={({ target }) => debounced(target.value)}
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => { onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
if (event.code === "Enter" && !question.content.largeCheck) { if (event.code === "Enter" && !largeCheck) {
addNewAnswer(); addNewAnswer();
} }
}} }}

@ -19,8 +19,6 @@ export default memo(
({ index, isDragging, questionData }: DraggableListItemProps) => { ({ index, isDragging, questionData }: DraggableListItemProps) => {
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const theme = useTheme(); const theme = useTheme();
console.log("Мой индекс " + index);
console.log(questionData);
return ( return (
<Draggable draggableId={String(index)} index={index}> <Draggable draggableId={String(index)} index={index}>

@ -78,6 +78,7 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
<CustomCheckbox <CustomCheckbox
label={"Можно несколько"} label={"Можно несколько"}
checked={question.content.multi} checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList<QuizQuestionSelect>(quizId, totalIndex, { updateQuestionsList<QuizQuestionSelect>(quizId, totalIndex, {
content: { ...question.content, multi: target.checked }, content: { ...question.content, multi: target.checked },

@ -55,6 +55,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"} label={"Можно несколько"}
checked={question.content.multi} checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestionsList<QuizQuestionEmoji>(quizId, totalIndex, { updateQuestionsList<QuizQuestionEmoji>(quizId, totalIndex, {
content: { ...question.content, multi: target.checked }, content: { ...question.content, multi: target.checked },

@ -19,8 +19,6 @@ export default memo(
({ index, isDragging, questionData }: FormDraggableListItemProps) => { ({ index, isDragging, questionData }: FormDraggableListItemProps) => {
const quizId = Number(useParams().quizId); const quizId = Number(useParams().quizId);
const theme = useTheme(); const theme = useTheme();
console.log("Мой индекс " + index);
console.log(questionData);
return ( return (
<Draggable draggableId={String(index)} index={index}> <Draggable draggableId={String(index)} index={index}>

@ -179,6 +179,7 @@ export default function SettingOpytionsPict({
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }} sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"} label={"Можно несколько"}
checked={question.content.multi} checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestionsList<QuizQuestionImages>(quizId, totalIndex, { updateQuestionsList<QuizQuestionImages>(quizId, totalIndex, {
content: { ...question.content, multi: target.checked }, content: { ...question.content, multi: target.checked },

@ -84,6 +84,7 @@ export const UploadImageModal: React.FC<ModalkaProps> = ({
accept="image/*" accept="image/*"
multiple multiple
type="file" type="file"
data-cy="upload-image-input"
/> />
<Box <Box
onDragOver={(event: DragEvent<HTMLDivElement>) => onDragOver={(event: DragEvent<HTMLDivElement>) =>

@ -80,6 +80,7 @@ export default function ResponseSettings({ totalIndex }: Props) {
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"} label={"Можно несколько"}
checked={question.content.multi} checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, { updateQuestionsList<QuizQuestionVariant>(quizId, totalIndex, {
content: { ...question.content, multi: target.checked }, content: { ...question.content, multi: target.checked },

@ -50,6 +50,7 @@ export default function AddOrEditImageButton({ onImageClick, onPlusClick, sx, im
</Button> </Button>
<Button <Button
onClick={onPlusClick} onClick={onPlusClick}
data-cy="add-variant-image-button"
sx={{ sx={{
p: 0, p: 0,
minWidth: "20px", minWidth: "20px",

@ -8,9 +8,10 @@ interface Props {
handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
checked?: boolean; checked?: boolean;
sx?: SxProps; sx?: SxProps;
dataCy?: string;
} }
export default function CustomCheckbox({ label, handleChange, checked, sx }: Props) { export default function CustomCheckbox({ label, handleChange, checked, sx, dataCy }: Props) {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -24,6 +25,7 @@ export default function CustomCheckbox({ label, handleChange, checked, sx }: Pro
checkedIcon={<CheckedIcon />} checkedIcon={<CheckedIcon />}
onChange={handleChange} onChange={handleChange}
checked={checked} checked={checked}
data-cy={dataCy}
/> />
} }
label={label} label={label}

@ -244,6 +244,7 @@ export const CropModal: FC<Props> = ({ onSaveImageClick }) => {
<Button <Button
onClick={handleSaveClick} onClick={handleSaveClick}
disableRipple disableRipple
data-cy="crop-modal-save-button"
sx={{ sx={{
height: "48px", height: "48px",
color: "#7E2AEA", color: "#7E2AEA",

@ -61,6 +61,8 @@ export default function Images({ question }: Props) {
<ButtonBase <ButtonBase
key={index} key={index}
onClick={() => handleVariantClick(index)} onClick={() => handleVariantClick(index)}
data-cy="variant-button"
data-checked={selectedVariants.includes(index)}
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",

@ -41,6 +41,7 @@ export default function Variant({ question }: Props) {
<FormControlLabel <FormControlLabel
key={index} key={index}
value={variant.answer} value={variant.answer}
data-cy="variant-answer"
control={ control={
<Radio <Radio
inputProps={{ inputProps={{
@ -50,7 +51,7 @@ export default function Variant({ question }: Props) {
} }
label={ label={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}> <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography data-cy="variant-answer"> <Typography>
{variant.answer} {variant.answer}
</Typography> </Typography>
{variant.hints && ( {variant.hints && (

@ -42,7 +42,12 @@ export default function Varimg({ question }: Props) {
}} }}
> >
<FormControl> <FormControl>
<FormLabel id="quiz-question-radio-group">{question.title}</FormLabel> <FormLabel
id="quiz-question-radio-group"
data-cy="variant-title"
>
{question.title}
</FormLabel>
<RadioGroup <RadioGroup
aria-labelledby="quiz-question-radio-group" aria-labelledby="quiz-question-radio-group"
value={currentVariant?.answer ?? ""} value={currentVariant?.answer ?? ""}
@ -54,7 +59,14 @@ export default function Varimg({ question }: Props) {
<FormControlLabel <FormControlLabel
key={index} key={index}
value={variant.answer} value={variant.answer}
control={<Radio />} data-cy="variant-answer"
control={
<Radio
inputProps={{
"data-cy": "variant-radio",
}}
/>
}
label={ label={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}> <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<Typography>{variant.answer}</Typography> <Typography>{variant.answer}</Typography>
@ -84,6 +96,7 @@ export default function Varimg({ question }: Props) {
{currentVariant?.extendedText ? ( {currentVariant?.extendedText ? (
<img <img
src={currentVariant.extendedText} src={currentVariant.extendedText}
data-cy="variant-image"
alt="question variant" alt="question variant"
style={{ style={{
width: "100%", width: "100%",