|
3 | 3 | """ |
4 | 4 |
|
5 | 5 |
|
6 | | -import json |
7 | 6 | import tempfile |
8 | 7 |
|
9 | 8 | import ddt |
|
15 | 14 | from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order |
16 | 15 | from xmodule.modulestore.tests.factories import ToyCourseFactory # lint-amnesty, pylint: disable=wrong-import-order |
17 | 16 |
|
18 | | -from .. import cohorts |
19 | | -from .helpers import CohortFactory |
| 17 | +from openedx.core.djangoapps.course_groups import cohorts |
| 18 | +from openedx.core.djangoapps.course_groups.views import link_cohort_to_partition_group |
| 19 | +from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory |
20 | 20 |
|
21 | 21 | USERNAME = 'honor' |
22 | 22 | USER_MAIL = 'honor@example.com' |
23 | 23 | SETTINGS_PAYLOAD = '{"is_cohorted": true}' |
24 | 24 | HANDLER_POST_PAYLOAD = '{"name":"Default","user_count":0,"assignment_type":"random","user_partition_id":null\ |
25 | 25 | ,"group_id":null}' |
26 | 26 | HANDLER_PATCH_PAYLOAD = '{"name":"Default Group","group_id":null,"user_partition_id":null,"assignment_type":"random"}' |
27 | | -ADD_USER_PAYLOAD = json.dumps({'users': [USER_MAIL, ]}) |
| 27 | +ADD_USER_PAYLOAD = {'users': [USER_MAIL, ]} |
28 | 28 | CSV_DATA = f'''email,cohort\n{USER_MAIL},DEFAULT''' |
29 | 29 |
|
30 | 30 |
|
@@ -307,7 +307,7 @@ def test_list_users_in_cohort(self, is_staff, status): |
307 | 307 | assert response.status_code == status |
308 | 308 |
|
309 | 309 | if status == 200: |
310 | | - results = json.loads(response.content.decode('utf-8'))['results'] |
| 310 | + results = response.json()['results'] |
311 | 311 | expected_results = [{ |
312 | 312 | 'username': user.username, |
313 | 313 | 'email': user.email, |
@@ -406,7 +406,7 @@ def test_add_users_to_cohort_different_types_of_users(self): |
406 | 406 | "invalid": ["foo@bar"], |
407 | 407 | "present": ["user2"] |
408 | 408 | } |
409 | | - assert json.loads(response.content.decode('utf-8')) == expected_response |
| 409 | + assert response.json() == expected_response |
410 | 410 |
|
411 | 411 | def test_remove_user_from_cohort_missing_username(self): |
412 | 412 | """ |
@@ -458,3 +458,151 @@ def test_add_users_csv(self, is_staff, payload, status): |
458 | 458 | response = self.client.post(path=path, |
459 | 459 | data={'uploaded-file': file_pointer}) |
460 | 460 | assert response.status_code == status |
| 461 | + |
| 462 | + def test_post_cohort_with_group_id(self): |
| 463 | + """ |
| 464 | + Test creating a cohort with group_id and user_partition_id. |
| 465 | + """ |
| 466 | + path = reverse('api_cohorts:cohort_handler', kwargs={'course_key_string': self.course_str}) |
| 467 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 468 | + |
| 469 | + payload = { |
| 470 | + 'name': 'TestCohort', |
| 471 | + 'assignment_type': 'manual', |
| 472 | + 'group_id': 1, |
| 473 | + 'user_partition_id': 50 |
| 474 | + } |
| 475 | + response = self.client.post(path=path, data=payload, content_type='application/json') |
| 476 | + assert response.status_code == 200 |
| 477 | + |
| 478 | + data = response.json() |
| 479 | + assert data['name'] == 'TestCohort' |
| 480 | + assert data['assignment_type'] == 'manual' |
| 481 | + assert data['group_id'] == 1 |
| 482 | + assert data['user_partition_id'] == 50 |
| 483 | + assert data['user_count'] == 0 |
| 484 | + assert 'id' in data |
| 485 | + |
| 486 | + def test_post_cohort_with_group_id_missing_partition_id(self): |
| 487 | + """ |
| 488 | + Test that creating a cohort with group_id but without user_partition_id returns an error. |
| 489 | + """ |
| 490 | + path = reverse('api_cohorts:cohort_handler', kwargs={'course_key_string': self.course_str}) |
| 491 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 492 | + |
| 493 | + payload = { |
| 494 | + 'name': 'TestCohort', |
| 495 | + 'assignment_type': 'manual', |
| 496 | + 'group_id': 1 |
| 497 | + } |
| 498 | + response = self.client.post(path=path, data=payload, content_type='application/json') |
| 499 | + assert response.status_code == 400 |
| 500 | + |
| 501 | + data = response.json() |
| 502 | + assert data['developer_message'] == 'If group_id is specified, user_partition_id must also be specified.' |
| 503 | + assert data['error_code'] == 'missing-user-partition-id' |
| 504 | + |
| 505 | + def test_patch_cohort_set_group_id(self): |
| 506 | + """ |
| 507 | + Test updating a cohort to set group_id and user_partition_id. |
| 508 | + """ |
| 509 | + cohort = cohorts.add_cohort(self.course_key, "TestCohort", "manual") |
| 510 | + path = reverse( |
| 511 | + 'api_cohorts:cohort_handler', |
| 512 | + kwargs={'course_key_string': self.course_str, 'cohort_id': cohort.id} |
| 513 | + ) |
| 514 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 515 | + |
| 516 | + payload = { |
| 517 | + 'group_id': 2, |
| 518 | + 'user_partition_id': 50 |
| 519 | + } |
| 520 | + response = self.client.patch(path=path, data=payload, content_type='application/json') |
| 521 | + assert response.status_code == 204 |
| 522 | + |
| 523 | + # Verify by fetching the cohort |
| 524 | + response = self.client.get(path=path) |
| 525 | + data = response.json() |
| 526 | + assert data['id'] == cohort.id |
| 527 | + assert data['name'] == 'TestCohort' |
| 528 | + assert data['assignment_type'] == 'manual' |
| 529 | + assert data['group_id'] == 2 |
| 530 | + assert data['user_partition_id'] == 50 |
| 531 | + |
| 532 | + def test_patch_cohort_remove_group_id(self): |
| 533 | + """ |
| 534 | + Test updating a cohort to remove the group_id association by setting it to null. |
| 535 | + """ |
| 536 | + cohort = cohorts.add_cohort(self.course_key, "TestCohort", "manual") |
| 537 | + link_cohort_to_partition_group(cohort, 50, 1) |
| 538 | + |
| 539 | + path = reverse( |
| 540 | + 'api_cohorts:cohort_handler', |
| 541 | + kwargs={'course_key_string': self.course_str, 'cohort_id': cohort.id} |
| 542 | + ) |
| 543 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 544 | + |
| 545 | + # Verify the cohort has a group_id |
| 546 | + response = self.client.get(path=path) |
| 547 | + data = response.json() |
| 548 | + assert data['id'] == cohort.id |
| 549 | + assert data['name'] == 'TestCohort' |
| 550 | + assert data['group_id'] == 1 |
| 551 | + assert data['user_partition_id'] == 50 |
| 552 | + |
| 553 | + # Remove the group_id by setting it to null |
| 554 | + payload = {'group_id': None} |
| 555 | + response = self.client.patch(path=path, data=payload, content_type='application/json') |
| 556 | + assert response.status_code == 204 |
| 557 | + |
| 558 | + # Verify the group_id was removed but other fields unchanged |
| 559 | + response = self.client.get(path=path) |
| 560 | + data = response.json() |
| 561 | + assert data['id'] == cohort.id |
| 562 | + assert data['name'] == 'TestCohort' |
| 563 | + assert data['assignment_type'] == 'manual' |
| 564 | + assert data['group_id'] is None |
| 565 | + assert data['user_partition_id'] is None |
| 566 | + |
| 567 | + def test_patch_cohort_with_group_id_missing_partition_id(self): |
| 568 | + """ |
| 569 | + Test that updating a cohort with group_id but without user_partition_id returns an error. |
| 570 | + """ |
| 571 | + cohort = cohorts.add_cohort(self.course_key, "TestCohort", "manual") |
| 572 | + path = reverse( |
| 573 | + 'api_cohorts:cohort_handler', |
| 574 | + kwargs={'course_key_string': self.course_str, 'cohort_id': cohort.id} |
| 575 | + ) |
| 576 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 577 | + |
| 578 | + payload = {'group_id': 2} |
| 579 | + response = self.client.patch(path=path, data=payload, content_type='application/json') |
| 580 | + assert response.status_code == 400 |
| 581 | + |
| 582 | + data = response.json() |
| 583 | + assert data['developer_message'] == 'If group_id is specified, user_partition_id must also be specified.' |
| 584 | + assert data['error_code'] == 'missing-user-partition-id' |
| 585 | + |
| 586 | + def test_patch_cohort_with_name_only(self): |
| 587 | + """ |
| 588 | + Test that PATCH with only name is now valid (previously required assignment_type too). |
| 589 | + """ |
| 590 | + cohort = cohorts.add_cohort(self.course_key, "OldName", "manual") |
| 591 | + path = reverse( |
| 592 | + 'api_cohorts:cohort_handler', |
| 593 | + kwargs={'course_key_string': self.course_str, 'cohort_id': cohort.id} |
| 594 | + ) |
| 595 | + self.client.login(username=self.staff_user.username, password=self.password) |
| 596 | + |
| 597 | + payload = {'name': 'NewName'} |
| 598 | + response = self.client.patch(path=path, data=payload, content_type='application/json') |
| 599 | + assert response.status_code == 204 |
| 600 | + |
| 601 | + # Verify the name was updated and other fields unchanged |
| 602 | + response = self.client.get(path=path) |
| 603 | + data = response.json() |
| 604 | + assert data['id'] == cohort.id |
| 605 | + assert data['name'] == 'NewName' |
| 606 | + assert data['assignment_type'] == 'manual' |
| 607 | + assert data['group_id'] is None |
| 608 | + assert data['user_partition_id'] is None |
0 commit comments