Skip to content

Commit

Permalink
Merge branch 'master' into bulk_beta_modify_access-to-drf
Browse files Browse the repository at this point in the history
  • Loading branch information
awais786 authored Dec 6, 2024
2 parents 7d8c60c + 0bd0e6f commit 4a84b4d
Show file tree
Hide file tree
Showing 30 changed files with 688 additions and 417 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/js-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
node-version: [18, 20]
node-version: [20]
python-version:
- "3.11"

Expand All @@ -28,7 +28,7 @@ jobs:
node-version: ${{ matrix.node-version }}

- name: Setup npm
run: npm i -g npm@10.5.x
run: npm i -g npm@10.7.x

- name: Install Firefox 123.0
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/static-assets-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
os: [ubuntu-24.04]
python-version:
- "3.11"
node-version: [18, 20]
npm-version: [10.5.x]
node-version: [20]
npm-version: [10.7.x]
mongo-version:
- "7.0"

Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
84 changes: 42 additions & 42 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,36 +48,36 @@ RUN echo "locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8"

# Setting up ppa deadsnakes to get python 3.11
RUN apt-get update && \
apt-get install -y software-properties-common && \
apt-add-repository -y ppa:deadsnakes/ppa
apt-get install -y software-properties-common && \
apt-add-repository -y ppa:deadsnakes/ppa

# Install requirements that are absolutely necessary
RUN apt-get update && \
apt-get -y dist-upgrade && \
apt-get -y install --no-install-recommends \
python3-pip \
python3.11 \
# python3-dev: required for building mysqlclient python package
python3.11-dev \
python3.11-venv \
libpython3.11 \
libpython3.11-stdlib \
libmysqlclient21 \
# libmysqlclient-dev: required for building mysqlclient python package
libmysqlclient-dev \
pkg-config \
libssl1.1 \
libxmlsec1-openssl \
# lynx: Required by https://github.com/openedx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16
lynx \
ntp \
git \
build-essential \
gettext \
gfortran \
graphviz \
locales \
swig \
python3-pip \
python3.11 \
# python3-dev: required for building mysqlclient python package
python3.11-dev \
python3.11-venv \
libpython3.11 \
libpython3.11-stdlib \
libmysqlclient21 \
# libmysqlclient-dev: required for building mysqlclient python package
libmysqlclient-dev \
pkg-config \
libssl1.1 \
libxmlsec1-openssl \
# lynx: Required by https://github.com/openedx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16
lynx \
ntp \
git \
build-essential \
gettext \
gfortran \
graphviz \
locales \
swig \
&& \
apt-get clean all && \
rm -rf /var/lib/apt/*
Expand All @@ -93,19 +93,19 @@ FROM minimal-system as builder-production

RUN apt-get update && \
apt-get -y install --no-install-recommends \
curl \
libssl-dev \
libffi-dev \
libfreetype6-dev \
libgeos-dev \
libgraphviz-dev \
libjpeg8-dev \
liblapack-dev \
libpng-dev \
libsqlite3-dev \
libxml2-dev \
libxmlsec1-dev \
libxslt1-dev
curl \
libssl-dev \
libffi-dev \
libfreetype6-dev \
libgeos-dev \
libgraphviz-dev \
libjpeg8-dev \
liblapack-dev \
libpng-dev \
libsqlite3-dev \
libxml2-dev \
libxmlsec1-dev \
libxslt1-dev

# Setup python virtual environment
# It is already 'activated' because $VIRTUAL_ENV/bin was put on $PATH
Expand All @@ -118,8 +118,8 @@ RUN pip install -r requirements/pip.txt
RUN pip install -r requirements/edx/base.txt

# Install node and npm
RUN nodeenv /edx/app/edxapp/nodeenv --node=18.19.0 --prebuilt
RUN npm install -g npm@10.5.x
RUN nodeenv /edx/app/edxapp/nodeenv --node=20.15.1 --prebuilt
RUN npm install -g npm@10.7.x

# This script is used by an npm post-install hook.
# We copy it into the image now so that it will be available when we run `npm install` in the next step.
Expand Down Expand Up @@ -178,8 +178,8 @@ FROM base as development

RUN apt-get update && \
apt-get -y install --no-install-recommends \
# wget is used in Makefile for common_constraints.txt
wget \
# wget is used in Makefile for common_constraints.txt
wget \
&& \
apt-get clean all && \
rm -rf /var/lib/apt/*
Expand Down
86 changes: 83 additions & 3 deletions cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
Unit tests for home page view.
"""
import ddt
import pytz
from collections import OrderedDict
from datetime import datetime, timedelta
from django.conf import settings
from django.test import override_settings
from django.urls import reverse
Expand Down Expand Up @@ -100,12 +102,13 @@ class HomePageCoursesViewTest(CourseTestCase):
def setUp(self):
super().setUp()
self.url = reverse("cms.djangoapps.contentstore:v1:courses")
CourseOverviewFactory.create(
self.course_overview = CourseOverviewFactory.create(
id=self.course.id,
org=self.course.org,
display_name=self.course.display_name,
display_number_with_default=self.course.number,
)
self.non_staff_client, _ = self.create_non_staff_authed_user_client()

def test_home_page_response(self):
"""Check successful response content"""
Expand All @@ -131,6 +134,7 @@ def test_home_page_response(self):
print(response.data)
self.assertDictEqual(expected_response, response.data)

@override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API)
def test_home_page_response_with_api_v2(self):
"""Check successful response content with api v2 modifications.
Expand All @@ -155,12 +159,88 @@ def test_home_page_response_with_api_v2(self):
"in_process_course_actions": [],
}

with override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API):
response = self.client.get(self.url)
response = self.client.get(self.url)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(expected_response, response.data)

@override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API)
@ddt.data(
("active_only", "true", 2, 0),
("archived_only", "true", 0, 1),
("search", "sample", 1, 0),
("search", "demo", 0, 1),
("order", "org", 2, 1),
("order", "display_name", 2, 1),
("order", "number", 2, 1),
("order", "run", 2, 1)
)
@ddt.unpack
def test_filter_and_ordering_courses(
self,
filter_key,
filter_value,
expected_active_length,
expected_archived_length
):
"""Test home page with org filter and ordering for a staff user.
The test creates an active/archived course, and then filters/orders them using the query parameters.
"""
archived_course_key = self.store.make_course_key("demo-org", "demo-number", "demo-run")
CourseOverviewFactory.create(
display_name="Course (Demo)",
id=archived_course_key,
org=archived_course_key.org,
end=(datetime.now() - timedelta(days=365)).replace(tzinfo=pytz.UTC),
)
active_course_key = self.store.make_course_key("sample-org", "sample-number", "sample-run")
CourseOverviewFactory.create(
display_name="Course (Sample)",
id=active_course_key,
org=active_course_key.org,
)

response = self.client.get(self.url, {filter_key: filter_value})

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data["archived_courses"]), expected_archived_length)
self.assertEqual(len(response.data["courses"]), expected_active_length)

@override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API)
@ddt.data(
("active_only", "true"),
("archived_only", "true"),
("search", "sample"),
("order", "org"),
)
@ddt.unpack
def test_filter_and_ordering_no_courses_staff(self, filter_key, filter_value):
"""Test home page with org filter and ordering when there are no courses for a staff user."""
self.course_overview.delete()

response = self.client.get(self.url, {filter_key: filter_value})

self.assertEqual(len(response.data["courses"]), 0)
self.assertEqual(response.status_code, status.HTTP_200_OK)

@override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API)
@ddt.data(
("active_only", "true"),
("archived_only", "true"),
("search", "sample"),
("order", "org"),
)
@ddt.unpack
def test_home_page_response_no_courses_non_staff(self, filter_key, filter_value):
"""Test home page with org filter and ordering when there are no courses for a non-staff user."""
self.course_overview.delete()

response = self.non_staff_client.get(self.url)

self.assertEqual(len(response.data["courses"]), 0)
self.assertEqual(response.status_code, status.HTTP_200_OK)

@override_waffle_switch(ENABLE_GLOBAL_STAFF_OPTIMIZATION, True)
def test_org_query_if_passed(self):
"""Test home page when org filter passed as a query param"""
Expand Down
98 changes: 98 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v2/views/tests/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def setUp(self):
org=archived_course_key.org,
end=(datetime.now() - timedelta(days=365)).replace(tzinfo=pytz.UTC),
)
self.non_staff_client, _ = self.create_non_staff_authed_user_client()

def test_home_page_response(self):
"""Get list of courses available to the logged in user.
Expand Down Expand Up @@ -247,3 +248,100 @@ def test_api_v2_is_disabled(self, mock_modulestore, mock_course_overview):
self.assertEqual(response.status_code, status.HTTP_200_OK)
mock_modulestore().get_course_summaries.assert_called_once()
mock_course_overview.get_all_courses.assert_not_called()

@ddt.data(
("active_only", "true"),
("archived_only", "true"),
("search", "sample"),
("order", "org"),
("page", 1),
)
@ddt.unpack
def test_if_empty_list_of_courses(self, query_param, value):
"""Get list of courses when no courses are available.
Expected result:
- An empty list of courses available to the logged in user.
"""
self.active_course.delete()
self.archived_course.delete()

response = self.client.get(self.api_v2_url, {query_param: value})

self.assertEqual(len(response.data['results']['courses']), 0)
self.assertEqual(response.status_code, status.HTTP_200_OK)

@override_settings(FEATURES=FEATURES_WITH_HOME_PAGE_COURSE_V2_API)
@ddt.data(
("active_only", "true", 2, 0),
("archived_only", "true", 0, 1),
("search", "foo", 1, 0),
("search", "demo", 0, 1),
("order", "org", 2, 1),
("order", "display_name", 2, 1),
("order", "number", 2, 1),
("order", "run", 2, 1)
)
@ddt.unpack
def test_filter_and_ordering_courses(
self,
filter_key,
filter_value,
expected_active_length,
expected_archived_length
):
"""Get list of courses when filter and ordering are applied.
This test creates two courses besides the default courses created in the setUp method.
Then filters and orders them based on the filter_key and filter_value passed as query parameters.
Expected result:
- A list of courses available to the logged in user for the specified filter and order.
"""
archived_course_key = self.store.make_course_key("demo-org", "demo-number", "demo-run")
CourseOverviewFactory.create(
display_name="Course (Demo)",
id=archived_course_key,
org=archived_course_key.org,
end=(datetime.now() - timedelta(days=365)).replace(tzinfo=pytz.UTC),
)
active_course_key = self.store.make_course_key("foo-org", "foo-number", "foo-run")
CourseOverviewFactory.create(
display_name="Course (Foo)",
id=active_course_key,
org=active_course_key.org,
)

response = self.client.get(self.api_v2_url, {filter_key: filter_value})

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
len([course for course in response.data["results"]["courses"] if course["is_active"]]),
expected_active_length
)
self.assertEqual(
len([course for course in response.data["results"]["courses"] if not course["is_active"]]),
expected_archived_length
)

@ddt.data(
("active_only", "true"),
("archived_only", "true"),
("search", "sample"),
("order", "org"),
("page", 1),
)
@ddt.unpack
def test_if_empty_list_of_courses_non_staff(self, query_param, value):
"""Get list of courses when no courses are available for non-staff users.
Expected result:
- An empty list of courses available to the logged in user.
"""
self.active_course.delete()
self.archived_course.delete()

response = self.non_staff_client.get(self.api_v2_url, {query_param: value})

self.assertEqual(len(response.data["results"]["courses"]), 0)
self.assertEqual(response.status_code, status.HTTP_200_OK)
Loading

0 comments on commit 4a84b4d

Please sign in to comment.