import { makeAppObjectRepo } from "@vived/core";
import { makeQuestionAnswerEntity } from "./QuestionAnswerEntity";
import { makeQuestionEntity, VALIDATION_NOT_ENOUGH_ANSWERS, VALIDATION_NO_CORRECT, } from "./QuestionEntity";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const questionAO = appObjects.getOrCreate("Question");
    const questionEntity = makeQuestionEntity(questionAO);
    questionEntity.answerFactory = (id) => {
        const index = questionEntity.getAllAnswers().length + 1;
        const ao = appObjects.getOrCreate(id ?? "answer" + index);
        return makeQuestionAnswerEntity(ao);
    };
    const observer = jest.fn();
    questionEntity.addChangeObserver(observer);
    const mockWarn = jest.fn();
    questionEntity.warn = mockWarn;
    const answerAO = appObjects.getOrCreate("answer");
    const mockAns = makeQuestionAnswerEntity(answerAO);
    return { questionEntity, observer, appObjects, mockWarn, mockAns };
}
describe("Question Challenge Entity", () => {
    it("Allows adding an answer", () => {
        const { questionEntity, observer, mockAns } = makeTestRig();
        expect(questionEntity.getAllAnswers()).toHaveLength(0);
        questionEntity.addAnswer(mockAns);
        expect(questionEntity.getAllAnswers()).toHaveLength(1);
        expect(questionEntity.getAnswer("answer")).toEqual(mockAns);
        expect(observer).toHaveBeenCalled();
    });
    it("Calls reset when an answers is added", () => {
        const { questionEntity, mockAns } = makeTestRig();
        questionEntity.reset = jest.fn();
        questionEntity.addAnswer(mockAns);
        expect(questionEntity.reset).toHaveBeenCalled();
    });
    it("Allows an answer to be removed", () => {
        const { questionEntity, observer, mockAns } = makeTestRig();
        questionEntity.addAnswer(mockAns);
        observer.mockClear();
        questionEntity.removeAnswer(mockAns.id);
        expect(observer).toHaveBeenCalled();
        expect(questionEntity.getAllAnswers()).toHaveLength(0);
    });
    it("Calls reset when an answers is removed", () => {
        const { questionEntity, mockAns } = makeTestRig();
        questionEntity.addAnswer(mockAns);
        questionEntity.reset = jest.fn();
        questionEntity.removeAnswer(mockAns.id);
        expect(questionEntity.reset).toHaveBeenCalled();
    });
    it("Does not notify if an unknown answer is removed", () => {
        const { questionEntity, observer } = makeTestRig();
        observer.mockClear();
        questionEntity.removeAnswer("whatTheFuuuu");
        expect(observer).not.toHaveBeenCalled();
    });
    it("Gets an answer by id", () => {
        const { questionEntity, mockAns } = makeTestRig();
        questionEntity.addAnswer(mockAns);
        const returnedAnswer = questionEntity.getAnswer(mockAns.id);
        expect(returnedAnswer).toEqual(mockAns);
    });
    it("Returns an undefined if an unknown ID is passed in for getting an answer", () => {
        const { questionEntity, mockAns } = makeTestRig();
        questionEntity.addAnswer(mockAns);
        const returnedAnswer = questionEntity.getAnswer("what");
        expect(returnedAnswer).toBeUndefined();
    });
    it("Check to see if it has an answer", () => {
        const { questionEntity, mockAns } = makeTestRig();
        questionEntity.addAnswer(mockAns);
        expect(questionEntity.hasAnswer(mockAns.id)).toEqual(true);
        expect(questionEntity.hasAnswer("what")).toEqual(false);
    });
    it("Can create an answer", () => {
        const { questionEntity, observer } = makeTestRig();
        expect(questionEntity.getAllAnswers()).toHaveLength(0);
        const answer = questionEntity.createNewAnswer();
        expect(questionEntity.getAllAnswers()).toHaveLength(1);
        expect(observer).toHaveBeenCalled();
        expect(questionEntity.getAnswer(answer.id)).toEqual(answer);
    });
    it("Calls reset when an answers is created", () => {
        const { questionEntity } = makeTestRig();
        questionEntity.reset = jest.fn();
        questionEntity.createNewAnswer();
        expect(questionEntity.reset).toHaveBeenCalled();
    });
    it("Allows an observer to be removed", () => {
        const { questionEntity, observer } = makeTestRig();
        questionEntity.removeChangeObserver(observer);
        observer.mockClear();
        questionEntity.createNewAnswer();
        expect(observer).not.toHaveBeenCalled();
    });
    it("Allows all answers to be removed", () => {
        const { questionEntity, observer } = makeTestRig();
        questionEntity.createNewAnswer();
        questionEntity.createNewAnswer();
        questionEntity.createNewAnswer();
        observer.mockClear();
        questionEntity.removeAllAnswers();
        expect(questionEntity.getAllAnswers()).toHaveLength(0);
        expect(observer).toHaveBeenCalled();
    });
    it("Calls reset when all answers are removed", () => {
        const { questionEntity } = makeTestRig();
        questionEntity.reset = jest.fn();
        questionEntity.removeAllAnswers();
        expect(questionEntity.reset).toHaveBeenCalled();
    });
    it("Handles submitting a correct answer", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        ans.isCorrect = true;
        expect(questionEntity.gotItRight).toEqual(false);
        observer.mockClear();
        questionEntity.submitAnswer(ans.id);
        expect(questionEntity.gotItRight).toEqual(true);
        expect(observer).toHaveBeenCalled();
    });
    it("Handles submitting an incorrect answer", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        ans.isCorrect = false;
        expect(questionEntity.gotItRight).toEqual(false);
        observer.mockClear();
        questionEntity.submitAnswer(ans.id);
        expect(questionEntity.gotItRight).toEqual(false);
        expect(observer).toHaveBeenCalled();
    });
    it("Sets the review text to the answer text", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        ans.feedbackText = "Hello world!";
        expect(questionEntity.reviewFeedback).toEqual("");
        observer.mockClear();
        questionEntity.submitAnswer(ans.id);
        expect(questionEntity.reviewFeedback).toEqual("Hello world!");
        expect(observer).toHaveBeenCalled();
    });
    it("Defaults the review feedback to Correct for a correct answer with no feedback", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        ans.feedbackText = "";
        ans.isCorrect = true;
        expect(questionEntity.reviewFeedback).toEqual("");
        observer.mockClear();
        questionEntity.submitAnswer(ans.id);
        expect(questionEntity.reviewFeedback).toEqual("Correct");
        expect(observer).toHaveBeenCalled();
    });
    it("Defaults the review feedback to Incorrect for an incorrect answer with no feedback", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        ans.feedbackText = "";
        ans.isCorrect = false;
        expect(questionEntity.reviewFeedback).toEqual("");
        observer.mockClear();
        questionEntity.submitAnswer(ans.id);
        expect(questionEntity.reviewFeedback).toEqual("Incorrect");
        expect(observer).toHaveBeenCalled();
    });
    it("Should warn but not change anything when submitting an unknown answer ", () => {
        const { questionEntity, observer, mockWarn } = makeTestRig();
        expect(questionEntity.gotItRight).toEqual(false);
        observer.mockClear();
        questionEntity.submitAnswer("unknown");
        expect(mockWarn).toHaveBeenCalled();
        expect(questionEntity.gotItRight).toEqual(false);
        expect(observer).not.toHaveBeenCalled();
    });
    it("Allows the questionEntity to be reset", () => {
        const { questionEntity, observer } = makeTestRig();
        const correct = questionEntity.createNewAnswer();
        correct.isCorrect = true;
        correct.feedbackText = "Hello World";
        const incorrect = questionEntity.createNewAnswer();
        incorrect.isCorrect = false;
        questionEntity.submitAnswer(incorrect.id);
        questionEntity.submitAnswer(correct.id);
        expect(questionEntity.gotItRight).toEqual(true);
        expect(questionEntity.reviewFeedback).toEqual("Hello World");
        observer.mockClear();
        questionEntity.reset();
        expect(questionEntity.gotItRight).toEqual(false);
        expect(questionEntity.reviewFeedback).toEqual("");
        expect(observer).toHaveBeenCalled();
    });
    it("Returns a validation message if there are not enough answers", () => {
        const { questionEntity } = makeTestRig();
        expect(questionEntity.validationMessage).toEqual(VALIDATION_NOT_ENOUGH_ANSWERS);
        const ans1 = questionEntity.createNewAnswer();
        ans1.text = "some text";
        expect(questionEntity.validationMessage).toEqual(VALIDATION_NOT_ENOUGH_ANSWERS);
        const ans2 = questionEntity.createNewAnswer();
        ans2.isCorrect = true;
        ans2.text = "some text";
        expect(questionEntity.validationMessage).toBeUndefined();
    });
    it("Returns a validation message if no answers are correct", () => {
        const { questionEntity } = makeTestRig();
        const ans1 = questionEntity.createNewAnswer();
        ans1.text = "some text";
        const ans2 = questionEntity.createNewAnswer();
        ans2.text = "some text";
        expect(questionEntity.validationMessage).toEqual(VALIDATION_NO_CORRECT);
        ans2.isCorrect = true;
        expect(questionEntity.validationMessage).toBeUndefined();
    });
    it("Forwards changes from the answers", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        observer.mockClear();
        ans.text = "Hello World";
        expect(observer).toHaveBeenCalled();
    });
    it("Stops forwarding changes from deleted answers", () => {
        const { questionEntity, observer } = makeTestRig();
        const ans = questionEntity.createNewAnswer();
        questionEntity.removeAnswer(ans.id);
        observer.mockClear();
        ans.text = "Hello World";
        expect(observer).not.toHaveBeenCalled();
    });
});
//# sourceMappingURL=QuestionEntity.test.js.map