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: generic template questions for cloned proposal #157

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
fe66cb8
fix:turn generic template events into an enum
mutambaraf Jan 13, 2023
94497e0
fix:improve how we mutate draftState for proposal genericTemplates
mutambaraf Jan 13, 2023
f6df3df
fix:use created generic template events to manage state in questionar…
mutambaraf Jan 13, 2023
b28966c
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 18, 2023
b5eaf1c
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 18, 2023
8e91d30
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 20, 2023
8632cc7
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 20, 2023
a07bb58
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 20, 2023
57b6990
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 24, 2023
de2f80a
add tests for generic subtemplates update on cloned proposals
mutambaraf Jan 24, 2023
9e7582e
fix deep scan issues
mutambaraf Jan 24, 2023
a95d191
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 31, 2023
0f80461
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Jan 31, 2023
67ab3d6
Improve naming and fix duplicate in generic template tests
mutambaraf Jan 31, 2023
17cd1d0
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Feb 3, 2023
614e965
Merge branch 'develop' into 763-fix-generic-template-questions-for-cl…
mutambaraf Feb 6, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ context('GenericTemplates tests', () => {
const addButtonLabel = twoFakes(2);
const genericTemplateTitle = faker.lorem.words(3);
const genericTemplateQuestionaryQuestion = twoFakes(3);
const genericTemplateTitleAnswers = [
faker.lorem.words(3),
faker.lorem.words(3),
faker.lorem.words(3),
faker.lorem.words(3),
];
const proposalWorkflow = {
name: faker.random.words(3),
description: faker.random.words(5),
Expand Down Expand Up @@ -150,6 +156,106 @@ context('GenericTemplates tests', () => {
}
});
};
const createGenericTemplates = (count: number) => {
const genericTemaplates: number[] = [];
for (let index = 0; index <= count; index++)
cy.createTemplate({
name: faker.lorem.word(5),
groupId: TemplateGroupId.GENERIC_TEMPLATE,
}).then((result) => {
if (result.createTemplate.template) {
const genericTemplateID = result.createTemplate.template.templateId;
const topicId =
result.createTemplate.template.steps[
result.createTemplate.template.steps.length - 1
].topic.id;
cy.createQuestion({
categoryId: TemplateCategoryId.GENERIC_TEMPLATE,
dataType: DataType.TEXT_INPUT,
}).then((questionResult) => {
const createdQuestion = questionResult.createQuestion.question;
if (createdQuestion) {
cy.updateQuestion({
id: createdQuestion.id,
question: faker.lorem.words(5),
naturalKey: faker.lorem.word(5),
config: `{"required":true,"multiline":false}`,
});
cy.createQuestionTemplateRelation({
questionId: createdQuestion.id,
templateId: genericTemplateID,
sortOrder: 1,
topicId: topicId,
});
}
});

genericTemaplates.push(genericTemplateID);
}
});

return genericTemaplates;
};
const createProposalTemplateWithSubTemplate = (
genericSubTemplateIds: number[]
) => {
cy.createTemplate({
name: faker.lorem.words(3),
groupId: TemplateGroupId.PROPOSAL,
}).then((result) => {
if (result.createTemplate.template) {
const proposalTemplateId = result.createTemplate.template.templateId;
for (let index = 0; index < genericSubTemplateIds.length - 1; index++) {
cy.createTopic({
templateId: proposalTemplateId,
sortOrder: index + 1,
}).then((topicResult) => {
if (!topicResult.createTopic.template) {
throw new Error('Can not create topic');
}
const topicId =
topicResult.createTopic.template.steps[
topicResult.createTopic.template.steps.length - 1
].topic.id;
cy.updateTopic({
title: faker.lorem.words(4),
templateId: proposalTemplateId,
sortOrder: index + 1,
topicId,
});
cy.createQuestion({
categoryId: TemplateCategoryId.PROPOSAL_QUESTIONARY,
dataType: DataType.GENERIC_TEMPLATE,
}).then((questionResult) => {
if (questionResult.createQuestion.question) {
const createdQuestion1Id =
questionResult.createQuestion.question.id;

cy.updateQuestion({
id: createdQuestion1Id,
question: genericTemplateQuestion[index],
config: `{"addEntryButtonLabel":"${addButtonLabel[index]}","minEntries":"1","maxEntries":"2","templateId":${genericSubTemplateIds[index]},"templateCategory":"GENERIC_TEMPLATE","required":false,"small_label":""}`,
});

cy.createQuestionTemplateRelation({
questionId: createdQuestion1Id,
templateId: proposalTemplateId,
sortOrder: index + 1,
topicId: topicId,
});
}
});
});
}
cy.updateCall({
id: initialDBData.call.id,
...updatedCall,
templateId: proposalTemplateId,
proposalWorkflowId: workflowId,
});
}
});
};

beforeEach(() => {
// NOTE: Stop the web application and clearly separate the end-to-end tests by visiting the blank about page before each test.
Expand Down Expand Up @@ -564,4 +670,149 @@ context('GenericTemplates tests', () => {
cy.contains(proposalTitle[1]).should('not.exist');
});
});

describe('Generic template cloning tests', () => {
beforeEach(() => {
cy.createProposalWorkflow(proposalWorkflow).then((result) => {
if (result.createProposalWorkflow.proposalWorkflow) {
workflowId = result.createProposalWorkflow.proposalWorkflow.id;
const genericTemplates = createGenericTemplates(2);
createProposalTemplateWithSubTemplate(genericTemplates);
cy.createProposal({ callId: initialDBData.call.id }).then(
(result) => {
if (result.createProposal.proposal) {
const proposalPK = result.createProposal.proposal.primaryKey;
const questionarySteps =
result.createProposal.proposal.questionary.steps;
const proposal = result.createProposal.proposal;
cy.updateProposal({
proposalPk: result.createProposal.proposal.primaryKey,
title: proposalTitle[1],
abstract: faker.lorem.words(3),
proposerId: initialDBData.users.user1.id,
});

for (let index = 1; index < questionarySteps.length; index++) {
cy.createGenericTemplate({
proposalPk: result.createProposal.proposal.primaryKey,
title: genericTemplateTitleAnswers[index - 1],
questionId:
result.createProposal.proposal.questionary.steps[index]
.fields[0].question.id,
templateId: genericTemplates[index - 1],
}).then((templateResult) => {
if (
templateResult.createGenericTemplate.genericTemplate
?.questionaryId
) {
cy.answerTopic({
isPartialSave: false,
questionaryId:
templateResult.createGenericTemplate.genericTemplate
.questionaryId,
topicId:
templateResult.createGenericTemplate.genericTemplate
.questionary.steps[0].topic.id,
answers: [
{
questionId:
templateResult.createGenericTemplate
.genericTemplate.questionary.steps[0].fields[1]
.question.id,
value: '{"value":"answer"}',
},
],
});
}
});
cy.answerTopic({
questionaryId: proposal.questionaryId,
topicId: questionarySteps[index].topic.id,
isPartialSave: false,
answers: [],
});
}
cy.cloneProposals({
callId: initialDBData.call.id,
proposalsToClonePk: [proposalPK],
});
}
}
);
} else {
throw new Error('Workflow creation failed');
}
});
});
it('User should be able to modify and submit cloned proposal with generic templates', () => {
cy.login('user1');
cy.visit('/');

cy.finishedLoading();

cy.contains(`Copy of ${proposalTitle[1]}`)
.parent()
.find('[aria-label="Edit proposal"]')
.click();

cy.finishedLoading();

cy.contains('New proposal', { matchCase: true }).click();

cy.get('[data-cy=title] input').clear().type(faker.lorem.word(5));

cy.get('[data-cy=abstract] textarea').first().type(faker.lorem.words(2));

cy.contains('Save and continue').click();

cy.finishedLoading();

cy.contains(genericTemplateTitleAnswers[0]).click();

cy.get('[data-cy=title-input] textarea')
.first()
.clear()
.type(genericTemplateTitleAnswers[2])
.should('have.value', genericTemplateTitleAnswers[2])
.blur();

cy.get(
'[data-cy=genericTemplate-declaration-modal] [data-cy=save-and-continue-button]'
).click();

cy.finishedLoading();

cy.contains(genericTemplateTitleAnswers[2]);

cy.contains('Save and continue').click();

cy.finishedLoading();

cy.contains(genericTemplateTitleAnswers[1]).click();

cy.get('[data-cy=title-input] textarea')
.first()
.clear()
.type(genericTemplateTitleAnswers[3])
.should('have.value', genericTemplateTitleAnswers[3])
.blur();

cy.get(
'[data-cy=genericTemplate-declaration-modal] [data-cy=save-and-continue-button]'
).click();

cy.finishedLoading();

cy.contains(genericTemplateTitleAnswers[3]);

cy.contains('Save and continue').click();

cy.contains('Submit').click();

cy.contains('OK').click();

cy.contains(genericTemplateTitleAnswers[2]);
cy.contains(genericTemplateTitleAnswers[3]);
});
});
});
12 changes: 12 additions & 0 deletions apps/user-office-frontend-e2e/cypress/support/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import {
CreateTemplateMutation,
CreateTemplateMutationVariables,
CreateTopicMutation,
UpdateTopicMutation,
CreateTopicMutationVariables,
UpdateQuestionMutation,
UpdateQuestionMutationVariables,
UpdateQuestionTemplateRelationSettingsMutation,
UpdateQuestionTemplateRelationSettingsMutationVariables,
UpdateTopicMutationVariables,
} from '@user-office-software-libs/shared-types';

import { getE2EApi } from './utils';
Expand All @@ -43,6 +45,15 @@ const createTopic = (
return cy.wrap(request);
};

const updateTopic = (
updateTopicInput: UpdateTopicMutationVariables
): Cypress.Chainable<UpdateTopicMutation> => {
const api = getE2EApi();
const request = api.updateTopic(updateTopicInput);

return cy.wrap(request);
};

const answerTopic = (
answerTopicInput: AnswerTopicMutationVariables
): Cypress.Chainable<AnswerTopicMutation> => {
Expand Down Expand Up @@ -549,6 +560,7 @@ Cypress.Commands.add('createGenericTemplate', createGenericTemplate);
Cypress.Commands.add('navigateToTemplatesSubmenu', navigateToTemplatesSubmenu);

Cypress.Commands.add('createTopic', createTopic);
Cypress.Commands.add('updateTopic', updateTopic);
Cypress.Commands.add('answerTopic', answerTopic);

Cypress.Commands.add('createQuestion', createQuestion);
Expand Down
13 changes: 13 additions & 0 deletions apps/user-office-frontend-e2e/cypress/types/template.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
CreateQuestionTemplateRelationMutation,
CreateQuestionTemplateRelationMutationVariables,
CreateTopicMutation,
UpdateTopicMutation,
CreateGenericTemplateMutationVariables,
CreateGenericTemplateMutation,
AnswerTopicMutationVariables,
Expand Down Expand Up @@ -279,6 +280,18 @@ declare global {
createTopicInput: CreateTopicMutationVariables
) => Cypress.Chainable<CreateTopicMutation>;

/**
* Updates topic in template
*
* @returns {typeof updateTopic}
* @memberof Chainable
* @example
* cy.updateTopic(updateTopicInput: UpdateTopicMutationVariables)
*/
updateTopic: (
updateTopicInput: UpdateTopicMutationVariables
) => Cypress.Chainable<UpdateTopicMutation>;

/**
* Answers topic in proposal template
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ProposalSubmissionState } from 'models/questionary/proposal/ProposalSub
import { ProposalWithQuestionary } from 'models/questionary/proposal/ProposalWithQuestionary';
import {
Event,
GENERIC_TEMPLATE_EVENT,
QuestionarySubmissionModel,
} from 'models/questionary/QuestionarySubmissionState';
import useEventHandlers from 'models/questionary/useEventHandlers';
Expand Down Expand Up @@ -61,8 +62,35 @@ export default function ProposalContainer(props: ProposalContainerProps) {
draftState.proposal.samples = action.newItems;
draftState.isDirty = true;
break;
case 'GENERIC_TEMPLATE_ITEMS_MODIFIED':
draftState.proposal.genericTemplates = action.newItems;
case GENERIC_TEMPLATE_EVENT.ITEMS_MODIFIED:
if (action.newItems) {
if (state.proposal.genericTemplates) {
const questionIds = action.newItems.map((value) => value.id);
draftState.proposal.genericTemplates = [
...state.proposal.genericTemplates.filter(
(value) => !questionIds.some((id) => id === value.id)
),
...action.newItems,
];
} else {
draftState.proposal.genericTemplates = action.newItems;
}
}
draftState.isDirty = true;
break;

case GENERIC_TEMPLATE_EVENT.ITEMS_DELETED:
if (action.newItems) {
if (state.proposal.genericTemplates) {
const questionIds = action.newItems.map((value) => value.id);
draftState.proposal.genericTemplates = [
...state.proposal.genericTemplates.filter(
(value) => !questionIds.some((id) => id === value.id)
),
];
action.newItems = [];
}
}
draftState.isDirty = true;
break;
}
Expand Down
Loading