itemengine-cypress-automation 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. package/.build_wna +4 -0
  2. package/README.md +3 -0
  3. package/currents.config.js +6 -0
  4. package/cypress/API/createItem/toggleItemMode.js +15 -0
  5. package/cypress/config-files/ildev.json +15 -0
  6. package/cypress/config-files/ilprod.json +15 -0
  7. package/cypress/config-files/ilqa.json +15 -0
  8. package/cypress/config-files/ilstage.json +15 -0
  9. package/cypress/e2e/ILC/sorry-cypress-test/spec1.js +18 -0
  10. package/cypress/e2e/ILC/sorry-cypress-test/spec2.js +18 -0
  11. package/cypress/e2e/ILC/sorry-cypress-test/spec3.js +18 -0
  12. package/cypress/fixtures/accessibilityConfig.json +6 -0
  13. package/cypress/fixtures/constants.js +18 -0
  14. package/cypress/fixtures/equationEditorCategoriesAndSymbols .js +2271 -0
  15. package/cypress/fixtures/specialAndMathCharacters.js +118 -0
  16. package/cypress/fixtures/theme/ilc.json +150 -0
  17. package/cypress/fixtures/theme/ngie.json +26 -0
  18. package/cypress/fixtures/uploads/20mbFile.png +0 -0
  19. package/cypress/fixtures/uploads/80mbFile.pdf +0 -0
  20. package/cypress/fixtures/uploads/highlightImage.jpg +0 -0
  21. package/cypress/fixtures/uploads/image.png +0 -0
  22. package/cypress/fixtures/uploads/sample.aac +0 -0
  23. package/cypress/fixtures/uploads/sample.accdb +0 -0
  24. package/cypress/fixtures/uploads/sample.csv +100 -0
  25. package/cypress/fixtures/uploads/sample.doc +0 -0
  26. package/cypress/fixtures/uploads/sample.gif +0 -0
  27. package/cypress/fixtures/uploads/sample.heic +0 -0
  28. package/cypress/fixtures/uploads/sample.heif +0 -0
  29. package/cypress/fixtures/uploads/sample.hevc +0 -0
  30. package/cypress/fixtures/uploads/sample.jpeg +0 -0
  31. package/cypress/fixtures/uploads/sample.jpg +0 -0
  32. package/cypress/fixtures/uploads/sample.mp3 +0 -0
  33. package/cypress/fixtures/uploads/sample.mp4 +0 -0
  34. package/cypress/fixtures/uploads/sample.pdf +0 -0
  35. package/cypress/fixtures/uploads/sample.ppt +0 -0
  36. package/cypress/fixtures/uploads/sample.pub +0 -0
  37. package/cypress/fixtures/uploads/sample.rtf +7902 -0
  38. package/cypress/fixtures/uploads/sample.svg +10 -0
  39. package/cypress/fixtures/uploads/sample.txt +1 -0
  40. package/cypress/fixtures/uploads/sample.wav +0 -0
  41. package/cypress/fixtures/uploads/sample.xlsx +0 -0
  42. package/cypress/fixtures/uploads/sample.xps +0 -0
  43. package/cypress/fixtures/uploads/sample.zip +0 -0
  44. package/cypress/fixtures/uploads/sample1.jpg +0 -0
  45. package/cypress/fixtures/uploads/sample1.mp3 +0 -0
  46. package/cypress/fixtures/uploads/sample1.zip +0 -0
  47. package/cypress/fixtures/uploads/sample10Sec.mp3 +0 -0
  48. package/cypress/fixtures/uploads/sample2.jpg +0 -0
  49. package/cypress/fixtures/uploads/sample2.mp3 +0 -0
  50. package/cypress/fixtures/uploads/sampleVirus.zip +0 -0
  51. package/cypress/pages/audioPlayerPage.js +628 -0
  52. package/cypress/pages/audioResponsePage.js +264 -0
  53. package/cypress/pages/components/additionalSettingsPanel.js +174 -0
  54. package/cypress/pages/components/answerNumerationComponent.js +109 -0
  55. package/cypress/pages/components/autoScoredAdditionalSettings.js +183 -0
  56. package/cypress/pages/components/autoScoredPreviewBase.js +94 -0
  57. package/cypress/pages/components/autoScoredScoringSection.js +195 -0
  58. package/cypress/pages/components/autoScoredScoringSectionMultipleResponsesType.js +268 -0
  59. package/cypress/pages/components/autoScoredSetCorrectAnswerSection.js +291 -0
  60. package/cypress/pages/components/ckEditorToolbar.js +64 -0
  61. package/cypress/pages/components/colorPopupComponent.js +293 -0
  62. package/cypress/pages/components/commonComponents.js +93 -0
  63. package/cypress/pages/components/componentsFlowChart/figFlowChart.png +0 -0
  64. package/cypress/pages/components/createCustomCategoryFlyout.js +138 -0
  65. package/cypress/pages/components/createQuestionBasePage.js +225 -0
  66. package/cypress/pages/components/customizeHighlightPropertiesComponent.js +318 -0
  67. package/cypress/pages/components/dragAndDropResponseOptions.js +738 -0
  68. package/cypress/pages/components/dragAndDropSetCorrectAnswerCheckboxComponents.js +124 -0
  69. package/cypress/pages/components/draggableOptionsContainer.js +857 -0
  70. package/cypress/pages/components/editCategoryFlyout.js +40 -0
  71. package/cypress/pages/components/equationEditorFlyout.js +158 -0
  72. package/cypress/pages/components/essayResponseCommonComponents.js +86 -0
  73. package/cypress/pages/components/figOverImageCommonComponent.js +924 -0
  74. package/cypress/pages/components/fillInTheGapsCommonComponents.js +687 -0
  75. package/cypress/pages/components/fillInTheGapsDropdownCommonComponent.js +442 -0
  76. package/cypress/pages/components/fillInTheGapsTextCommonComponent.js +884 -0
  77. package/cypress/pages/components/gridCommonComponents.js +951 -0
  78. package/cypress/pages/components/index.js +38 -0
  79. package/cypress/pages/components/listSortingAndOrderingBase.js +401 -0
  80. package/cypress/pages/components/maximumRecorderLengthComponent.js +116 -0
  81. package/cypress/pages/components/mcqAdditionalSettingsBase.js +390 -0
  82. package/cypress/pages/components/mcqOptionsComponent.js +263 -0
  83. package/cypress/pages/components/mcqPreviewComponents.js +78 -0
  84. package/cypress/pages/components/mcqQuestionCommonComponents.js +265 -0
  85. package/cypress/pages/components/mcqScoringComponent.js +120 -0
  86. package/cypress/pages/components/mcqSetCorrectAnswerSection.js +143 -0
  87. package/cypress/pages/components/optionsWrapperComponent.js +221 -0
  88. package/cypress/pages/components/playbackControlsBaseComponent.js +163 -0
  89. package/cypress/pages/components/previewScoringAndShowCorrectAnswerComponent.js +90 -0
  90. package/cypress/pages/components/questionInstructionsComponent.js +112 -0
  91. package/cypress/pages/components/scoringSectionBase.js +308 -0
  92. package/cypress/pages/components/setPointsPopupBase.js +79 -0
  93. package/cypress/pages/components/specialAndCustomSpecialCharactersComponent.js +79 -0
  94. package/cypress/pages/components/specialCharactersFlyoutComponent.js +58 -0
  95. package/cypress/pages/components/studentResponseAreaAndLayoutComponent.js +28 -0
  96. package/cypress/pages/components/uploadImageSectionComponent.js +594 -0
  97. package/cypress/pages/createItemPage.js +28 -0
  98. package/cypress/pages/dialogBoxBase.js +111 -0
  99. package/cypress/pages/dragAndDropIntoCategoriesAllOrNothingScoring.js +1161 -0
  100. package/cypress/pages/dragAndDropIntoCategoriesCellsScoring.js +1559 -0
  101. package/cypress/pages/dragAndDropIntoCategoriesPage.js +1556 -0
  102. package/cypress/pages/dragAndDropIntoCategoriesResponseScoring.js +1396 -0
  103. package/cypress/pages/essayResponseBasicPage.js +57 -0
  104. package/cypress/pages/essayResponseMathPage.js +47 -0
  105. package/cypress/pages/essayResponsePage.js +385 -0
  106. package/cypress/pages/feedbackScalePage.js +698 -0
  107. package/cypress/pages/fillInTheGapsDragAndDropPage.js +742 -0
  108. package/cypress/pages/fillInTheGapsDropdownPage.js +99 -0
  109. package/cypress/pages/fillInTheGapsOverImageDropdownPage.js +232 -0
  110. package/cypress/pages/fillInTheGapsOverImageTextPage.js +135 -0
  111. package/cypress/pages/fillInTheGapsScoring.js +5974 -0
  112. package/cypress/pages/fillInTheGapsSetCorrectAnswerSection.js +260 -0
  113. package/cypress/pages/fillInTheGapsTextPage.js +225 -0
  114. package/cypress/pages/highlightImagePage.js +1316 -0
  115. package/cypress/pages/highlightPage.js +870 -0
  116. package/cypress/pages/index.js +30 -0
  117. package/cypress/pages/listMatchingPage.js +1330 -0
  118. package/cypress/pages/listMatchingScoring.js +2635 -0
  119. package/cypress/pages/listOrderingPage.js +751 -0
  120. package/cypress/pages/listSortingPage.js +1201 -0
  121. package/cypress/pages/multipleSelectionGridPage.js +359 -0
  122. package/cypress/pages/multipleSelectionPage.js +88 -0
  123. package/cypress/pages/passagePage.js +426 -0
  124. package/cypress/pages/readingRulerPage.js +302 -0
  125. package/cypress/pages/selectQuestionResourceToolPage.js +64 -0
  126. package/cypress/pages/shortTextResponsePage.js +197 -0
  127. package/cypress/pages/singleSelectionGridPage.js +370 -0
  128. package/cypress/pages/singleSelectionPage.js +65 -0
  129. package/cypress/pages/uploadResponsePage.js +110 -0
  130. package/cypress/pages/videoResponsePage.js +375 -0
  131. package/cypress/support/commands.js +140 -0
  132. package/cypress/support/e2e.js +14 -0
  133. package/cypress/support/helpers/abortEarly.js +19 -0
  134. package/cypress/support/helpers/accessibility.js +34 -0
  135. package/cypress/support/helpers/cypressUtilities.js +64 -0
  136. package/cypress/support/helpers/localStorage.js +13 -0
  137. package/cypress/support/helpers/selectText.js +77 -0
  138. package/cypress/support/helpers/utilities.js +126 -0
  139. package/cypress.config.js +76 -0
  140. package/il.yaml +14 -0
  141. package/language +1 -0
  142. package/package.json +26 -0
@@ -0,0 +1,1556 @@
1
+ import { additionalSettingsPanel, autoScoredAdditionalSettings, autoScoredPreviewBase, autoScoredScoringSection, autoScoredScoringSectionMultipleResponsesType, autoScoredSetCorrectAnswerSection, commonComponents, createQuestionBasePage, dragAndDropResponseOptions, dragAndDropSetCorrectAnswerCheckboxComponents, draggableOptionsContainer, optionsWrapperComponent, previewScoringAndShowCorrectAnswerComponent, questionInstructionsComponent, scoringSectionBase, answerNumerationComponent, studentResponseAndLayoutComponent } from "./components";
2
+ const css = Cypress.env('css');
3
+ const answerResponseOptions = ['Bat', 'Eagle', 'Platypus', 'Ostrich', 'Whale', 'Parrot', 'Flying squirrel', 'Peacock', 'Falcon'];
4
+ const correctTabAnswerArray = [['Bat'], ['Eagle', 'Parrot'], ['Platypus', 'Whale'], ['Ostrich']];
5
+
6
+ const selectors = {
7
+ ...questionInstructionsComponent,
8
+ ...commonComponents,
9
+ ...optionsWrapperComponent,
10
+ ...dragAndDropSetCorrectAnswerCheckboxComponents,
11
+ ...autoScoredSetCorrectAnswerSection,
12
+ ...autoScoredScoringSectionMultipleResponsesType,
13
+ ...scoringSectionBase,
14
+ ...dragAndDropResponseOptions,
15
+ ...additionalSettingsPanel,
16
+ ...autoScoredAdditionalSettings,
17
+ ...previewScoringAndShowCorrectAnswerComponent,
18
+ ...autoScoredPreviewBase,
19
+ ...createQuestionBasePage,
20
+ ...draggableOptionsContainer,
21
+ ...answerNumerationComponent,
22
+ categoryLabel: () => cy.get('[class*="AddCategoriesAndRowsstyles__Label"]').eq(0),
23
+ optionNumeration: () => cy.get('[class*="OptionsComponentstyles__IndexWrapper"]'),
24
+ categoryInputField: () => cy.get('[title*="Enter category"]'),
25
+ //TODO:need to create separate delete buttons for delete category and delete row icon buttons
26
+ deleteButton: () => cy.get('.ngie-icon-btn-cls'),
27
+ addCategoryButton: () => cy.get('.add-option-wrapper-cls button').eq(0),
28
+ addRowButton: () => cy.get('.add-option-wrapper-cls button').eq(1),
29
+ rowLabel: () => cy.get('[class*="AddCategoriesAndRowsstyles__Label"]').eq(1),
30
+ rowInputField: () => cy.get('[title*="Enter row"]'),
31
+ setCorrectAnswerSectionCategoryTitle: () => cy.get('.column-header-cell'),
32
+ setCorrectAnswerSectionRowTitle: () => cy.get('.row-header-cell'),
33
+ setCorrectAnswerSectionCategoryCell: () => cy.get('[class*="DragAndDropMatrixstyles__CellContainer"]'),
34
+ previewTabCategoryTitle: () => cy.get('.classification-response-preview-wrapper .column-header-cell'),
35
+ previewTabRowTitle: () => cy.get('.classification-response-preview-wrapper .row-header-cell'),
36
+ previewTabCategoryCell: () => cy.get('.classification-response-preview-wrapper [class*="DragAndDropMatrixstyles__CellContainer"]'),
37
+ setCorrectAnswerSectionRowContainer: () => cy.get('.row'),
38
+ previewTabRowContainer: () => cy.get('.classification-response-preview-wrapper .row'),
39
+ scoringSubtypeLabel: () => cy.get('#Scoring-Subtype-dropdown-label'),
40
+ scoringSubtypeDropdown: () => cy.get('#Scoring-Subtype-select'),
41
+ scoringSubtypeDropdownListOption: (ariaLabel = null) => {
42
+ if (ariaLabel) {
43
+ return cy.get(`[aria-labelledby*="Scoring-Subtype-dropdown-label"] [role="option"][aria-label*="${ariaLabel}"]`)
44
+ } else {
45
+ return cy.get('[aria-labelledby*="Scoring-Subtype-dropdown-label "] [role="option"]')
46
+ }
47
+ },
48
+ categoryCellNumeration: () => cy.get('[class*="DragAndDropMatrixstyles__CellIndexWrapper"]'),
49
+ correctAnswerCategoryCell: () => cy.get('[class*="DragAndDropMatrixstyles__AnswerCell"]'),
50
+ correctAnswerOption: () => cy.get('[class*="DragAndDropMatrixstyles__AnswerWrapper"]'),
51
+ correctIncorrectAnswerBorder: () => cy.get('.edit-question-preview-wrapper [class*="DragAndDropMatrixstyles__CorrectAnswerBorder"]'),
52
+ correctIncorrectAnswerLabel: () => cy.get('[class*="AnswerStatusText"]'),
53
+ correctAnswerContainer: () => cy.get('[class*="CorrectAnswerWrapper"]'),
54
+ checkCellIcon: () => cy.get('.check-cell-icon'),
55
+ correctIncorrectCellBorder: () => cy.get('[class*="border-top"][class*="border-right"][class*="border-bottom"][class*="border-left"]'),
56
+ correctAnswerLabel: () => cy.get('[class*="DragAndDropMatrixstyles__CorrectAnswerLabel"]'),
57
+ setCorrectAnswerSectionCategoryGrid: () => cy.get('[class*="DragAndDropMatrixstyles__TableWrapper"]'),
58
+ previewTabCategoryGrid: () => cy.get('.edit-question-preview-wrapper [class*="DragAndDropMatrixstyles__TableWrapper"]'),
59
+ //Additional settings
60
+ rowHeadingLabel: () => cy.get('[class*="Classificationstyle__RowResponseWrapper"] .inline-text-property-label').eq(0),
61
+ rowHeadingInputField: () => cy.get('input[aria-label="Row heading"]'),
62
+ rowHeadingSetCorrectAnswerSection: () => cy.get('[class*="DragAndDropMatrixstyles__RowTitleCell"]'),
63
+ rowHeadingPreviewTab: () => cy.get('.edit-question-preview-wrapper [class*="DragAndDropMatrixstyles__RowTitleCell"]'),
64
+ rowTitleWidthLabel: () => cy.get('label[aria-labelledby="Row title width (px)"]'),
65
+ rowTitleWidthInputField: () => cy.get('input[aria-label="Row title width (px)"]'),
66
+ rowMinHeightLabel: () => cy.get('label[aria-labelledby="Row minimum height (px)"]'),
67
+ rowMinHeightInputField: () => cy.get('input[aria-label="Row minimum height (px)"]'),
68
+ maxResponsePerCellLabel: () => cy.get('label[aria-labelledby="Maximum responses per cell"]'),
69
+ maxResponsePerCellInputField: () => cy.get('input[aria-label="Maximum responses per cell"]'),
70
+ optionsWrapper: () => cy.get('[class*="DragAndDropMatrixstyles__DraggableItemWrapper"]'),
71
+ responseOptionPlacementLabel: () => cy.get('#Response-option-placement-dropdown-label'),
72
+ responseOptionPlacementDropdown: () => cy.get('#Response-option-placement-select'),
73
+ responseOptionPlacementDropdownListOption: (ariaLabel = null) => {
74
+ if (ariaLabel) {
75
+ return cy.get(`[aria-labelledby*="Response-option-placement-dropdown-label"] [role="option"][aria-label*="${ariaLabel}"]`);
76
+ } else {
77
+ return cy.get('[aria-labelledby*="Response-option-placement-dropdown-label"] [role="option"]');
78
+ }
79
+ },
80
+ questionPreviewWrapper: () => cy.get('.classification-response-preview-wrapper')
81
+ }
82
+
83
+ const steps = {
84
+ ...questionInstructionsComponent.steps,
85
+ ...commonComponents.steps,
86
+ ...createQuestionBasePage.steps,
87
+ ...autoScoredSetCorrectAnswerSection.steps,
88
+ ...autoScoredScoringSection.steps,
89
+ ...scoringSectionBase.steps,
90
+ ...autoScoredScoringSectionMultipleResponsesType.steps,
91
+ ...dragAndDropResponseOptions.steps,
92
+ ...additionalSettingsPanel.steps,
93
+ ...autoScoredAdditionalSettings.steps,
94
+ ...previewScoringAndShowCorrectAnswerComponent.steps,
95
+ ...autoScoredPreviewBase.steps,
96
+ ...dragAndDropSetCorrectAnswerCheckboxComponents.steps,
97
+ ...optionsWrapperComponent.steps,
98
+ ...draggableOptionsContainer.steps,
99
+ ...answerNumerationComponent.steps,
100
+ ...autoScoredAdditionalSettings.steps,
101
+ //functions related to category
102
+ /**
103
+ * @param {number} count is the number of category input fields present
104
+ * @description verify the count of category input fields present
105
+ */
106
+ verifyCountOfCategoryInputFields: (count) => {
107
+ dragAndDropIntoCategoriesPage.categoryInputField()
108
+ .should('have.length', count);
109
+ },
110
+
111
+ addCategory: () => {
112
+ dragAndDropIntoCategoriesPage.addCategoryButton()
113
+ .click();
114
+ },
115
+
116
+ /**
117
+ * @param {number} inputFieldIndex indicates the category input field index
118
+ * @param {string} textContent indicates the text that is entered and verified in the category input field
119
+ * @description enter text in the category input field
120
+ */
121
+ enterTextInCategoryInputField: (inputFieldIndex, textContent) => {
122
+ dragAndDropIntoCategoriesPage.categoryInputField()
123
+ .eq(inputFieldIndex)
124
+ .clear()
125
+ .type(textContent, { delay: 0 })
126
+ .blur()
127
+ .focus()
128
+ .should('have.text', textContent);
129
+ },
130
+
131
+ /**
132
+ * @param {number} inputFieldIndex indicates the category input field index
133
+ * @description clears text in a category input field
134
+ */
135
+ clearTextInCategoryInputField: (inputFieldIndex) => {
136
+ dragAndDropIntoCategoriesPage.categoryInputField()
137
+ .eq(inputFieldIndex)
138
+ .focus()
139
+ .clear()
140
+ .should('have.text', '')
141
+ .blur();
142
+ },
143
+
144
+ /**
145
+ * @param {number} inputFieldIndex indicates the category input field index
146
+ * @description verify placeholder text of category input field
147
+ */
148
+ verifyPlaceholderTextInCategoryInputField: (inputFieldIndex) => {
149
+ dragAndDropIntoCategoriesPage.categoryInputField()
150
+ .eq(inputFieldIndex)
151
+ .should('have.attr', 'data-cke-editorplaceholder', 'Enter category title');
152
+ },
153
+
154
+ /**
155
+ * @param {number} inputFieldIndex indicates the category input field index
156
+ * @description verify placeholder text does not exist in a category input field
157
+ */
158
+ verifyPlaceholderTextNotExistInCategoryInputField: (inputFieldIndex) => {
159
+ dragAndDropIntoCategoriesPage.categoryInputField()
160
+ .eq(inputFieldIndex)
161
+ .should('not.have.attr', 'data-cke-editorplaceholder');
162
+ },
163
+
164
+ /**
165
+ * @param {number} inputFieldIndex indicates the category input field index
166
+ * @description delete a category input field
167
+ */
168
+ deleteCategoryInputField: (inputFieldIndex) => {
169
+ dragAndDropIntoCategoriesPage.categoryInputField()
170
+ .eq(inputFieldIndex)
171
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
172
+ .find('[aria-label*="Delete category"]')
173
+ .click();
174
+ },
175
+
176
+ /**
177
+ * @param {number} inputFieldIndex indicates the category input field index
178
+ * @description verify the delete category button is visible and enabled
179
+ */
180
+ verifyDeleteCategoryButton: (inputFieldIndex) => {
181
+ dragAndDropIntoCategoriesPage.categoryInputField()
182
+ .eq(inputFieldIndex)
183
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
184
+ .find('[aria-label*="Delete category"]')
185
+ .should('be.visible')
186
+ .and('be.enabled');
187
+ },
188
+
189
+ verifyNumerationOfCategoryInputFields: () => {
190
+ dragAndDropIntoCategoriesPage.categoryInputField()
191
+ .then(elements => {
192
+ for (let inputFieldIndex = 0; inputFieldIndex < elements.length; inputFieldIndex++) {
193
+ cy.wrap(elements)
194
+ .eq(inputFieldIndex)
195
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
196
+ .find('[class*="OptionsComponentstyles__IndexWrapper"]')
197
+ .should('have.text', `${inputFieldIndex + 1}`);
198
+ };
199
+ });
200
+ },
201
+
202
+ /**
203
+ * @param {number} count denotes the number of category titles present
204
+ * @description verify count of category titles in set correct answer section
205
+ */
206
+ verifyCountOfCategoryTitlesInSetCorrectAnswerSection: (count) => {
207
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryTitle()
208
+ .should('have.length', count);
209
+ },
210
+
211
+ /**
212
+ * @param {number} count denotes the number of categories present
213
+ * @description verify count of categories in set correct answer section
214
+ */
215
+ verifyCountOfCategoriesInSetCorrectAnswerSection: (count) => {
216
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
217
+ .should('have.length', count);
218
+ },
219
+
220
+ /**
221
+ * @param {number} categoryIndex denotes the index of the category title
222
+ * @param {string} title denotes the category title
223
+ * @description verify category title in set correct answer section
224
+ */
225
+ verifyCategoryTitleInSetCorrectAnswerSection: (categoryIndex, title) => {
226
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryTitle()
227
+ .eq(categoryIndex)
228
+ .should('have.text', title)
229
+ .and('be.visible');
230
+ },
231
+
232
+ /**
233
+ * @param {number} count denotes the number of categories titles present
234
+ * @description verify count of category titles in preview tab
235
+ */
236
+ verifyCountOfCategoryTitlesInPreviewTab: (count) => {
237
+ dragAndDropIntoCategoriesPage.previewTabCategoryTitle()
238
+ .should('have.length', count);
239
+ },
240
+
241
+ /**
242
+ * @param {number} count denotes the number of categories
243
+ * @description verify count of categories in preview tab
244
+ */
245
+ verifyCountOfCategoriesInPreviewTab: (count) => {
246
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
247
+ .should('have.length', count);
248
+ },
249
+
250
+ /**
251
+ * @param {number} categoryIndex denotes the index of the category title
252
+ * @param {string} title denotes the category title
253
+ * @description verify category title in preview tab
254
+ */
255
+ verifyCategoryTitleInPreviewTab: (categoryIndex, title) => {
256
+ dragAndDropIntoCategoriesPage.previewTabCategoryTitle()
257
+ .eq(categoryIndex)
258
+ .should('have.text', title)
259
+ .and('be.visible');
260
+ },
261
+
262
+ /**
263
+ * @param {number} inputFieldIndex denotes the category input field index
264
+ * @description focus in and out of a category input field
265
+ */
266
+ focusInAndFocusOutOfCategoryInputField: (inputFieldIndex) => {
267
+ dragAndDropIntoCategoriesPage.categoryInputField()
268
+ .eq(inputFieldIndex)
269
+ .click()
270
+ .blur();
271
+ },
272
+
273
+ /**
274
+ * @param {number} inputFieldIndex denotes the category input field index
275
+ * @description verify tooltip of Delete category button
276
+ */
277
+ verifyDeleteCategoryTooltip: (inputFieldIndex) => {
278
+ dragAndDropIntoCategoriesPage.categoryInputField()
279
+ .eq(inputFieldIndex)
280
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
281
+ .find('button')
282
+ .verifyTooltip('Delete category');
283
+ },
284
+
285
+ //functions related to row
286
+
287
+ /**
288
+ * @param {number} count denotes the number of row input fields
289
+ * @description verify count of number of row input fields present
290
+ */
291
+ verifyCountOfRowInputFields: (count) => {
292
+ dragAndDropIntoCategoriesPage.rowInputField()
293
+ .should('have.length', count);
294
+ },
295
+
296
+ /**
297
+ * @param {number} inputFieldIndex is the index of the row input field
298
+ * @description verify the default state of a row input field
299
+ */
300
+ verifyDefaultStateOfRowInputField: (inputFieldIndex) => {
301
+ dragAndDropIntoCategoriesPage.rowInputField()
302
+ .eq(inputFieldIndex)
303
+ .should('have.text', '')
304
+ .and('have.attr', 'data-cke-editorplaceholder', 'Enter row title')
305
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
306
+ .find('[class*="OptionsComponentstyles__IndexWrapper"]')
307
+ .should('have.text', `${inputFieldIndex + 1}`);
308
+ },
309
+
310
+ verifyNumerationOfRowInputFields: () => {
311
+ dragAndDropIntoCategoriesPage.rowInputField()
312
+ .then(elements => {
313
+ for (let inputFieldIndex = 0; inputFieldIndex < elements.length; inputFieldIndex++) {
314
+ cy.wrap(elements)
315
+ .eq(inputFieldIndex)
316
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
317
+ .find('[class*="OptionsComponentstyles__IndexWrapper"]')
318
+ .should('have.text', `${inputFieldIndex + 1}`);
319
+ };
320
+ });
321
+ },
322
+
323
+ /**
324
+ * @param {number} inputFieldIndex is the index of the row input field
325
+ * @description verify if the delete row button is disabled
326
+ */
327
+ verifyDisabledDeleteRowButton: (inputFieldIndex) => {
328
+ dragAndDropIntoCategoriesPage.rowInputField()
329
+ .eq(inputFieldIndex)
330
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
331
+ .find('button')
332
+ .should('be.visible')
333
+ .and('be.disabled');
334
+ },
335
+
336
+ /**
337
+ * @param {number} inputFieldIndex is the index of the row input field
338
+ * @description verify if the delete row button is enabled
339
+ */
340
+ verifyEnabledDeleteRowButton: (inputFieldIndex) => {
341
+ dragAndDropIntoCategoriesPage.rowInputField()
342
+ .eq(inputFieldIndex)
343
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
344
+ .find('button')
345
+ .should('be.visible')
346
+ .and('be.enabled');
347
+ },
348
+
349
+ /**
350
+ * @param {number} inputFieldIndex is the index of the row input field
351
+ * @description verify placeholder text in the row input field
352
+ */
353
+ verifyPlaceholderTextInRowInputField: (inputFieldIndex) => {
354
+ dragAndDropIntoCategoriesPage.rowInputField()
355
+ .eq(inputFieldIndex)
356
+ .should('have.attr', 'data-cke-editorplaceholder', 'Enter row title');
357
+ },
358
+
359
+ /**
360
+ * @param {number} inputFieldIndex is the index of the row input field
361
+ * @description verify placeholder does not exist in the row input field
362
+ */
363
+ verifyPlaceholderTextNotExistInRowInputField: (inputFieldIndex) => {
364
+ dragAndDropIntoCategoriesPage.rowInputField()
365
+ .eq(inputFieldIndex)
366
+ .should('not.have.attr', 'data-cke-editorplaceholder');
367
+ },
368
+
369
+ /**
370
+ * @param {number} inputFieldIndex is the index of the row input field
371
+ * @param {string} textContent text that is entered in the row input field
372
+ * @description enter text and verify in the row input field
373
+ */
374
+ enterTextInRowInputField: (inputFieldIndex, textContent) => {
375
+ dragAndDropIntoCategoriesPage.rowInputField()
376
+ .eq(inputFieldIndex)
377
+ .clear()
378
+ .type(textContent, { delay: 0 })
379
+ .blur()
380
+ .focus()
381
+ .should('have.text', textContent);
382
+ },
383
+
384
+ addRow: () => {
385
+ dragAndDropIntoCategoriesPage.addRowButton()
386
+ .click();
387
+ },
388
+
389
+ /**
390
+ * @param {number} inputFieldIndex is the index of the row input field
391
+ * @description delete a row input field
392
+ */
393
+ deleteRowInputField: (inputFieldIndex) => {
394
+ dragAndDropIntoCategoriesPage.rowInputField()
395
+ .eq(inputFieldIndex)
396
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
397
+ .find('button')
398
+ .click();
399
+ },
400
+
401
+ /**
402
+ * @param {number} count denotes the number of rows
403
+ * @description verify count of rows present in set correct answer section
404
+ */
405
+ verifyCountOfRowsInSetCorrectAnswerSection: (count) => {
406
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionRowContainer()
407
+ .should('have.length', count);
408
+ },
409
+
410
+ /**
411
+ * @param {number} count denotes the number of ro titles
412
+ * @description verify count of row titles present in the set correct answer section
413
+ */
414
+ verifyCountOfRowTitlesInSetCorrectAnswerSection: (count) => {
415
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionRowTitle()
416
+ .should('have.length', count)
417
+ },
418
+
419
+ /**
420
+ * @param {number} count denotes the number of rows present
421
+ * @description verify count of rows in the preview tab
422
+ */
423
+ verifyCountOfRowsInPreviewTab: (count) => {
424
+ dragAndDropIntoCategoriesPage.previewTabRowContainer()
425
+ .should('have.length', count);
426
+ },
427
+
428
+ /**
429
+ * @param {number} count denotes the number of rows titles
430
+ * @description verify count of row titles present in the preview tab
431
+ */
432
+ verifyCountOfRowTitlesInPreviewTab: (count) => {
433
+ dragAndDropIntoCategoriesPage.previewTabRowTitle()
434
+ .should('have.length', count)
435
+ },
436
+
437
+ verifyDisabledRowInputFieldTooltip: () => {
438
+ dragAndDropIntoCategoriesPage.rowInputField()
439
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
440
+ .within(() => {
441
+ dragAndDropIntoCategoriesPage.deleteButton()
442
+ .trigger('mouseover', { force: true });
443
+ });
444
+ commonComponents.tooltipText()
445
+ .verifyInnerText('Minimum one row is required');
446
+ dragAndDropIntoCategoriesPage.rowInputField()
447
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
448
+ .within(() => {
449
+ dragAndDropIntoCategoriesPage.deleteButton()
450
+ .trigger('mouseout', { force: true });
451
+ });
452
+ commonComponents.tooltipText()
453
+ .should('not.exist');
454
+ },
455
+
456
+ /**
457
+ * @param {number} inputFieldIndex is the index of the row input field
458
+ * @description focus in and out of a row input field
459
+ */
460
+ focusInAndFocusOutOfRowInputField: (inputFieldIndex) => {
461
+ dragAndDropIntoCategoriesPage.rowInputField()
462
+ .eq(inputFieldIndex)
463
+ .click()
464
+ .blur();
465
+ },
466
+
467
+ /**
468
+ * @param {number} inputFieldIndex is the index of the row input field
469
+ * @description verify tooltip of enabled 'Delete row' button
470
+ */
471
+ verifyEnabledDeleteRowInputFieldTooltip: (inputFieldIndex) => {
472
+ dragAndDropIntoCategoriesPage.rowInputField()
473
+ .eq(inputFieldIndex)
474
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
475
+ .within(() => {
476
+ dragAndDropIntoCategoriesPage.deleteButton()
477
+ .trigger('mouseover');
478
+ });
479
+ commonComponents.tooltipText()
480
+ .verifyInnerText('Delete row');
481
+ dragAndDropIntoCategoriesPage.rowInputField()
482
+ .eq(inputFieldIndex)
483
+ .parents('[class*="OptionsComponentstyles__TitleWrapper"]')
484
+ .within(() => {
485
+ dragAndDropIntoCategoriesPage.deleteButton()
486
+ .trigger('mouseout');
487
+ });
488
+ commonComponents.tooltipText()
489
+ .should('not.exist');
490
+ },
491
+
492
+ /**
493
+ * @param {number} rowIndex is the index of the row title
494
+ * @param {string} title is the text of the row title
495
+ * @description verify row title in set correct answer section
496
+ */
497
+ verifyRowTitleInSetCorrectAnswerSection: (rowIndex, title) => {
498
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionRowTitle()
499
+ .eq(rowIndex)
500
+ .should('have.text', title)
501
+ .and('be.visible');
502
+ },
503
+
504
+ /**
505
+ * @param {number} rowIndex is the index of the row title
506
+ * @param {string} title is the text of the row title
507
+ * @description verify row title in preview tab
508
+ */
509
+ verifyRowTitleInPreviewTab: (rowIndex, title) => {
510
+ dragAndDropIntoCategoriesPage.previewTabRowTitle()
511
+ .eq(rowIndex)
512
+ .should('have.text', title)
513
+ .and('be.visible');
514
+ },
515
+
516
+ /**
517
+ * @param {string} optionName denotes the text content of the draggable option
518
+ * @param {number} categoryIndex denotes the category in which draggable option is being dropped
519
+ * @description click and drop a draggable option into a category in the set correct answer section
520
+ */
521
+ clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection: (optionName, categoryIndex) => {
522
+ draggableOptionsContainer.setCorrectAnswerDraggableOptionsWrapper('drag and drop into categories')
523
+ .within(() => {
524
+ draggableOptionsContainer.draggableOption()
525
+ .contains(optionName)
526
+ .click();
527
+ });
528
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
529
+ .eq(categoryIndex)
530
+ .click({ force: true });
531
+ },
532
+
533
+ /**
534
+ * @param {string} optionName denotes the text content of the draggable option
535
+ * @param {number} categoryIndex denotes the category in which draggable option is being dropped
536
+ * @description click and drop a draggable option into a category in the preview tab
537
+ */
538
+ clickAndDropDraggableOptionInCategoryCellOfPreviewTab: (optionName, categoryIndex) => {
539
+ draggableOptionsContainer.previewTabDraggableOptionsWrapper('drag and drop into categories')
540
+ .within(() => {
541
+ draggableOptionsContainer.draggableOption()
542
+ .contains(optionName)
543
+ .click();
544
+ });
545
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
546
+ .eq(categoryIndex)
547
+ .click({ force: true });
548
+ },
549
+
550
+ /**
551
+ * @param {number} categoryIndex index of the category cell in set correct answer section
552
+ * @param {string[]} responseArray array of options set as correct responses in a category cell
553
+ */
554
+ verifyDraggableOptionInCategoryCellOfSetCorrectAnswerSection: (categoryIndex, responseArray) => {
555
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
556
+ .eq(categoryIndex)
557
+ .within(() => {
558
+ responseArray.forEach((response, count) => {
559
+ draggableOptionsContainer.draggableOption()
560
+ .eq(count)
561
+ .verifyInnerText(response);
562
+ });
563
+ });
564
+ },
565
+
566
+ clickOnScoringSubtypeDropdown: () => {
567
+ dragAndDropIntoCategoriesPage.scoringSubtypeDropdown()
568
+ .scrollIntoView()
569
+ .click();
570
+ },
571
+
572
+ verifyListOptionsOfScoringSubtypeDropdown: () => {
573
+ dragAndDropIntoCategoriesPage.scoringSubtypeDropdownListOption()
574
+ .should('be.visible');
575
+ let dropdownOptions = ['All or nothing', 'Total score divided between each correct response', 'Partial - score for each correct response', 'Total score divided between each cell', 'Partial - score for each cell'];
576
+ dropdownOptions.forEach((option, count) => {
577
+ dragAndDropIntoCategoriesPage.scoringSubtypeDropdownListOption()
578
+ .eq(count)
579
+ .verifyInnerText(option);
580
+ });
581
+ //Note: Clicking on an option to close the dropdown
582
+ cy.get('body')
583
+ .click();
584
+ commonComponents.dropdownList()
585
+ .should('not.exist');
586
+ },
587
+
588
+ /**
589
+ * @param {string} optionName option from the scoring subtype dropdown. Should be one of 'All or nothing', 'Total score divided between each correct response', 'Partial - score for each correct response', 'Total score divided between each cell', 'Partial - score for each cell'
590
+ * @description select an option from the scoring subtype dropdown
591
+ */
592
+ selectScoringSubTypeDropdownOption: (optionName) => {
593
+ dragAndDropIntoCategoriesPage.scoringSubtypeDropdownListOption(optionName)
594
+ .click();
595
+ },
596
+
597
+ /**
598
+ * @param {string[]} optionsArray the array of options present in the category container
599
+ * @param {number} points allocated points present in the points input field
600
+ * @description verify the correct answer options and points
601
+ */
602
+ verifyCorrectAnswerOptionsAndPointsInSetCorrectAnswerSection: (optionsArray, points) => {
603
+ optionsArray.forEach((responseText, count) => {
604
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
605
+ .eq(count)
606
+ .verifyInnerText(responseText);
607
+ });
608
+ scoringSectionBase.pointsInputField()
609
+ .should('have.value', points);
610
+ },
611
+
612
+ setQuestion: () => {
613
+ questionInstructionsComponent.questionInstructionsInputField()
614
+ .type('Fill the categories with the right answer.', { delay: 0 })
615
+ .blur();
616
+ dragAndDropIntoCategoriesPage.steps.enterTextInCategoryInputField(0, 'Mammal');
617
+ dragAndDropIntoCategoriesPage.steps.enterTextInCategoryInputField(1, 'Not mammal');
618
+ dragAndDropIntoCategoriesPage.addRowButton()
619
+ .click()
620
+ dragAndDropIntoCategoriesPage.steps.enterTextInRowInputField(0, 'Can fly');
621
+ dragAndDropIntoCategoriesPage.steps.enterTextInRowInputField(1, 'Cannot fly');
622
+ const numberOfClicks = 7;
623
+ const addOptionButton = optionsWrapperComponent.addOptionButton();
624
+ for (let i = 0; i < numberOfClicks; i++) {
625
+ addOptionButton.click();
626
+ };
627
+ dragAndDropResponseOptions.steps.addInputToOptionsForDragAndDropFields(answerResponseOptions);
628
+ },
629
+
630
+ /**
631
+ * Verifies the numeration of category cells in the question preview.
632
+ * @param {Array<string>} numerationArray - An array of expected numeration values for category cells.
633
+ * @returns {void}
634
+ */
635
+ verifyNumerationOfCategoryCellsInQuestionPreview: (numerationArray) => {
636
+ numerationArray.forEach((option, count) => {
637
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
638
+ .eq(count)
639
+ .within(() => {
640
+ dragAndDropIntoCategoriesPage.categoryCellNumeration()
641
+ .should('have.text', option)
642
+ .and('be.visible');
643
+ });
644
+ });
645
+ },
646
+
647
+ /**
648
+ * @param {string[][]} correctAnswerArray array of correct answer option of a category
649
+ * @param {number[]} categoryCellIndexArray numeration of the category cells of the correct answer options
650
+ * @description verify the correct answer options of a category and numeration of the category cell
651
+ */
652
+ verifyCorrectAnswerResponsesInCorrectAnswerSectionAndCount: (correctAnswerArray, categoryCellIndexArray) => {
653
+ dragAndDropIntoCategoriesPage.steps.verifyCountOfCorrectAnswerCategoryCells(correctAnswerArray.length);
654
+ correctAnswerArray.forEach((correctAnswer, index) => {
655
+ dragAndDropIntoCategoriesPage.correctAnswerCategoryCell()
656
+ .eq(index)
657
+ .within(() => {
658
+ dragAndDropIntoCategoriesPage.categoryCellNumeration()
659
+ .should('have.text', categoryCellIndexArray[index]);
660
+ correctAnswer.forEach((answerOption, optionIndex) => {
661
+ dragAndDropIntoCategoriesPage.correctAnswerOption()
662
+ .eq(optionIndex)
663
+ .should('have.text', answerOption);
664
+ });
665
+ });
666
+ });
667
+ },
668
+
669
+ /**
670
+ * @param {number} categoryCellCount count of correct answer category cells
671
+ * @description verify the count of correct answer category cells present in the correct answer section
672
+ */
673
+ verifyCountOfCorrectAnswerCategoryCells: (categoryCellCount) => {
674
+ dragAndDropIntoCategoriesPage.correctAnswerCategoryCell()
675
+ .should('have.length', categoryCellCount)
676
+ },
677
+
678
+ verifyCorrectAttemptBorder: () => {
679
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerBorder()
680
+ .should('have.css', 'border-width', '1px')
681
+ .and('have.css', 'border-style', 'solid')
682
+ .and('have.css', 'border-color', `${css.color.correctAnswer}`);
683
+ },
684
+
685
+ verifyIncorrectAttemptBorder: () => {
686
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerBorder()
687
+ .should('have.css', 'border-width', '1px')
688
+ .and('have.css', 'border-style', 'solid')
689
+ .and('have.css', 'border-color', `${css.color.incorrectAnswer}`);
690
+ },
691
+
692
+ verifyCorrectIncorrectBorderNotVisible: () => {
693
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerBorder()
694
+ .should('have.css', 'border-style', 'none');
695
+ },
696
+
697
+ /**
698
+ * @param {number} optionIndex index of the response option in category cell
699
+ * @description verify the incorrect cross-mark icon against the incorrect response
700
+ */
701
+ verifyIncorrectOptionCrossmarkIcon: (optionIndex) => {
702
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
703
+ .within(() => {
704
+ dragAndDropIntoCategoriesPage.optionsWrapper()
705
+ .eq(optionIndex)
706
+ .find('.tick-icon-wrapper')
707
+ .should('have.class', 'icon-incorrect')
708
+ .and('be.visible');
709
+ })
710
+ },
711
+
712
+ /**
713
+ * @param {number} optionIndex index of the response option in category cell
714
+ * @description verify the correct cross-mark icon against the correct response
715
+ */
716
+ verifyCorrectOptionCheckmarkIcon: (optionIndex) => {
717
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
718
+ .within(() => {
719
+ dragAndDropIntoCategoriesPage.optionsWrapper()
720
+ .eq(optionIndex)
721
+ .find('.tick-icon-wrapper')
722
+ .should('have.class', 'icon-correct')
723
+ .and('be.visible');
724
+ })
725
+ },
726
+
727
+ /**
728
+ * @param {string} labelText correct/incorrect label
729
+ * @description verify the correct/incorrect label
730
+ */
731
+ verifyCorrectIncorrectAnswerLabel: (labelText) => {
732
+ let labelIconText = labelText.toLowerCase();
733
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerLabel()
734
+ .should('be.visible')
735
+ .verifyInnerText(`${labelText} answer`)
736
+ .parents('[class*="AnswerStatusWrapper"]')
737
+ .find('[class*="AnswerStatusIcon"]')
738
+ .should('be.visible')
739
+ .should('have.class', `icon-${labelIconText}`);
740
+ },
741
+
742
+ verifyCorrectAnswerSectionNotVisible: () => {
743
+ dragAndDropIntoCategoriesPage.correctAnswerContainer()
744
+ .should('not.visible');
745
+ },
746
+
747
+ verifyQuestionPreviewStateWhenShowCorrectAnswerIsUnchecked: () => {
748
+ cy.log('After deselecting Show correct answer checkbox, the question preview should return to the previous state');
749
+ previewScoringAndShowCorrectAnswerComponent.showCorrectAnswerCheckbox()
750
+ .click()
751
+ .should('not.be.checked');
752
+ autoScoredPreviewBase.correctIcon()
753
+ .should('not.exist');
754
+ autoScoredPreviewBase.incorrectIcon()
755
+ .should('not.exist');
756
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerLabel()
757
+ .should('not.exist');
758
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectIncorrectBorderNotVisible();
759
+ },
760
+
761
+ resetQuestionPreview: () => {
762
+ cy.log('Switching to edit tab and back to preview tab to reset the question preview')
763
+ dragAndDropIntoCategoriesPage.steps.switchToEditTab();
764
+ dragAndDropIntoCategoriesPage.steps.switchToPreviewTab();
765
+ },
766
+
767
+ verifyCorrectAnswersLabel: () => {
768
+ dragAndDropIntoCategoriesPage.correctAnswerContainer()
769
+ .should('contain', 'Correct answers:')
770
+ .and('be.visible');
771
+ },
772
+
773
+ verifyCorrectIncorrectCellBorderNotExists: () => {
774
+ dragAndDropIntoCategoriesPage.correctIncorrectCellBorder()
775
+ .should('not.exist');
776
+ dragAndDropIntoCategoriesPage.checkCellIcon()
777
+ .should('not.exist');
778
+ },
779
+
780
+ /**
781
+ * @param {string} optionName denotes the text content of the draggable option
782
+ * @description click and drop a draggable option into the response container in the set correct answer section
783
+ */
784
+ clickAndDropDraggableOptionInResponseContainerOfSetCorrectAnswerSection: (optionName) => {
785
+ draggableOptionsContainer.draggableOption()
786
+ .contains(optionName)
787
+ .click();
788
+ draggableOptionsContainer.setCorrectAnswerDraggableOptionsWrapper('drag and drop into categories')
789
+ .find('[class*="DragAndDropMatrixstyles__DroppableWrapper"]')
790
+ .click({ force: true });
791
+ },
792
+
793
+ /**
794
+ * @param {string} optionName denotes the text content of the draggable option
795
+ * @description click and drop a draggable option into the grouped response container in the set correct answer section
796
+ */
797
+ clickAndDropDraggableOptionInResponseContainerOfPreviewTab: (optionName) => {
798
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
799
+ .within(() => {
800
+ draggableOptionsContainer.draggableOption()
801
+ .contains(optionName)
802
+ .click();
803
+ });
804
+ draggableOptionsContainer.previewTabDraggableOptionsWrapper('drag and drop into categories')
805
+ .find('[class*="DragAndDropMatrixstyles__DroppableWrapper"]')
806
+ .click({ force: true });
807
+ },
808
+
809
+ /**
810
+ * @param {string} optionName denotes the text content of the draggable option
811
+ * @description click and drop a draggable option into the grouped response container in the set correct answer section
812
+ */
813
+ clickAndDropDraggableOptionInGroupedResponseContainerOfSetCorrectAnswerSection: (optionName) => {
814
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryGrid()
815
+ .within(() => {
816
+ draggableOptionsContainer.draggableOption()
817
+ .contains(optionName)
818
+ .click();
819
+ });
820
+ draggableOptionsContainer.setCorrectAnswerDraggableOptionsWrapper('drag and drop into categories')
821
+ .find('.item-list')
822
+ .eq(0)
823
+ .click({ force: true });
824
+ },
825
+
826
+ /**
827
+ * @param {string} optionName denotes the text content of the draggable option
828
+ * @description click and drop a draggable option into the grouped response container in the set correct answer section
829
+ */
830
+ clickAndDropDraggableOptionInGroupedResponseContainerOfPreviewTab: (optionName) => {
831
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
832
+ .within(() => {
833
+ draggableOptionsContainer.draggableOption()
834
+ .contains(optionName)
835
+ .click();
836
+ });
837
+ draggableOptionsContainer.previewTabDraggableOptionsWrapper('drag and drop into categories')
838
+ .find('.item-list')
839
+ .eq(0)
840
+ .click({ force: true });
841
+ },
842
+
843
+ verifyCorrectCellCheckmarkIcon: (categoryCellIndexArray) => {
844
+ categoryCellIndexArray.forEach((cellIndex) => {
845
+ dragAndDropIntoCategoriesPage.correctIncorrectCellBorder()
846
+ .eq(cellIndex)
847
+ .within(() => {
848
+ dragAndDropIntoCategoriesPage.checkCellIcon()
849
+ .should('have.class', 'icon-correct')
850
+ .and('be.visible');
851
+ });
852
+ });
853
+ },
854
+
855
+ verifyIncorrectCellCrossmarkIcon: (categoryCellIndexArray) => {
856
+ categoryCellIndexArray.forEach((cellIndex) => {
857
+ dragAndDropIntoCategoriesPage.correctIncorrectCellBorder()
858
+ .eq(cellIndex)
859
+ .within(() => {
860
+ dragAndDropIntoCategoriesPage.checkCellIcon()
861
+ .should('have.class', 'icon-incorrect')
862
+ .and('be.visible');
863
+ });
864
+ });
865
+ },
866
+
867
+ verifyOptionsErrorMessageIsDisplayed: (index) => {
868
+ optionsWrapperComponent.optionsSectionWrapper()
869
+ .within(() => {
870
+ optionsWrapperComponent.optionWrapper()
871
+ .eq(index)
872
+ .within(() => {
873
+ commonComponents.errorMessage()
874
+ .should('have.text', 'Error: Option is required.');
875
+ });
876
+ });
877
+ },
878
+
879
+ verifyOptionsErrorMessageIsNotDisplayed: (index) => {
880
+ optionsWrapperComponent.optionsSectionWrapper()
881
+ .within(() => {
882
+ optionsWrapperComponent.optionWrapper()
883
+ .eq(index)
884
+ .within(() => {
885
+ commonComponents.errorMessage()
886
+ .should('not.exist');
887
+ });
888
+ });
889
+ },
890
+
891
+ setCorrectTabAnswerOptions: () => {
892
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Bat', 0);
893
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Eagle', 1);
894
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Parrot', 1);
895
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Platypus', 2);
896
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Whale', 2);
897
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfSetCorrectAnswerSection('Ostrich', 3);
898
+ },
899
+
900
+ verifyEmptyStateOfCategoryCellInSetCorrectAnswerSection: (cellIndex) => {
901
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
902
+ .eq(cellIndex)
903
+ .should('have.text', '');
904
+ },
905
+
906
+ verifyEmptyStateOfCategoryCellInPreviewTab: (cellIndex) => {
907
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
908
+ .eq(cellIndex)
909
+ .should('have.text', '');
910
+ },
911
+
912
+ /**
913
+ * @param {number} categoryIndex index of the category cell in preview tab
914
+ * @param {string[]} responseArray array of options set as correct responses in a category cell
915
+ */
916
+ verifyDraggableOptionInCategoryCellOfPreviewTab: (categoryIndex, responseArray) => {
917
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
918
+ .eq(categoryIndex)
919
+ .within(() => {
920
+ responseArray.forEach((response, count) => {
921
+ draggableOptionsContainer.draggableOption()
922
+ .eq(count)
923
+ .verifyInnerText(response);
924
+ });
925
+ });
926
+ },
927
+
928
+ setQuestionForGroupedResponseOptions: () => {
929
+ let animals = [['Bat', 'Platypus', 'Panda', 'Zebra'],
930
+ ['Peacock', 'Falcon', 'Eagle', 'Tiger'],
931
+ ['Parrot', 'Lion', 'Whale', 'Elephant'],
932
+ ['Giraffe', 'Kangaroo', 'Ostrich', 'Flying squirrel']
933
+ ];
934
+ let groupTitles = ['Group A', 'Group B', 'Group C', 'Group D'];
935
+ questionInstructionsComponent.questionInstructionsInputField()
936
+ .type('Fill the categories with the right answer.', { delay: 0 })
937
+ .blur();
938
+ dragAndDropIntoCategoriesPage.steps.enterTextInCategoryInputField(0, 'Mammal');
939
+ dragAndDropIntoCategoriesPage.steps.enterTextInCategoryInputField(1, 'Not mammal');
940
+ dragAndDropIntoCategoriesPage.addRowButton()
941
+ .click()
942
+ dragAndDropIntoCategoriesPage.steps.enterTextInRowInputField(0, 'Can fly');
943
+ dragAndDropIntoCategoriesPage.steps.enterTextInRowInputField(1, 'Cannot fly');
944
+ dragAndDropResponseOptions.steps.selectResponseOptionsLayout('Grouped')
945
+ dragAndDropResponseOptions.steps.addGroupTitle(0, groupTitles[0]);
946
+ optionsWrapperComponent.addOptionButton()
947
+ .click();
948
+ optionsWrapperComponent.addOptionButton()
949
+ .click();
950
+ dragAndDropResponseOptions.steps.addInputToOptionsForGroupedResponseLayout(0, animals[0]);
951
+ dragAndDropResponseOptions.steps.addGroupWithTitleAndOptionsInResponseOptionsSection(1, groupTitles[1], animals[1]);
952
+ dragAndDropResponseOptions.steps.addGroupWithTitleAndOptionsInResponseOptionsSection(2, groupTitles[2], animals[2]);
953
+ dragAndDropResponseOptions.steps.addGroupWithTitleAndOptionsInResponseOptionsSection(3, groupTitles[3], animals[3]);
954
+ },
955
+
956
+ verifyInactiveStateOfAllCategoryCellsInSetCorrectAnswerSection: () => {
957
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryGrid()
958
+ .should('not.have.class', 'active-area-on-tap');
959
+ },
960
+
961
+ verifyActiveStateOfAllCategoryCellsInSetCorrectAnswerSection: () => {
962
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryGrid()
963
+ .should('have.class', 'active-area-on-tap');
964
+ },
965
+
966
+ verifyInactiveStateOfAllCategoryCellsInPreviewTab: () => {
967
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
968
+ .should('not.have.class', 'active-area-on-tap');
969
+ },
970
+
971
+ verifyActiveStateOfAllCategoryCellsInPreviewTab: () => {
972
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
973
+ .should('have.class', 'active-area-on-tap');
974
+ },
975
+
976
+ /**
977
+ * @param {number} responseAreaIndex Index of the stem response area in set correct answer section
978
+ * @description Verify drag handle is not visible in filled category cell in set correct answer section
979
+ */
980
+ verifyDragHandleNotVisibleInFilledCategoryCellOfSetCorrectAnswerSection: (responseAreaIndex) => {
981
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
982
+ .eq(responseAreaIndex)
983
+ .within(() => {
984
+ draggableOptionsContainer.draggableOptionDragIcon()
985
+ .should('not.be.visible');
986
+ });
987
+ },
988
+
989
+ /**
990
+ * @param {number} responseAreaIndex Index of the stem response area in set correct answer section
991
+ * @description Verify drag handle is not visible in filled category cell in preview tab
992
+ */
993
+ verifyDragHandleNotVisibleInFilledCategoryCellOfPreviewTab: (responseAreaIndex) => {
994
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
995
+ .eq(responseAreaIndex)
996
+ .within(() => {
997
+ draggableOptionsContainer.draggableOptionDragIcon()
998
+ .should('not.be.visible');
999
+ });
1000
+ },
1001
+
1002
+ /**
1003
+ * @param {string} optionName denotes the text content of the draggable option
1004
+ * @description click on a draggable option present in the category cell of set correct answer section
1005
+ */
1006
+ clickOnDraggableOptionInCategoryCellOfSetCorrectAnswerSection: (optionName) => {
1007
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryGrid()
1008
+ .within(() => {
1009
+ draggableOptionsContainer.draggableOption()
1010
+ .contains(optionName)
1011
+ .click();
1012
+ });
1013
+ },
1014
+
1015
+ verifyPleaseSetACorrectAnswerErrorMessage: () => {
1016
+ commonComponents.errorMessage()
1017
+ .verifyInnerText('Error: Please set a correct answer.')
1018
+ .should('be.visible');
1019
+ },
1020
+
1021
+ clickOnCategoryCellInCategoryCellOfSetCorrectAnswerSection: (categoryIndex) => {
1022
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
1023
+ .eq(categoryIndex)
1024
+ .click({ force: true });
1025
+ },
1026
+
1027
+ clickOnCategoryCellInCategoryCellOfPreviewTab: (categoryIndex) => {
1028
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
1029
+ .eq(categoryIndex)
1030
+ .click({ force: true });
1031
+ },
1032
+
1033
+ /**
1034
+ * @param {string} optionName denotes the text content of the draggable option
1035
+ * @description click on a draggable option present in the category cell of preview tab
1036
+ */
1037
+ clickOnDraggableOptionInCategoryCellOfPreviewTab: (optionName) => {
1038
+ dragAndDropIntoCategoriesPage.previewTabCategoryGrid()
1039
+ .within(() => {
1040
+ draggableOptionsContainer.draggableOption()
1041
+ .contains(optionName)
1042
+ .click();
1043
+ });
1044
+ },
1045
+
1046
+ /**
1047
+ * Verifies the numeration of correct answer container category cells.
1048
+ * @param {Array<string>} categoryCellIndexArray - An array of expected numeration values for category cells.
1049
+ * @returns {void}
1050
+ */
1051
+ verifyCorrectAnswerContainerNumeration: (categoryCellIndexArray) => {
1052
+ categoryCellIndexArray.forEach((categoryCellNumeration, index) => {
1053
+ dragAndDropIntoCategoriesPage.correctAnswerCategoryCell()
1054
+ .eq(index)
1055
+ .within(() => {
1056
+ dragAndDropIntoCategoriesPage.categoryCellNumeration()
1057
+ .should('have.text', `${categoryCellNumeration}`);
1058
+ });
1059
+ });
1060
+ },
1061
+
1062
+ /**
1063
+ * Enters text into the row title width input field.
1064
+ * @param {string} text - The text to be entered into the row input field.
1065
+ * @returns {void}
1066
+ */
1067
+ enterTextInRowTitleWidthInputField: (text) => {
1068
+ dragAndDropIntoCategoriesPage.rowTitleWidthInputField()
1069
+ .type(text, { delay: 0 })
1070
+ .blur();
1071
+ },
1072
+
1073
+ clearTextInRowTitleWidthInputField: () => {
1074
+ dragAndDropIntoCategoriesPage.rowTitleWidthInputField()
1075
+ .clear();
1076
+ },
1077
+
1078
+ /**
1079
+ * Verifies the value of the row title width input field.
1080
+ * @param {string} width - The expected width value to compare against.
1081
+ * @returns {void}
1082
+ */
1083
+ verifyRowTitleWidthInputFieldValue: (width) => {
1084
+ dragAndDropIntoCategoriesPage.rowTitleWidthInputField()
1085
+ .should('have.attr', 'value', width)
1086
+ },
1087
+
1088
+ /**
1089
+ * Enters text into the row minimum height input field.
1090
+ * @param {string} text - The text to be entered into the row minimum height input field.
1091
+ * @returns {void}
1092
+ */
1093
+ enterTextInRowMinHeightInputField: (text) => {
1094
+ dragAndDropIntoCategoriesPage.rowMinHeightInputField()
1095
+ .type(text, { delay: 0 })
1096
+ .blur();
1097
+ },
1098
+
1099
+ clearTextInRowMinHeightInputField: () => {
1100
+ dragAndDropIntoCategoriesPage.rowMinHeightInputField()
1101
+ .clear();
1102
+ },
1103
+
1104
+ /**
1105
+ * Verifies the value of the row minimum height input field.
1106
+ * @param {string} value - The expected row minimum height value to compare against.
1107
+ * @returns {void}
1108
+ */
1109
+ verifyRowMinHeightInputFieldValue: (value) => {
1110
+ dragAndDropIntoCategoriesPage.rowMinHeightInputField()
1111
+ .should('have.attr', 'value', value)
1112
+ },
1113
+
1114
+ /**
1115
+ * Enters text into the row heading input field.
1116
+ * @param {string} text - The text to be entered into the row heading input field.
1117
+ * @returns {void}
1118
+ */
1119
+ enterTextInRowHeadingInputField: (text) => {
1120
+ dragAndDropIntoCategoriesPage.rowHeadingInputField()
1121
+ .type(text, { delay: 0 })
1122
+ .blur();
1123
+ },
1124
+
1125
+ clearTextInRowHeadingInputField: () => {
1126
+ dragAndDropIntoCategoriesPage.rowHeadingInputField()
1127
+ .clear();
1128
+ },
1129
+
1130
+ /**
1131
+ * Verifies the value of the row heading input field.
1132
+ * @param {string} value - The expected row heading value to compare against.
1133
+ * @returns {void}
1134
+ */
1135
+ verifyRowHeadingInputFieldValue: (value) => {
1136
+ dragAndDropIntoCategoriesPage.rowHeadingInputField()
1137
+ .should('have.attr', 'value', value)
1138
+ },
1139
+
1140
+ /**
1141
+ * Verifies the width of the row title in the 'Set correct answer' section.
1142
+ * @param {number} expectedWidth - The expected width value to compare against.
1143
+ * @returns {void}
1144
+ */
1145
+ verifyRowTitleWidthSetCorrectAnswerSection: (expectedWidth) => {
1146
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionRowTitle()
1147
+ .parents('[class*="RowHeaderCellContainer"]')
1148
+ .should(($element) => {
1149
+ const width = $element.width();
1150
+ expect(width).to.be.equal(expectedWidth);
1151
+ });
1152
+ },
1153
+
1154
+ /**
1155
+ * Verifies the width of the row title in the 'Preview tab'.
1156
+ * @param {number} expectedWidth - The expected width value to compare against.
1157
+ * @returns {void}
1158
+ */
1159
+ verifyRowTitleWidthPreviewTab: (expectedWidth) => {
1160
+ dragAndDropIntoCategoriesPage.previewTabRowTitle()
1161
+ .parents('[class*="RowHeaderCellContainer"]')
1162
+ .should(($element) => {
1163
+ const width = $element.width();
1164
+ expect(width).to.be.equal(expectedWidth);
1165
+ });
1166
+ },
1167
+
1168
+ /**
1169
+ * Verifies the minimum height of a row in the 'Set correct answer' section.
1170
+ * @param {number} expectedMinHeight - The expected minimum height value to compare against.
1171
+ * @returns {void}
1172
+ */
1173
+ verifyRowMinHeightSetCorrectAnswerSection: (expectedMinHeight) => {
1174
+ dragAndDropIntoCategoriesPage.setCorrectAnswerSectionCategoryCell()
1175
+ .parents('[class*="RowContainer"]')
1176
+ .should(($element) => {
1177
+ const minHeight = parseFloat($element.css('min-height'));
1178
+ expect(minHeight).to.be.equal(expectedMinHeight);
1179
+ });
1180
+ },
1181
+
1182
+ /**
1183
+ * Verifies the minimum height of a row in the 'Preview tab'.
1184
+ * @param {number} expectedMinHeight - The expected minimum height value to compare against.
1185
+ * @returns {void}
1186
+ */
1187
+ verifyRowMinHeightPreviewTab: (expectedMinHeight) => {
1188
+ dragAndDropIntoCategoriesPage.previewTabCategoryCell()
1189
+ .parents('[class*="RowContainer"]')
1190
+ .should(($element) => {
1191
+ const minHeight = parseFloat($element.css('min-height'));
1192
+ expect(minHeight).to.be.equal(expectedMinHeight);
1193
+ });
1194
+ },
1195
+
1196
+ /**
1197
+ * Sets the maximum response value per cell in max response per cell input field
1198
+ * @param {string} value - The value to set as the maximum response per cell.
1199
+ * @returns {void}
1200
+ */
1201
+ setMaxResponsePerCell: (value) => {
1202
+ dragAndDropIntoCategoriesPage.maxResponsePerCellInputField()
1203
+ .type(value, { delay: 0 })
1204
+ .blur();
1205
+ },
1206
+
1207
+ clearMaxResponsePerCellInputField: () => {
1208
+ dragAndDropIntoCategoriesPage.maxResponsePerCellInputField()
1209
+ .clear();
1210
+ },
1211
+
1212
+ /**
1213
+ * Verifies the value of the maximum response per cell input field.
1214
+ * @param {string} value - The expected value to compare against.
1215
+ * @returns {void}
1216
+ */
1217
+ verifyMaxResponsePerCellInputFieldValue: (value) => {
1218
+ dragAndDropIntoCategoriesPage.maxResponsePerCellInputField()
1219
+ .should('have.attr', 'value', value)
1220
+ },
1221
+
1222
+ clickOnResponseOptionPlacementDropdown: () => {
1223
+ dragAndDropIntoCategoriesPage.responseOptionPlacementDropdown()
1224
+ .click();
1225
+ },
1226
+
1227
+ /**
1228
+ * Selects an option from the response option placement dropdown list.
1229
+ * @param {string} dropdownOption - The option to select from the dropdown list ('Bottom', 'Top', 'Left', or 'Right')..
1230
+ * @returns {void}
1231
+ */
1232
+ selectResponseOptionPlacementDropdownOption: (dropdownOption) => {
1233
+ dragAndDropIntoCategoriesPage.responseOptionPlacementDropdownListOption(dropdownOption)
1234
+ .click();
1235
+ },
1236
+
1237
+ verifyResponseOptionPlacementDropdownOptions: () => {
1238
+ let dropdownOptions = ['Top', 'Bottom', 'Left', 'Right'];
1239
+ dragAndDropIntoCategoriesPage.responseOptionPlacementDropdownListOption()
1240
+ .each(($el, index) => {
1241
+ cy.wrap($el)
1242
+ .should('have.text', dropdownOptions[index]);
1243
+ });
1244
+ },
1245
+
1246
+ /**
1247
+ * Verifies the placement option of a response option in the preview tab.
1248
+ * @param {string} placementOption - The placement option to verify ('Bottom', 'Top', 'Left', or 'Right').
1249
+ * @throws {Error} Throws an error if an invalid placement option is provided.
1250
+ */
1251
+ verifyResponseOptionPlacementPreviewTab: (placementOption) => {
1252
+ const questionPreviewWrapper = dragAndDropIntoCategoriesPage.questionPreviewWrapper();
1253
+ switch (placementOption) {
1254
+ case 'Bottom':
1255
+ questionPreviewWrapper
1256
+ .should('not.have.class', 'classification-preview-top')
1257
+ .and('not.have.class', 'classification-preview-left')
1258
+ .and('not.have.class', 'classification-preview-right');
1259
+ break;
1260
+ case 'Top':
1261
+ questionPreviewWrapper
1262
+ .should('have.class', 'classification-preview-top');
1263
+ break;
1264
+ case 'Left':
1265
+ questionPreviewWrapper
1266
+ .should('have.class', 'classification-preview-left');
1267
+ break;
1268
+ case 'Right':
1269
+ questionPreviewWrapper
1270
+ .should('have.class', 'classification-preview-right');
1271
+ break;
1272
+ default:
1273
+ throw new Error('Invalid placement option');
1274
+ }
1275
+ }
1276
+ }
1277
+
1278
+ const tests = {
1279
+ ...questionInstructionsComponent.tests,
1280
+ ...dragAndDropResponseOptions.tests,
1281
+ ...autoScoredSetCorrectAnswerSection.tests,
1282
+ ...dragAndDropSetCorrectAnswerCheckboxComponents.tests,
1283
+ ...autoScoredScoringSection.tests,
1284
+ ...scoringSectionBase.tests,
1285
+ ...dragAndDropResponseOptions.tests,
1286
+ ...additionalSettingsPanel.tests,
1287
+ ...autoScoredAdditionalSettings.tests,
1288
+ ...autoScoredScoringSectionMultipleResponsesType.tests,
1289
+ ...previewScoringAndShowCorrectAnswerComponent.tests,
1290
+ ...createQuestionBasePage.tests,
1291
+ ...commonComponents.tests,
1292
+ ...draggableOptionsContainer.tests,
1293
+ ...answerNumerationComponent.tests,
1294
+ ...studentResponseAndLayoutComponent.tests,
1295
+ ...autoScoredAdditionalSettings.tests,
1296
+ /**
1297
+ * @param {string} scoringSubtype option from the scoring subtype dropdown. Should be one of 'Total score divided between each correct response', 'Total score divided between each cell'
1298
+ * @description verify the contents of the selected scoring subtype that have round down score feature
1299
+ */
1300
+ verifyScoringSubtypeWithRoundDownScoreContents: (scoringSubtype) => {
1301
+ it(`When the user selects \'${scoringSubtype}\' option from the scoring subtype dropdown, penalty points label and input field, minimum score awarded (if attempted) label and input field and round down score label with checkbox in checked state should be displayed`, () => {
1302
+ dragAndDropIntoCategoriesPage.steps.clickOnScoringSubtypeDropdown();
1303
+ dragAndDropIntoCategoriesPage.steps.selectScoringSubTypeDropdownOption(scoringSubtype);
1304
+ autoScoredScoringSectionMultipleResponsesType.steps.verifyDefaultPenaltyPointsInputFieldAndLabel();
1305
+ scoringSectionBase.steps.verifyDefaultMinimumScoreIfAttemptedLabelAndPointsField();
1306
+ autoScoredScoringSectionMultipleResponsesType.steps.verifyDefaultRoundDownScoreCheckboxCheckedAndLabel();
1307
+ });
1308
+ },
1309
+
1310
+ /**
1311
+ * @param {string} optionName option from the scoring subtype dropdown. Should be one of 'Partial - score for each correct response', 'Partial - score for each cell'
1312
+ * @description verify the contents of the selected scoring subtype that do not have round down score feature
1313
+ */
1314
+ verifyScoringSubtypeWithoutRoundDownScoreContents: (scoringSubtype) => {
1315
+ it(`When the user selects \'${scoringSubtype}\' option from the scoring subtype dropdown, penalty points label and input field, minimum score awarded (if attempted) label and input field should be displayed`, () => {
1316
+ dragAndDropIntoCategoriesPage.steps.clickOnScoringSubtypeDropdown();
1317
+ dragAndDropIntoCategoriesPage.steps.selectScoringSubTypeDropdownOption(scoringSubtype);
1318
+ autoScoredScoringSectionMultipleResponsesType.steps.verifyDefaultPenaltyPointsInputFieldAndLabel();
1319
+ scoringSectionBase.steps.verifyDefaultMinimumScoreIfAttemptedLabelAndPointsField();
1320
+ autoScoredScoringSectionMultipleResponsesType.rounddownScoreCheckboxLabel()
1321
+ .should('not.exist');
1322
+ autoScoredScoringSectionMultipleResponsesType.rounddownScoreCheckbox()
1323
+ .should('not.exist');
1324
+ });
1325
+ },
1326
+
1327
+ /**
1328
+ * @param {number} allocatedPoints points allocated to the question
1329
+ * @description verify the contents of the question preview on selecting the show correct answer checkbox without attempting the question
1330
+ */
1331
+ verifyQuestionPreviewOnSelectingShowCorrectAnswerWithoutAttempting: (allocatedPoints) => {
1332
+ it('When the user selects \'Show correct answer\' checkbox without attempting the question, numeration should appear in each category cell, correct/incorrect cell border or icons should not be displayed, a correct answer section with \'Correct answers:\' label and all correct answers should be displayed below the question preview', () => {
1333
+ dragAndDropIntoCategoriesPage.steps.checkShowCorrectAnswerCheckbox();
1334
+ dragAndDropIntoCategoriesPage.steps.verifyNumerationOfCategoryCellsInQuestionPreview([1, 2, 3, 4]);
1335
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectIncorrectBorderNotVisible();
1336
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectIncorrectCellBorderNotExists();
1337
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectAnswersLabel();
1338
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectAnswerResponsesInCorrectAnswerSectionAndCount(correctTabAnswerArray, [1, 2, 3, 4]);
1339
+ dragAndDropIntoCategoriesPage.previewScoreText()
1340
+ .verifyInnerText(`0/${allocatedPoints}`);
1341
+ });
1342
+ },
1343
+
1344
+ verifyQuestionPreviewOnClickingCheckAnswerWithoutAttempting: () => {
1345
+ it('When user selects Check answer button without attempting the question, correct/incorrect border and icon for cell should not be displayed, correct/incorrect answer border for the question and label should not be displayed below the question preview and no correct answer section should not be displayed', () => {
1346
+ cy.log('Pre-step: Deselect the show correct checkbox')
1347
+ dragAndDropIntoCategoriesPage.steps.uncheckShowCorrectAnswerCheckbox();
1348
+ dragAndDropIntoCategoriesPage.steps.checkAnswer();
1349
+ dragAndDropIntoCategoriesPage.correctIncorrectAnswerLabel()
1350
+ .should('not.exist');
1351
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectIncorrectBorderNotVisible();
1352
+ dragAndDropIntoCategoriesPage.steps.verifyCorrectAnswerSectionNotVisible();
1353
+ });
1354
+ },
1355
+
1356
+ /**
1357
+ * @param {number} totalPoints the maximum points that can be scored by the user
1358
+ * @description verify the functionality of minimum points when penalty points are not set and user attempts incorrect answer
1359
+ */
1360
+ verifyMinimumScoreAwardedIfAttemptedFunctionalityForIncorrectAnswer: (totalPoints) => {
1361
+ it('When user has provided minimum score awarded (if attempted) points, then in Preview tab on entering incorrect answer, minimum score should be provided for the question', () => {
1362
+ cy.log('Switch to edit tab and set minimum score if attempted points')
1363
+ createQuestionBasePage.steps.switchToEditTab();
1364
+ scoringSectionBase.steps.allotMinimumScoreAwardedIfAttempted(1)
1365
+ createQuestionBasePage.steps.switchToPreviewTab()
1366
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 2);
1367
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 3);
1368
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 1);
1369
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1370
+ .verifyInnerText(`1/${totalPoints}`);
1371
+ });
1372
+
1373
+ it('When user removes minimum score awarded (if attempted) points, then in Preview tab on selecting any options other than correct answers, points should not be provided', () => {
1374
+ cy.log('Switch to edit tab and remove minimum score if attempted points')
1375
+ createQuestionBasePage.steps.switchToEditTab();
1376
+ dragAndDropIntoCategoriesPage.steps.clearMinimumScoreIfAttemptedPointsField();
1377
+ createQuestionBasePage.steps.switchToPreviewTab()
1378
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 2);
1379
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 3);
1380
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 1);
1381
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1382
+ .verifyInnerText(`0/${totalPoints}`);
1383
+ });
1384
+ },
1385
+
1386
+ /**
1387
+ * @param {number} scoredPoints the points scored by the user
1388
+ * @param {number} totalPoints the maximum points that can be scored by the user
1389
+ * @description verify the functionality of Penalty points when minimum points are not set and user attempts incorrect answer
1390
+ */
1391
+ verifyPenaltyPointsFunctionalityForIncorrectAnswer: (scoredPoints, totalPoints) => {
1392
+ it('When user has defined penalty points', () => {
1393
+ cy.log('Pre-step: Switch to edit tab and set penalty points');
1394
+ createQuestionBasePage.steps.switchToEditTab();
1395
+ autoScoredScoringSectionMultipleResponsesType.steps.allotPenaltyPoints(3)
1396
+
1397
+ cy.log('After switching to preview tab, when user adds an incorrect answer input, then 0 points should be awarded(no negative points)');
1398
+ createQuestionBasePage.steps.switchToPreviewTab();
1399
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 2);
1400
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 3);
1401
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 1);
1402
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1403
+ .verifyInnerText(`0/${totalPoints}`);
1404
+
1405
+ cy.log('When user adds a partially correct answer input, the points should be updated accordingly with deducted penalty points');
1406
+ dragAndDropIntoCategoriesPage.steps.resetQuestionPreview();
1407
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1408
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 1);
1409
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Parrot', 1);
1410
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 2);
1411
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Flying squirrel', 2);
1412
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1413
+ .verifyInnerText(`${scoredPoints}/${totalPoints}`);
1414
+ });
1415
+ },
1416
+
1417
+ /**
1418
+ * @param {number[]} pointsScoredArray An array of numbers representing points scored in different cases.
1419
+ * - The first element represents points scored for incorrect answers.
1420
+ * - The second element represents points scored for partially correct answers.
1421
+ * - The third element represents points scored when minimum score awarded (if attempted) points is greater than the points achieved by attempting the question partially correct
1422
+ * @param {number} minimumPointsForPartialCorrectAnswers minimum score awarded (if attempted) points on attempting the question partially correct
1423
+ * @param {number} totalPoints the maximum points that can be achieved by the user
1424
+ * @description verify the functionality of Minimum score awarded (if attempted) and penalty points are set and user attempts the question for the following cases.
1425
+ * - For all incorrect responses
1426
+ * - For partially correct responses, when points scored > minimum score awarded(if attempted) points
1427
+ * - For partially correct responses, when minimum score awarded(if attempted) points > points scored
1428
+ */
1429
+ verifyMinimumScoreIfAttemptedAndPenaltyPointsFunctionalityForIncorrectAnswer: (pointsScoredArray, minimumPointsForPartialCorrectAnswers, totalPoints) => {
1430
+ it('When user has defined both penalty points and minimum score awarded (if attempted) points', () => {
1431
+ cy.log('Pre-step: Switch to edit tab and set minimum score awarded (if attempted) points');
1432
+ createQuestionBasePage.steps.switchToEditTab();
1433
+ scoringSectionBase.steps.allotMinimumScoreAwardedIfAttempted(1);
1434
+
1435
+ cy.log('Switch to preview tab and give incorrect answer input to check that minimum points are displayed');
1436
+ createQuestionBasePage.steps.switchToPreviewTab();
1437
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 2);
1438
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 3);
1439
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 1);
1440
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1441
+ .verifyInnerText(`${pointsScoredArray[0]}/${totalPoints}`);
1442
+
1443
+ cy.log('When user adds a partially correct answer such that the points of the attempt(with penalty points deducted) is more than the minimum score awarded(if attempted) points');
1444
+ dragAndDropIntoCategoriesPage.steps.resetQuestionPreview();
1445
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1446
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 1);
1447
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Parrot', 1);
1448
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 2);
1449
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Flying squirrel', 3);
1450
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1451
+ .verifyInnerText(`${pointsScoredArray[1]}/${totalPoints}`);
1452
+
1453
+ cy.log('When user switches to edit tab and increases the minimum score awarded (if attempted) points to check the case for an attempt in which points of the attempt is less than minimum score awarded (if attempted) points, then the minimum score awarded (if attempted) points should be displayed to the user');
1454
+ createQuestionBasePage.steps.switchToEditTab();
1455
+ scoringSectionBase.steps.clearMinimumScoreIfAttemptedPointsField()
1456
+ scoringSectionBase.steps.allotMinimumScoreAwardedIfAttempted(minimumPointsForPartialCorrectAnswers);
1457
+ cy.log('Switching to preview tab');
1458
+ createQuestionBasePage.steps.switchToPreviewTab();
1459
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1460
+ previewScoringAndShowCorrectAnswerComponent.previewScoreText()
1461
+ .verifyInnerText(`${pointsScoredArray[2]}/${totalPoints}`);
1462
+ });
1463
+ },
1464
+
1465
+ /**
1466
+ * @param {number[]} pointsScoredArray An array of numbers representing points scored in different cases.
1467
+ * - The first element represents points scored for a partially correct answer when round down score is selected.
1468
+ * - The second element represents points scored for full correct answer when round down score is selected.
1469
+ * - The third element represents points scored for a partially correct answer when round down score is deselected.
1470
+ * @param {number} totalPoints the maximum points that can be achieved by the user
1471
+ * @description verify the functionality of round down score for following cases.
1472
+ * - For partially correct response, when round down score is selected.
1473
+ * - For full correct answer response, when round down score is selected
1474
+ * - For partially correct response, when round down score is deselected.
1475
+ * - For full correct answer response, when round down score is deselected
1476
+ */
1477
+ verifyRoundDownScoreFunctionality: (pointsScoredArray, totalPoints) => {
1478
+ it('When the \'Round down score\' checkbox is selected, then in preview tab when user enters partially or fully correct answer responses, the score displayed should be rounded down to the nearest whole number', () => {
1479
+ dragAndDropIntoCategoriesPage.previewScoreText()
1480
+ .verifyInnerText(`0/${totalPoints}`);
1481
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1482
+ dragAndDropIntoCategoriesPage.previewScoreText()
1483
+ .verifyInnerText(`${pointsScoredArray[0]}/${totalPoints}`);
1484
+ dragAndDropIntoCategoriesPage.steps.verifyPreviewTabPointsBackgroundForIncorrectOrPartiallyCorrectAnswer();
1485
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 1);
1486
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Parrot', 1);
1487
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 2);
1488
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Whale', 2);
1489
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Ostrich', 3);
1490
+ dragAndDropIntoCategoriesPage.previewScoreText()
1491
+ .verifyInnerText(`${pointsScoredArray[1]}/${totalPoints}`);
1492
+ dragAndDropIntoCategoriesPage.steps.verifyPreviewTabPointsBackgroundForIncorrectOrPartiallyCorrectAnswer();
1493
+ });
1494
+
1495
+ it('When the \'Round down score\' checkbox is not selected, then in preview tab when user selects partially or fully correct answers the points should be displayed in decimal points if applicable as per the options selected by the user', () => {
1496
+ cy.log('Switching to Edit tab')
1497
+ dragAndDropIntoCategoriesPage.steps.switchToEditTab();
1498
+ dragAndDropIntoCategoriesPage.steps.uncheckRoundDownScoreCheckbox();
1499
+ cy.log('Switching to Preview tab')
1500
+ dragAndDropIntoCategoriesPage.steps.switchToPreviewTab();
1501
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1502
+ dragAndDropIntoCategoriesPage.previewScoreText()
1503
+ .verifyInnerText(`${pointsScoredArray[2]}/${totalPoints}`);
1504
+ dragAndDropIntoCategoriesPage.steps.verifyPreviewTabPointsBackgroundForIncorrectOrPartiallyCorrectAnswer();
1505
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Eagle', 1);
1506
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Parrot', 1);
1507
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Platypus', 2);
1508
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Whale', 2);
1509
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Ostrich', 3);
1510
+ dragAndDropIntoCategoriesPage.previewScoreText()
1511
+ .verifyInnerText(`${totalPoints}/${totalPoints}`);
1512
+ });
1513
+ },
1514
+
1515
+ verifyReuseOptionScoring: () => {
1516
+ it('When the user has set same answer options in the \'Set correct answer\' section, then the user should be awarded full points on attempting the question with reused options', () => {
1517
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 0);
1518
+ dragAndDropIntoCategoriesPage.steps.clickAndDropDraggableOptionInCategoryCellOfPreviewTab('Bat', 1);
1519
+ dragAndDropIntoCategoriesPage.previewScoreText()
1520
+ .verifyInnerText('5/5');
1521
+ dragAndDropIntoCategoriesPage.steps.verifyPreviewTabPointsBackgroundForCorrectAnswer();
1522
+ });
1523
+ },
1524
+
1525
+ //Additional settings
1526
+ /**
1527
+ * @param {string[]} numerationArray array of the numeration displayed with options numbers| lowercase| uppercase
1528
+ * @description this function checks the numeration displayed for the options and correct answer container options when Show correct answer is checked
1529
+ */
1530
+ verifyCategoryCellsAndCorrectAnswerContainerNumerationWhenShowCorrectAnswerCheckboxIsChecked: (numerationArray) => {
1531
+ it('When user clicks on \'Show correct answer\' checkbox then the numeration should be displayed on the options as well as \'Correct answers:\' section', () => {
1532
+ previewScoringAndShowCorrectAnswerComponent.steps.checkShowCorrectAnswerCheckbox()
1533
+ steps.verifyNumerationOfCategoryCellsInQuestionPreview(numerationArray)
1534
+ steps.verifyCorrectAnswerContainerNumeration(numerationArray)
1535
+ cy.log('Post step: Uncheck \'Show correct answer\' checkbox')
1536
+ previewScoringAndShowCorrectAnswerComponent.steps.uncheckShowCorrectAnswerCheckbox()
1537
+ });
1538
+ },
1539
+
1540
+ /**
1541
+ * @param {string[]} numerationArray array of the numeration displayed with options numbers| lowercase| uppercase
1542
+ * @description this function checks the numeration displayed for the options and correct answer container options when check answer is selected
1543
+ */
1544
+ verifyCategoryCellsNumerationNotDisplayedWhenCheckAnswerIsSelected: () => {
1545
+ it('When user clicks on \'Check answer\' button then the numeration should not be displayed in the category cells', () => {
1546
+ autoScoredPreviewBase.steps.checkAnswer()
1547
+ dragAndDropIntoCategoriesPage.categoryCellNumeration()
1548
+ .should('not.exist');
1549
+ });
1550
+ }
1551
+ }
1552
+ export const dragAndDropIntoCategoriesPage = {
1553
+ ...selectors,
1554
+ steps,
1555
+ tests
1556
+ };