|
173 | 173 | }] }.deep_stringify_keys |
174 | 174 | end |
175 | 175 |
|
| 176 | + context 'extra marks (bonus_comments)' do |
| 177 | + let(:base_results) { results.deep_dup } # keep original intact |
| 178 | + |
| 179 | + shared_context 'bonus setup' do |
| 180 | + before do |
| 181 | + submission.reload |
| 182 | + submission.current_result.update!(released_to_students: false) |
| 183 | + allow(grouping).to receive(:current_submission_used).and_return(submission) |
| 184 | + end |
| 185 | + end |
| 186 | + |
| 187 | + context 'when the test run has a submission and a valid POINTS bonus' do |
| 188 | + include_context 'bonus setup' |
| 189 | + |
| 190 | + let(:submission) { create(:version_used_submission, grouping: grouping) } |
| 191 | + let(:test_run) do |
| 192 | + create(:test_run, status: :in_progress, submission: submission, grouping: grouping, autotest_test_id: 1) |
| 193 | + end |
| 194 | + |
| 195 | + before do |
| 196 | + base_results['test_groups'].first['tests'].first['extra_properties'] = { |
| 197 | + 'bonus_comments' => [ |
| 198 | + { |
| 199 | + 'mark' => 3, |
| 200 | + 'unit' => 'points', |
| 201 | + 'description' => 'this is a test comment' |
| 202 | + } |
| 203 | + ] |
| 204 | + } |
| 205 | + end |
| 206 | + |
| 207 | + it 'creates an ExtraMark on the submission result' do |
| 208 | + expect { test_run.update_results!(base_results) }.to change { ExtraMark.count }.by(1) |
| 209 | + em = ExtraMark.last |
| 210 | + expect(em.unit).to eq ExtraMark::POINTS |
| 211 | + expect(em.extra_mark).to eq 3 |
| 212 | + expect(em.result_id).to eq submission.current_result.id |
| 213 | + expect(em.description).to eq 'this is a test comment' |
| 214 | + end |
| 215 | + |
| 216 | + it 'adds the points to the test_group_result.marks_earned' do |
| 217 | + test_run.update_results!(base_results) |
| 218 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 219 | + # baseline earned = 1 (from first test), +3 bonus = 4 total |
| 220 | + expect(tgr.marks_earned).to eq 4 |
| 221 | + expect(tgr.marks_total).to eq 2 # unchanged |
| 222 | + end |
| 223 | + end |
| 224 | + |
| 225 | + context 'when the test run has a submission and a non-POINTS unit (percentage)' do |
| 226 | + include_context 'bonus setup' |
| 227 | + |
| 228 | + let(:submission) { create(:version_used_submission, grouping: grouping) } |
| 229 | + let(:test_run) do |
| 230 | + create(:test_run, status: :in_progress, submission: submission, grouping: grouping, autotest_test_id: 1) |
| 231 | + end |
| 232 | + |
| 233 | + before do |
| 234 | + base_results['test_groups'].first['tests'].first['extra_properties'] = { |
| 235 | + 'bonus_comments' => [ |
| 236 | + { 'unit' => ExtraMark::PERCENTAGE, 'mark' => 10, 'description' => '10% bump' } |
| 237 | + ] |
| 238 | + } |
| 239 | + end |
| 240 | + |
| 241 | + it 'creates an ExtraMark but does not change marks_earned' do |
| 242 | + expect { test_run.update_results!(base_results) }.to change { ExtraMark.count }.by(1) |
| 243 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 244 | + # baseline earned remains 1 since non-POINTS units don’t add to marks_earned |
| 245 | + expect(tgr.marks_earned).to eq 1 |
| 246 | + expect(tgr.marks_total).to eq 2 |
| 247 | + end |
| 248 | + end |
| 249 | + |
| 250 | + context 'when the unit is invalid' do |
| 251 | + let(:submission) { create(:version_used_submission, grouping: grouping) } |
| 252 | + let(:test_run) do |
| 253 | + create(:test_run, status: :in_progress, submission: submission, grouping: grouping, autotest_test_id: 1) |
| 254 | + end |
| 255 | + |
| 256 | + before do |
| 257 | + base_results['test_groups'].first['tests'].first['extra_properties'] = { |
| 258 | + 'bonus_comments' => [ |
| 259 | + { 'unit' => 'bananas', 'mark' => 99, 'description' => 'nope' } |
| 260 | + ] |
| 261 | + } |
| 262 | + end |
| 263 | + |
| 264 | + it 'ignores the comment and does not create an ExtraMark nor change marks' do |
| 265 | + expect { test_run.update_results!(base_results) }.not_to(change { ExtraMark.count }) |
| 266 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 267 | + expect(tgr.marks_earned).to eq 1 |
| 268 | + expect(tgr.marks_total).to eq 2 |
| 269 | + end |
| 270 | + end |
| 271 | + |
| 272 | + context 'when bonus_comments is not an array' do |
| 273 | + let(:submission) { create(:version_used_submission, grouping: grouping) } |
| 274 | + let(:test_run) do |
| 275 | + create(:test_run, status: :in_progress, submission: submission, grouping: grouping, autotest_test_id: 1) |
| 276 | + end |
| 277 | + |
| 278 | + before do |
| 279 | + base_results['test_groups'].first['tests'].first['extra_properties'] = { |
| 280 | + 'bonus_comments' => 'not-an-array' |
| 281 | + } |
| 282 | + end |
| 283 | + |
| 284 | + it 'does nothing' do |
| 285 | + expect { test_run.update_results!(base_results) }.not_to(change { ExtraMark.count }) |
| 286 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 287 | + expect(tgr.marks_earned).to eq 1 |
| 288 | + expect(tgr.marks_total).to eq 2 |
| 289 | + end |
| 290 | + end |
| 291 | + |
| 292 | + context 'when bonus_comments is missing' do |
| 293 | + let(:submission) { create(:version_used_submission, grouping: grouping) } |
| 294 | + let(:test_run) do |
| 295 | + create(:test_run, status: :in_progress, submission: submission, grouping: grouping, autotest_test_id: 1) |
| 296 | + end |
| 297 | + |
| 298 | + it 'does nothing' do |
| 299 | + expect { test_run.update_results!(base_results) }.not_to(change { ExtraMark.count }) |
| 300 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 301 | + expect(tgr.marks_earned).to eq 1 |
| 302 | + expect(tgr.marks_total).to eq 2 |
| 303 | + end |
| 304 | + end |
| 305 | + |
| 306 | + context 'when there is no submission result (no submission on the test run)' do |
| 307 | + let(:test_run) { create(:test_run, status: :in_progress, grouping: grouping, autotest_test_id: 1) } |
| 308 | + |
| 309 | + before do |
| 310 | + base_results['test_groups'].first['tests'].first['extra_properties'] = { |
| 311 | + 'bonus_comments' => [ |
| 312 | + { 'unit' => ExtraMark::POINTS, 'mark' => 5, 'description' => 'should be ignored' } |
| 313 | + ] |
| 314 | + } |
| 315 | + end |
| 316 | + |
| 317 | + it 'does not create ExtraMark and does not change marks_earned' do |
| 318 | + expect { test_run.update_results!(base_results) }.not_to(change { ExtraMark.count }) |
| 319 | + tgr = TestGroupResult.find_by(test_group_id: test_group.id, test_run_id: test_run.id) |
| 320 | + # no submission => add_extra_marks_to_test! returns 0, so only earned = 1 baseline |
| 321 | + expect(tgr.marks_earned).to eq 1 |
| 322 | + expect(tgr.marks_total).to eq 2 |
| 323 | + end |
| 324 | + end |
| 325 | + end |
| 326 | + |
176 | 327 | context 'when there are feedback files' do |
177 | 328 | let(:feedback_files) { test_group.test_group_results.first.feedback_files } |
178 | 329 |
|
|
0 commit comments