Compare commits
23 Commits
release/te
...
bw/compone
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e19b5774c | ||
|
|
f7a4309888 | ||
|
|
3e3a73e2bb | ||
|
|
af8d7182ef | ||
|
|
d898a9cc2f | ||
|
|
f4b839f4d8 | ||
|
|
f41b237d08 | ||
|
|
6dd2fb3dd6 | ||
|
|
b173681edb | ||
|
|
5fcde3b9e8 | ||
|
|
35ee68ea9d | ||
|
|
dde8e759b6 | ||
|
|
6b149e9ce0 | ||
|
|
4cf5ba7a07 | ||
|
|
7a506324a8 | ||
|
|
7f54cc4917 | ||
|
|
134ace9483 | ||
|
|
0e6f52fca9 | ||
|
|
ca64cc614a | ||
|
|
1ad297c46c | ||
|
|
f2bb0d7c2a | ||
|
|
f76f3d64c9 | ||
|
|
db56d76d37 |
1
.env
1
.env
@@ -10,7 +10,6 @@ DATA_API_BASE_URL=''
|
|||||||
SEGMENT_KEY=''
|
SEGMENT_KEY=''
|
||||||
FEATURE_FLAGS={}
|
FEATURE_FLAGS={}
|
||||||
ACCESS_TOKEN_COOKIE_NAME=''
|
ACCESS_TOKEN_COOKIE_NAME=''
|
||||||
LANGUAGE_PREFERENCE_COOKIE_NAME=''
|
|
||||||
NEW_RELIC_APP_ID=''
|
NEW_RELIC_APP_ID=''
|
||||||
NEW_RELIC_LICENSE_KEY=''
|
NEW_RELIC_LICENSE_KEY=''
|
||||||
SITE_NAME=''
|
SITE_NAME=''
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ LOGOUT_URL='http://localhost:18000/login'
|
|||||||
LOGO_URL=https://edx-cdn.org/v3/default/logo.svg
|
LOGO_URL=https://edx-cdn.org/v3/default/logo.svg
|
||||||
LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
|
LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
|
||||||
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
|
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
|
||||||
|
LOGO_POWERED_BY_OPEN_EDX_URL_SVG=https://edx-cdn.org/v3/stage/open-edx-tag.svg
|
||||||
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
|
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
|
||||||
CSRF_TOKEN_API_PATH='/csrf/api/v1/token'
|
CSRF_TOKEN_API_PATH='/csrf/api/v1/token'
|
||||||
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
|
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
|
||||||
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
|
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
|
||||||
LANGUAGE_PREFERENCE_COOKIE_NAME='openedx-language-preference'
|
|
||||||
USER_INFO_COOKIE_NAME='edx-user-info'
|
USER_INFO_COOKIE_NAME='edx-user-info'
|
||||||
SITE_NAME=localhost
|
SITE_NAME=localhost
|
||||||
DATA_API_BASE_URL='http://localhost:8000'
|
DATA_API_BASE_URL='http://localhost:8000'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const { createConfig } = require('@openedx/frontend-build');
|
const { createConfig } = require('@edx/frontend-build');
|
||||||
|
|
||||||
const config = createConfig('eslint', {
|
const config = createConfig('eslint', {
|
||||||
rules: {
|
rules: {
|
||||||
|
|||||||
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
@@ -1,7 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Adding new check for github-actions
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
33
.github/renovate.json
vendored
33
.github/renovate.json
vendored
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"config:base",
|
|
||||||
"schedule:weekly",
|
|
||||||
":automergeLinters",
|
|
||||||
":automergeMinor",
|
|
||||||
":automergeTesters",
|
|
||||||
":enableVulnerabilityAlerts",
|
|
||||||
":rebaseStalePrs",
|
|
||||||
":semanticCommits",
|
|
||||||
":updateNotScheduled"
|
|
||||||
],
|
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"matchDepTypes": [
|
|
||||||
"devDependencies"
|
|
||||||
],
|
|
||||||
"matchUpdateTypes": [
|
|
||||||
"lockFileMaintenance",
|
|
||||||
"minor",
|
|
||||||
"patch",
|
|
||||||
"pin"
|
|
||||||
],
|
|
||||||
"automerge": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"matchPackagePatterns": ["@edx", "@openedx"],
|
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
|
||||||
"automerge": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"timezone": "America/New_York"
|
|
||||||
}
|
|
||||||
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@@ -10,16 +10,23 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node: [16]
|
||||||
|
npm: [8.5.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup Nodejs
|
- name: Setup Nodejs
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version: ${{ matrix.node }}
|
||||||
|
|
||||||
|
- name: Install npm 8.5.x
|
||||||
|
run: npm install -g npm@${{ matrix.npm }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -40,14 +47,11 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Run Coverage
|
- name: Run Coverage
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v2
|
||||||
with:
|
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
fail_ci_if_error: true
|
|
||||||
|
|
||||||
- name: Send failure notification
|
- name: Send failure notification
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
uses: dawidd6/action-send-mail@v4
|
uses: dawidd6/action-send-mail@v3
|
||||||
with:
|
with:
|
||||||
server_address: email-smtp.us-east-1.amazonaws.com
|
server_address: email-smtp.us-east-1.amazonaws.com
|
||||||
server_port: 465
|
server_port: 465
|
||||||
|
|||||||
2
.github/workflows/lockfileversion-check.yml
vendored
2
.github/workflows/lockfileversion-check.yml
vendored
@@ -10,4 +10,4 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
version-check:
|
version-check:
|
||||||
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master
|
uses: openedx/.github/.github/workflows/lockfileversion-check.yml@master
|
||||||
|
|||||||
33
.github/workflows/npm-publish.yml
vendored
Normal file
33
.github/workflows/npm-publish.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Release CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Create Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Release Package
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
|
||||||
|
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
|
||||||
|
run: npm semantic-release
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -23,5 +23,3 @@ temp/babel-plugin-react-intl
|
|||||||
### transifex ###
|
### transifex ###
|
||||||
src/i18n/transifex_input.json
|
src/i18n/transifex_input.json
|
||||||
temp
|
temp
|
||||||
|
|
||||||
src/i18n/messages/
|
|
||||||
27
.releaserc
Normal file
27
.releaserc
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"branch": "master",
|
||||||
|
"tagFormat": "v${version}",
|
||||||
|
"verifyConditions": [
|
||||||
|
"@semantic-release/npm",
|
||||||
|
{
|
||||||
|
"path": "@semantic-release/github",
|
||||||
|
"assets": {
|
||||||
|
"path": "dist/*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"analyzeCommits": "@semantic-release/commit-analyzer",
|
||||||
|
"generateNotes": "@semantic-release/release-notes-generator",
|
||||||
|
"prepare": "@semantic-release/npm",
|
||||||
|
"publish": [
|
||||||
|
"@semantic-release/npm",
|
||||||
|
{
|
||||||
|
"path": "@semantic-release/github",
|
||||||
|
"assets": {
|
||||||
|
"path": "dist/*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"success": [],
|
||||||
|
"fail": []
|
||||||
|
}
|
||||||
9
.tx/config
Normal file
9
.tx/config
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[main]
|
||||||
|
host = https://www.transifex.com
|
||||||
|
|
||||||
|
[o:open-edx:p:edx-platform:r:frontend-app-gradebook]
|
||||||
|
file_filter = src/i18n/messages/<lang>.json
|
||||||
|
source_file = src/i18n/transifex_input.json
|
||||||
|
source_lang = en
|
||||||
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
35
Makefile
35
Makefile
@@ -1,14 +1,18 @@
|
|||||||
npm-install-%: ## install specified % npm package
|
npm-install-%: ## install specified % npm package
|
||||||
npm ci $* --save-dev
|
npm install $* --save-dev
|
||||||
git add package.json
|
git add package.json
|
||||||
|
export TRANSIFEX_RESOURCE = frontend-app-gradebook
|
||||||
|
transifex_langs = "ar,de,es_419,fa_IR,fr,fr_CA,hi,it,pt,ru,uk,zh_CN"
|
||||||
|
|
||||||
intl_imports = ./node_modules/.bin/intl-imports.js
|
intl_imports = ./node_modules/.bin/intl-imports.js
|
||||||
transifex_utils = ./node_modules/.bin/transifex-utils.js
|
transifex_utils = ./node_modules/.bin/transifex-utils.js
|
||||||
i18n = ./src/i18n
|
i18n = ./src/i18n
|
||||||
transifex_input = $(i18n)/transifex_input.json
|
transifex_input = $(i18n)/transifex_input.json
|
||||||
|
tx_url1 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/translation/en/strings/
|
||||||
|
tx_url2 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/source/
|
||||||
|
|
||||||
# This directory must match .babelrc .
|
# This directory must match .babelrc .
|
||||||
transifex_temp = ./temp/babel-plugin-formatjs
|
transifex_temp = ./temp/babel-plugin-react-intl
|
||||||
|
|
||||||
NPM_TESTS=build i18n_extract lint test is-es5
|
NPM_TESTS=build i18n_extract lint test is-es5
|
||||||
|
|
||||||
@@ -35,20 +39,39 @@ i18n.concat:
|
|||||||
|
|
||||||
extract_translations: | requirements i18n.extract i18n.concat
|
extract_translations: | requirements i18n.extract i18n.concat
|
||||||
|
|
||||||
|
# Despite the name, we actually need this target to detect changes in the incoming translated message files as well.
|
||||||
|
detect_changed_source_translations:
|
||||||
|
# Checking for changed translations...
|
||||||
|
git diff --exit-code $(i18n)
|
||||||
|
|
||||||
|
# Pushes translations to Transifex. You must run make extract_translations first.
|
||||||
|
push_translations:
|
||||||
|
# Pushing strings to Transifex...
|
||||||
|
tx push -s
|
||||||
|
# Fetching hashes from Transifex...
|
||||||
|
./node_modules/@edx/reactifex/bash_scripts/get_hashed_strings_v3.sh
|
||||||
|
# Writing out comments to file...
|
||||||
|
$(transifex_utils) $(transifex_temp) --comments --v3-scripts-path
|
||||||
|
# Pushing comments to Transifex...
|
||||||
|
./node_modules/@edx/reactifex/bash_scripts/put_comments_v3.sh
|
||||||
|
|
||||||
|
ifeq ($(OPENEDX_ATLAS_PULL),)
|
||||||
|
# Pulls translations from Transifex.
|
||||||
|
pull_translations:
|
||||||
|
tx pull -t -f --mode reviewed --languages=$(transifex_langs)
|
||||||
|
else
|
||||||
# Experimental: OEP-58 Pulls translations using atlas
|
# Experimental: OEP-58 Pulls translations using atlas
|
||||||
pull_translations:
|
pull_translations:
|
||||||
rm -rf src/i18n/messages
|
rm -rf src/i18n/messages
|
||||||
mkdir src/i18n/messages
|
mkdir src/i18n/messages
|
||||||
cd src/i18n/messages \
|
cd src/i18n/messages \
|
||||||
&& atlas pull $(ATLAS_OPTIONS) \
|
&& atlas pull --filter=$(transifex_langs) \
|
||||||
translations/frontend-component-footer/src/i18n/messages:frontend-component-footer \
|
translations/frontend-component-footer/src/i18n/messages:frontend-component-footer \
|
||||||
translations/frontend-component-header/src/i18n/messages:frontend-component-header \
|
translations/frontend-component-header/src/i18n/messages:frontend-component-header \
|
||||||
translations/frontend-platform/src/i18n/messages:frontend-platform \
|
|
||||||
translations/paragon/src/i18n/messages:paragon \
|
|
||||||
translations/frontend-app-gradebook/src/i18n/messages:frontend-app-gradebook
|
translations/frontend-app-gradebook/src/i18n/messages:frontend-app-gradebook
|
||||||
|
|
||||||
$(intl_imports) frontend-platform paragon frontend-component-header frontend-component-footer frontend-app-gradebook
|
$(intl_imports) frontend-component-header frontend-component-footer frontend-app-gradebook
|
||||||
|
endif
|
||||||
|
|
||||||
# This target is used by CI.
|
# This target is used by CI.
|
||||||
validate-no-uncommitted-package-lock-changes:
|
validate-no-uncommitted-package-lock-changes:
|
||||||
|
|||||||
136
README.md
136
README.md
@@ -1,5 +1,3 @@
|
|||||||
# frontend-app-gradebook
|
|
||||||
|
|
||||||
[](https://travis-ci.com/edx/frontend-app-gradebook)
|
[](https://travis-ci.com/edx/frontend-app-gradebook)
|
||||||
[](https://app.codecov.io/gh/openedx/frontend-app-gradebook)
|
[](https://app.codecov.io/gh/openedx/frontend-app-gradebook)
|
||||||
[](@edx/frontend-app-gradebook)
|
[](@edx/frontend-app-gradebook)
|
||||||
@@ -7,7 +5,7 @@
|
|||||||
[](@edx/frontend-app-gradebook)
|
[](@edx/frontend-app-gradebook)
|
||||||
[](https://github.com/semantic-release/semantic-release)
|
[](https://github.com/semantic-release/semantic-release)
|
||||||
|
|
||||||
# Purpose
|
# Gradebook
|
||||||
|
|
||||||
Gradebook allows course staff to view, filter, and override subsection grades for a course. Additionally for Masters courses, Gradebook enables bulk management of subsection grades.
|
Gradebook allows course staff to view, filter, and override subsection grades for a course. Additionally for Masters courses, Gradebook enables bulk management of subsection grades.
|
||||||
|
|
||||||
@@ -18,8 +16,8 @@ Jump to:
|
|||||||
|
|
||||||
For existing documentation see:
|
For existing documentation see:
|
||||||
|
|
||||||
- Basic Usage: [Review Learner Grades (read-the-docs)](https://docs.openedx.org/en/latest/educators/how-tos/data/view_learner_grades.html)
|
- Basic Usage: [Review Learner Grades (read-the-docs)](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/student_progress/course_grades.html#review-learner-grades-on-the-instructor-dashboard)
|
||||||
- Bulk Grade Management: [Override Learner Subsection Scores in Bulk (read-the-docs)](https://docs.openedx.org/en/latest/educators/how-tos/data/manage_learner_grades.html#override-learner-subsection-scores-in-bulk)
|
- Bulk Grade Management: [Override Learner Subsection Scores in Bulk (read-the-docs)](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/student_progress/course_grades.html#override-learner-subsection-scores-in-bulk)
|
||||||
|
|
||||||
## Should I use Gradebook in my course?
|
## Should I use Gradebook in my course?
|
||||||
|
|
||||||
@@ -49,8 +47,7 @@ depending on their needs. Instructors that expect to review grades infrequently
|
|||||||
to the problem in question will have a worse UX than the legacy gradebook provides. Instructors that rely on the graphs
|
to the problem in question will have a worse UX than the legacy gradebook provides. Instructors that rely on the graphs
|
||||||
generated by the current gradebook might find the lack of autogenerated graphs to be frustrating.
|
generated by the current gradebook might find the lack of autogenerated graphs to be frustrating.
|
||||||
|
|
||||||
## Getting Started
|
## Quickstart
|
||||||
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
@@ -59,66 +56,47 @@ To install gradebook into your project:
|
|||||||
npm i --save @edx/frontend-app-gradebook
|
npm i --save @edx/frontend-app-gradebook
|
||||||
```
|
```
|
||||||
|
|
||||||
Cloning and Startup
|
|
||||||
===================
|
|
||||||
|
|
||||||
1. Clone your new repo:
|
|
||||||
|
|
||||||
``git clone https://github.com/openedx/frontend-app-gradebook.git``
|
|
||||||
|
|
||||||
2. Use the version of Node specified in ``.nvmrc``
|
|
||||||
|
|
||||||
3. Stop the Tutor devstack, if it's running:
|
|
||||||
|
|
||||||
``tutor dev stop``
|
|
||||||
|
|
||||||
4. Next, we need to tell Tutor that we're going to be running this repo in development mode, and it should be excluded from the mfe container that otherwise runs every MFE. Run this:
|
|
||||||
|
|
||||||
``tutor mounts add /path/to/frontend-app-gradebook``
|
|
||||||
|
|
||||||
5. Start Tutor in development mode. This command will start the LMS and Studio,
|
|
||||||
and other required MFEs like ``authn`` and ``account``, but will not start the
|
|
||||||
Gradebook MFE, which we're going to run on the host instead of in a container
|
|
||||||
managed by Tutor. Run:
|
|
||||||
|
|
||||||
``tutor dev start lms cms mfe``
|
|
||||||
|
|
||||||
## Startup
|
|
||||||
|
|
||||||
1. Install npm dependencies:
|
|
||||||
|
|
||||||
``cd frontend-app-gradebook && npm install``
|
|
||||||
|
|
||||||
2. Start the dev server:
|
|
||||||
|
|
||||||
``npm run dev``
|
|
||||||
|
|
||||||
## Running the UI Standalone
|
## Running the UI Standalone
|
||||||
|
|
||||||
To install the project please refer to the [`MFE Development on Tutor`](https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development) instructions.
|
To install the project please refer to the [`edX Developer Stack`](https://github.com/openedx/devstack) instructions.
|
||||||
|
|
||||||
When not mounted, gradebook will run in the shared MFE container at http://apps.local.openedx.io/gradebook/course-v1:edX+DemoX+Demo_Course.
|
The web application runs on port **1994**, so when you go to `http://localhost:1994/course-v1:edX+DemoX+Demo_Course` you should see the UI (assuming you have such a Demo Course in your devstack). Note that you always have to provide a course id to actually see a gradebook.
|
||||||
|
|
||||||
When mounted in the tutor ``gradebook`` container, or when running a local (host) webpack dev server, the web application runs on port **1994**, so when you go to `http://apps.local.openedx.io:1994/gradebook/course-v1:edX+DemoX+Demo_Course` you should see the UI (assuming you have such a Demo Course in your devstack). Note that you always have to provide a course id to actually see a gradebook.
|
If you don't, you can see the log messages for the docker container by executing `make gradebook-logs` in the `devstack` directory.
|
||||||
|
|
||||||
(Note: This may not work in Tutor; these instructions are for the deprecated Devstack) You can see the log messages for the docker container by executing `make gradebook-logs` in the `devstack` directory.
|
|
||||||
|
|
||||||
Note that starting the container executes the `npm run start` script which will hot-reload JavaScript and Sass files changes, so you should (:crossed_fingers:) not need to do anything (other than wait) when making changes.
|
Note that starting the container executes the `npm run start` script which will hot-reload JavaScript and Sass files changes, so you should (:crossed_fingers:) not need to do anything (other than wait) when making changes.
|
||||||
|
|
||||||
## Plugins
|
## Configuring for local use in edx-platform
|
||||||
This MFE can be customized using [Frontend Plugin Framework](https://github.com/openedx/frontend-plugin-framework).
|
|
||||||
|
|
||||||
The parts of this MFE that can be customized in that manner are documented [here](/src/plugin-slots).
|
Assuming you've got the UI running at `http://localhost:1994`, you can configure the LMS in edx-platform
|
||||||
|
to point to your local gradebook from the instructor dashboard by putting this setting in `lms/env/private.py`:
|
||||||
|
```
|
||||||
|
WRITABLE_GRADEBOOK_URL = 'http://localhost:1994'
|
||||||
|
```
|
||||||
|
|
||||||
|
There are also several edx-platform waffle and feature flags you'll have to enable from the Django admin:
|
||||||
|
|
||||||
|
1. Grades > Persistent grades enabled flag. Add this flag if it doesn't exist,
|
||||||
|
check the ``enabled`` and ``enabled for all courses`` boxes.
|
||||||
|
|
||||||
|
2. Waffle > Switches. Add the ``grades.assume_zero_grade_if_absent`` switch and make it active.
|
||||||
|
|
||||||
|
3. Waffle_utils > Waffle flag course overrides. Activate waffle flags for courses where you want to enable Gradebook functionality:
|
||||||
|
- Enable Gradebook by adding the ``grades.writable_gradebook`` add checking the ``enabled`` box.
|
||||||
|
- Enable Bulk Grade Management by adding the ``grades.bulk_management`` flag and checking the ``enabled`` box.
|
||||||
|
|
||||||
|
Alternatively, you could add these as regular waffle flags to enable the functionality for all courses.
|
||||||
|
|
||||||
|
**NOTE:** IF the above flags are not configured correctly, the gradebook may appear to work, but will return bogus
|
||||||
|
numbers for grades. If your gradebook isn't accepting your changes, or the changes aren't resulting in sane,
|
||||||
|
recalculated grade values, verify you've set all flags correctly.
|
||||||
|
|
||||||
## Running tests
|
## Running tests
|
||||||
|
|
||||||
Run:
|
1. Assuming that you're operating in the context of the edX devstack,
|
||||||
|
run `gradebook-shell` from your devstack directory. This will start a bash shell inside your
|
||||||
``nvm use``
|
running gradebook container.
|
||||||
|
2. Run `make test` (which executes `npm run test`). This will run all of the gradebook tests.
|
||||||
``npm ci``
|
|
||||||
|
|
||||||
``npm test``
|
|
||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
@@ -141,49 +119,3 @@ Run:
|
|||||||
## Authentication with backend API services
|
## Authentication with backend API services
|
||||||
|
|
||||||
See the [`@edx/frontend-auth`](https://github.com/edx-unsupported/frontend-auth) repo for information about securing routes in your application that require user authentication.
|
See the [`@edx/frontend-auth`](https://github.com/edx-unsupported/frontend-auth) repo for information about securing routes in your application that require user authentication.
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
The code in this repository is licensed under the AGPLv3 unless otherwise
|
|
||||||
noted.
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
============
|
|
||||||
|
|
||||||
Contributions are very welcome. Please read [How To Contribute](https://docs.openedx.org/en/latest/developers/references/developer_guide/process/index.html) for details.
|
|
||||||
|
|
||||||
This project is currently accepting all types of contributions, bug fixes,
|
|
||||||
security fixes, maintenance work, or new features. However, please make sure
|
|
||||||
to have a discussion about your new feature idea with the maintainers prior to
|
|
||||||
beginning development to maximize the chances of your change being accepted.
|
|
||||||
You can start a conversation by creating a new issue on this repo summarizing
|
|
||||||
your idea.
|
|
||||||
|
|
||||||
Getting Help
|
|
||||||
===========
|
|
||||||
|
|
||||||
If you're having trouble, we have discussion forums at
|
|
||||||
https://discuss.openedx.org where you can connect with others in the community.
|
|
||||||
|
|
||||||
Our real-time conversations are on Slack. You can request a [Slack
|
|
||||||
invitation](https://openedx.org/slack), then join our
|
|
||||||
[community Slack workspace](https://openedx.slack.com/) Because this is a
|
|
||||||
frontend repository, the best place to discuss it would be in the
|
|
||||||
[#wg-frontend channel](https://openedx.slack.com/archives/C04BM6YC7A6).
|
|
||||||
|
|
||||||
For anything non-trivial, the best path is to open an issue in this repository
|
|
||||||
with as many details about the issue you are facing as you can provide.
|
|
||||||
|
|
||||||
https://github.com/openedx/frontend-app-gradebook/issues
|
|
||||||
|
|
||||||
For more information about these options, see the [Getting Help](https://openedx.org/community/connect) page.
|
|
||||||
|
|
||||||
The Open edX Code of Conduct
|
|
||||||
============================
|
|
||||||
|
|
||||||
All community members are expected to follow the [Open edX Code of Conduct](https://openedx.org/code-of-conduct/).
|
|
||||||
|
|
||||||
Reporting Security Issues
|
|
||||||
=========================
|
|
||||||
Please do not report security issues in public. Please email security@openedx.org.
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
const { createConfig } = require('@openedx/frontend-build');
|
const { createConfig } = require('@edx/frontend-build');
|
||||||
|
|
||||||
module.exports = createConfig('babel');
|
module.exports = createConfig('babel');
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# This file records information about this repo. Its use is described in OEP-55:
|
|
||||||
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html
|
|
||||||
apiVersion: backstage.io/v1alpha1
|
|
||||||
kind: Component
|
|
||||||
metadata:
|
|
||||||
name: "frontend-app-gradebook"
|
|
||||||
description: "The frontend (MFE) for Open edX Gradebook"
|
|
||||||
annotations:
|
|
||||||
openedx.org/arch-interest-groups: ""
|
|
||||||
openedx.org/release: "master"
|
|
||||||
spec:
|
|
||||||
owner: user:farhaanbukhsh
|
|
||||||
type: 'website'
|
|
||||||
lifecycle: 'experimental'
|
|
||||||
@@ -4,15 +4,15 @@ Instructions for setting up environments and data for testing Gradebook.
|
|||||||
|
|
||||||
## Set up a course with graded content
|
## Set up a course with graded content
|
||||||
|
|
||||||
A course with graded content is the first prerequisite to testing. Use an existing course (e.g. the DemoX Demonstration Course in Devstack) or see [Building and Running an edX Course > Developing Your Course](https://docs.openedx.org/en/latest/educators/quickstarts/build_a_course.html) for notes on how to develop a course from scratch.
|
A course with graded content is the first prerequisite to testing. Use an existing course (e.g. the DemoX Demonstration Course in Devstack) or see [Building and Running an edX Course > Developing Your Course](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/developing_course/index.html) for notes on how to develop a course from scratch.
|
||||||
|
|
||||||
Notably, the course needs a grading policy and subsections with scoreable content.
|
Notably, the course needs a grading policy and subsections with scoreable content.
|
||||||
After creating subsections with content, they need to be configured with an "Assignment Type" to be included in grading.
|
After creating subsections with content, they need to be configured with an "Assignment Type" to be included in grading.
|
||||||
|
|
||||||
Suggested resources:
|
Suggested resources:
|
||||||
- [Establishing a Grading Policy For Your Course](https://docs.openedx.org/en/latest/educators/how-tos/data/manage_learner_grades.html#review-how-grading-is-configured-for-your-course)
|
- [Establishing a Grading Policy For Your Course](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/grading/index.html)
|
||||||
- [Adding Exercises and Tools](https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_problems_exercises_tools.html)
|
- [Adding Exercises and Tools](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/grading/index.html)
|
||||||
- [Set the Assignment Type and Due Date for a Subsection](https://docs.openedx.org/en/latest/educators/how-tos/course_development/set_subsection_problem_date.html#set-the-assignment-type-and-due-date-for-a-subsection)
|
- [Set the Assignment Type and Due Date for a Subsection](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/developing_course/course_subsections.html#set-the-assignment-type-and-due-date-for-a-subsection)
|
||||||
|
|
||||||
## Enable Gradebook for course
|
## Enable Gradebook for course
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ Bulk Management is an added feature to allow modifying grades in bulk via CSV up
|
|||||||
|
|
||||||
## Create a Master's track for testing Master's-only features
|
## Create a Master's track for testing Master's-only features
|
||||||
|
|
||||||
[source - note: possibly outdated, edx.org-specific](https://openedx.atlassian.net/wiki/spaces/MS/pages/1453818012/Add+a+learner+into+a+master+s+track)
|
[source](https://openedx.atlassian.net/wiki/spaces/MS/pages/1453818012/Add+a+learner+into+a+master+s+track)
|
||||||
|
|
||||||
Add a Master's track in your course:
|
Add a Master's track in your course:
|
||||||
- As an admin user, go to Django Admin (`{lms-url}/admin`) > Course Modes and add a new course mode
|
- As an admin user, go to Django Admin (`{lms-url}/admin`) > Course Modes and add a new course mode
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
const { createConfig } = require('@openedx/frontend-build');
|
const { createConfig } = require('@edx/frontend-build');
|
||||||
|
|
||||||
module.exports = createConfig('jest', {
|
module.exports = createConfig('jest', {
|
||||||
setupFilesAfterEnv: [
|
setupFilesAfterEnv: [
|
||||||
'<rootDir>/src/setupTest.js',
|
'<rootDir>/src/setupTest.js',
|
||||||
],
|
],
|
||||||
modulePaths: ['<rootDir>/src/'],
|
modulePaths: ['<rootDir>/src/'],
|
||||||
|
snapshotSerializers: [
|
||||||
|
'enzyme-to-json/serializer',
|
||||||
|
],
|
||||||
coveragePathIgnorePatterns: [
|
coveragePathIgnorePatterns: [
|
||||||
'src/segment.js',
|
'src/segment.js',
|
||||||
'src/postcss.config.js',
|
'src/postcss.config.js',
|
||||||
|
|||||||
9
openedx.yaml
Normal file
9
openedx.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# This file describes this Open edX repo, as described in OEP-2:
|
||||||
|
# http://open-edx-proposals.readthedocs.io/en/latest/oeps/oep-0002.html#specification
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- frontend-app
|
||||||
|
- masters
|
||||||
|
oeps:
|
||||||
|
oep-2: true # Repository metadata
|
||||||
|
openedx-release: {ref: master}
|
||||||
48204
package-lock.json
generated
48204
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@@ -9,13 +9,12 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "fedx-scripts webpack",
|
"build": "fedx-scripts webpack",
|
||||||
"is-es5": "es-check es5 ./dist/*.js",
|
"is-es5": "es-check es5 ./dist/*.js",
|
||||||
"i18n_extract": "fedx-scripts formatjs extract",
|
"i18n_extract": "BABEL_ENV=i18n fedx-scripts babel src --quiet > /dev/null",
|
||||||
"lint": "fedx-scripts eslint --ext .jsx,.js src/",
|
"lint": "fedx-scripts eslint --ext .jsx,.js src/",
|
||||||
"lint-fix": "fedx-scripts eslint --fix --ext .jsx,.js src/",
|
"lint-fix": "fedx-scripts eslint --fix --ext .jsx,.js src/",
|
||||||
"prepush": "npm run lint",
|
"prepush": "npm run lint",
|
||||||
"semantic-release": "semantic-release",
|
"semantic-release": "semantic-release",
|
||||||
"start": "fedx-scripts webpack-dev-server --progress",
|
"start": "fedx-scripts webpack-dev-server --progress",
|
||||||
"dev": "PUBLIC_PATH=/gradebook/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
|
|
||||||
"test": "TZ=GMT fedx-scripts jest --coverage --passWithNoTests",
|
"test": "TZ=GMT fedx-scripts jest --coverage --passWithNoTests",
|
||||||
"watch-tests": "jest --watch"
|
"watch-tests": "jest --watch"
|
||||||
},
|
},
|
||||||
@@ -29,34 +28,33 @@
|
|||||||
"extends @edx/browserslist-config"
|
"extends @edx/browserslist-config"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
"@edx/brand": "npm:@edx/brand-openedx@^1.2.0",
|
||||||
"@edx/frontend-component-footer": "^14.6.0",
|
"@edx/frontend-component-footer": "^12.0.0",
|
||||||
"@edx/frontend-component-header": "^6.4.0",
|
"@edx/frontend-component-header": "^4.0.0",
|
||||||
"@edx/frontend-platform": "^8.3.1",
|
"@edx/frontend-platform": "^4.2.0",
|
||||||
"@edx/openedx-atlas": "^0.6.0",
|
"@edx/paragon": "^19.25.4",
|
||||||
"@edx/react-unit-test-utils": "^4.0.0",
|
|
||||||
"@edx/reactifex": "^2.1.1",
|
"@edx/reactifex": "^2.1.1",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.11.2",
|
"@fortawesome/free-brands-svg-icons": "^5.11.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.5",
|
"@fortawesome/react-fontawesome": "^0.1.5",
|
||||||
"@openedx/frontend-plugin-framework": "^1.6.0",
|
|
||||||
"@openedx/paragon": "^22.16.0",
|
|
||||||
"@redux-beacon/segment": "^1.0.0",
|
"@redux-beacon/segment": "^1.0.0",
|
||||||
"@reduxjs/toolkit": "^1.5.1",
|
"@reduxjs/toolkit": "^1.5.1",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"core-js": "3.6.5",
|
"core-js": "3.6.5",
|
||||||
"email-prop-type": "^1.1.7",
|
"email-prop-type": "^1.1.7",
|
||||||
|
"enzyme": "^3.10.0",
|
||||||
|
"enzyme-to-json": "^3.6.2",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
"query-string": "6.13.0",
|
"query-string": "6.13.0",
|
||||||
"react": "^18.3.1",
|
"react": "16.14.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "16.14.0",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-redux": "^7.2.9",
|
"react-redux": "^7.1.1",
|
||||||
"react-router": "6.15.0",
|
"react-router": "5.2.0",
|
||||||
"react-router-dom": "6.15.0",
|
"react-router-dom": "5.2.0",
|
||||||
"react-router-redux": "^5.0.0-alpha.9",
|
"react-router-redux": "^5.0.0-alpha.9",
|
||||||
"redux": "4.0.5",
|
"redux": "4.0.5",
|
||||||
"redux-beacon": "^2.1.0",
|
"redux-beacon": "^2.1.0",
|
||||||
@@ -69,15 +67,20 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@edx/browserslist-config": "^1.1.1",
|
"@edx/browserslist-config": "^1.1.1",
|
||||||
"@openedx/frontend-build": "^14.3.3",
|
"@edx/frontend-build": "^12.4.15",
|
||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^12.1.0",
|
||||||
|
"axios": "0.21.2",
|
||||||
|
"axios-mock-adapter": "^1.17.0",
|
||||||
|
"enzyme-adapter-react-16": "^1.14.0",
|
||||||
"es-check": "^2.3.0",
|
"es-check": "^2.3.0",
|
||||||
"fetch-mock": "^12.2.0",
|
"fetch-mock": "^6.5.2",
|
||||||
|
"husky": "2.7.0",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^26.6.3",
|
||||||
"react-dev-utils": "^12.0.1",
|
"react-dev-utils": "^12.0.1",
|
||||||
"react-test-renderer": "^18.3.1",
|
"react-test-renderer": "^16.10.1",
|
||||||
"reactifex": "1.1.1",
|
"reactifex": "1.1.1",
|
||||||
"redux-mock-store": "^1.5.3"
|
"redux-mock-store": "^1.5.3",
|
||||||
|
"semantic-release": "^19.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/App.jsx
18
src/App.jsx
@@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Route, Routes } from 'react-router-dom';
|
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
import { AppProvider } from '@edx/frontend-platform/react';
|
import { AppProvider } from '@edx/frontend-platform/react';
|
||||||
|
|
||||||
import { FooterSlot } from '@edx/frontend-component-footer';
|
import Footer from '@edx/frontend-component-footer';
|
||||||
import Header from '@edx/frontend-component-header';
|
import Header from '@edx/frontend-component-header';
|
||||||
|
|
||||||
|
import { routePath } from 'data/constants/app';
|
||||||
import store from 'data/store';
|
import store from 'data/store';
|
||||||
import GradebookPage from 'containers/GradebookPage';
|
import GradebookPage from 'containers/GradebookPage';
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
@@ -14,18 +15,21 @@ import Head from './head/Head';
|
|||||||
const App = () => (
|
const App = () => (
|
||||||
<AppProvider store={store}>
|
<AppProvider store={store}>
|
||||||
<Head />
|
<Head />
|
||||||
|
<Router>
|
||||||
<div>
|
<div>
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<Routes>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
path="/:courseId"
|
exact
|
||||||
element={<GradebookPage />}
|
path={routePath}
|
||||||
|
component={GradebookPage}
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Switch>
|
||||||
</main>
|
</main>
|
||||||
<FooterSlot />
|
<Footer logo={process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG} />
|
||||||
</div>
|
</div>
|
||||||
|
</Router>
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// frontend-app-*/src/index.scss
|
// frontend-app-*/src/index.scss
|
||||||
@import "~@edx/brand/paragon/fonts";
|
@import "~@edx/brand/paragon/fonts";
|
||||||
@import "~@edx/brand/paragon/variables";
|
@import "~@edx/brand/paragon/variables";
|
||||||
@import "~@openedx/paragon/scss/core/core";
|
@import "~@edx/paragon/scss/core/core";
|
||||||
@import "~@edx/brand/paragon/overrides";
|
@import "~@edx/brand/paragon/overrides";
|
||||||
|
|
||||||
$fa-font-path: "~font-awesome/fonts";
|
$fa-font-path: "~font-awesome/fonts";
|
||||||
|
|||||||
@@ -1,63 +1,80 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { Route } from 'react-router-dom';
|
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
|
||||||
|
import { AppProvider } from '@edx/frontend-platform/react';
|
||||||
|
|
||||||
|
import Footer from '@edx/frontend-component-footer';
|
||||||
|
import Header from '@edx/frontend-component-header';
|
||||||
|
|
||||||
|
import { routePath } from 'data/constants/app';
|
||||||
import store from 'data/store';
|
import store from 'data/store';
|
||||||
import GradebookPage from 'containers/GradebookPage';
|
import GradebookPage from 'containers/GradebookPage';
|
||||||
|
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import Head from './head/Head';
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({
|
jest.mock('react-router-dom', () => ({
|
||||||
BrowserRouter: () => 'BrowserRouter',
|
BrowserRouter: () => 'BrowserRouter',
|
||||||
Route: () => 'Route',
|
Route: () => 'Route',
|
||||||
Routes: () => 'Routes',
|
Switch: () => 'Switch',
|
||||||
}));
|
}));
|
||||||
jest.mock('@edx/frontend-platform/react', () => ({
|
jest.mock('@edx/frontend-platform/react', () => ({
|
||||||
AppProvider: () => 'AppProvider',
|
AppProvider: () => 'AppProvider',
|
||||||
}));
|
}));
|
||||||
jest.mock('@edx/frontend-component-footer', () => ({ FooterSlot: 'FooterSlot' }));
|
jest.mock('data/constants/app', () => ({
|
||||||
|
routePath: '/:courseId',
|
||||||
|
}));
|
||||||
|
jest.mock('@edx/frontend-component-footer', () => 'Footer');
|
||||||
jest.mock('data/store', () => 'testStore');
|
jest.mock('data/store', () => 'testStore');
|
||||||
jest.mock('containers/GradebookPage', () => 'GradebookPage');
|
jest.mock('containers/GradebookPage', () => 'GradebookPage');
|
||||||
jest.mock('@edx/frontend-component-header', () => 'Header');
|
jest.mock('@edx/frontend-component-header', () => 'Header');
|
||||||
jest.mock('./head/Head', () => 'Head');
|
|
||||||
|
|
||||||
|
const logo = 'fakeLogo.png';
|
||||||
let el;
|
let el;
|
||||||
let secondChild;
|
let router;
|
||||||
|
|
||||||
describe('App router component', () => {
|
describe('App router component', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(shallow(<App />).snapshot).toMatchSnapshot();
|
expect(shallow(<App />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
describe('component', () => {
|
describe('component', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG = logo;
|
||||||
el = shallow(<App />);
|
el = shallow(<App />);
|
||||||
secondChild = el.instance.children;
|
router = el.childAt(1);
|
||||||
});
|
});
|
||||||
describe('AppProvider', () => {
|
describe('AppProvider', () => {
|
||||||
test('AppProvider is the parent component, passed the redux store props', () => {
|
test('AppProvider is the parent component, passed the redux store props', () => {
|
||||||
expect(el.instance.type).toBe('AppProvider');
|
expect(el.type()).toBe(AppProvider);
|
||||||
expect(el.instance.props.store).toEqual(store);
|
expect(el.props().store).toEqual(store);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Head', () => {
|
describe('Head', () => {
|
||||||
test('first child of AppProvider', () => {
|
test('first child of AppProvider', () => {
|
||||||
expect(el.instance.children[0].type).toBe('Head');
|
expect(el.childAt(0).type()).toBe(Head);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Router', () => {
|
describe('Router', () => {
|
||||||
test('second child of AppProvider', () => {
|
test('second child of AppProvider', () => {
|
||||||
expect(secondChild[1].type).toBe('div');
|
expect(router.type()).toBe(Router);
|
||||||
});
|
});
|
||||||
test('Header is above/outside-of the routing', () => {
|
test('Header is above/outside-of the routing', () => {
|
||||||
expect(secondChild[1].children[0].type).toBe('Header');
|
expect(router.childAt(0).childAt(0).type()).toBe(Header);
|
||||||
expect(secondChild[1].children[1].type).toBe('main');
|
expect(router.childAt(0).childAt(1).type()).toBe('main');
|
||||||
});
|
});
|
||||||
test('Routing - GradebookPage is only route', () => {
|
test('Routing - GradebookPage is only route', () => {
|
||||||
expect(secondChild[1].findByType(Route)).toHaveLength(1);
|
expect(router.find('main')).toEqual(shallow(
|
||||||
expect(secondChild[1].findByType(Route)[0].props.path).toEqual('/:courseId');
|
<main>
|
||||||
expect(secondChild[1].findByType(Route)[0].props.element.type).toEqual(GradebookPage);
|
<Switch>
|
||||||
});
|
<Route exact path={routePath} component={GradebookPage} />
|
||||||
|
</Switch>
|
||||||
|
</main>,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('Footer logo drawn from env variable', () => {
|
||||||
|
expect(router.find(Footer).props().logo).toEqual(logo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,17 +5,20 @@ exports[`App router component snapshot 1`] = `
|
|||||||
store="testStore"
|
store="testStore"
|
||||||
>
|
>
|
||||||
<Head />
|
<Head />
|
||||||
|
<BrowserRouter>
|
||||||
<div>
|
<div>
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<Routes>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
element={<GradebookPage />}
|
component="GradebookPage"
|
||||||
|
exact={true}
|
||||||
path="/:courseId"
|
path="/:courseId"
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Switch>
|
||||||
</main>
|
</main>
|
||||||
<FooterSlot />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
</BrowserRouter>
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { Alert } from '@openedx/paragon';
|
import { Alert } from '@edx/paragon';
|
||||||
|
|
||||||
import selectors from 'data/selectors';
|
import selectors from 'data/selectors';
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { Alert } from '@openedx/paragon';
|
import { Alert } from '@edx/paragon';
|
||||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import selectors from 'data/selectors';
|
import selectors from 'data/selectors';
|
||||||
@@ -12,7 +12,7 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
|
|||||||
defineMessages: m => m,
|
defineMessages: m => m,
|
||||||
FormattedMessage: () => 'FormattedMessage',
|
FormattedMessage: () => 'FormattedMessage',
|
||||||
}));
|
}));
|
||||||
jest.mock('@openedx/paragon', () => ({
|
jest.mock('@edx/paragon', () => ({
|
||||||
Alert: () => 'Alert',
|
Alert: () => 'Alert',
|
||||||
}));
|
}));
|
||||||
jest.mock('data/selectors', () => ({
|
jest.mock('data/selectors', () => ({
|
||||||
@@ -35,17 +35,17 @@ describe('BulkManagementAlerts', () => {
|
|||||||
el = shallow(<BulkManagementAlerts />);
|
el = shallow(<BulkManagementAlerts />);
|
||||||
});
|
});
|
||||||
test('snapshot - bulkImportError closed, success closed', () => {
|
test('snapshot - bulkImportError closed, success closed', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('closed danger alert', () => {
|
test('closed danger alert', () => {
|
||||||
expect(el.instance.children[0].type).toBe('Alert');
|
expect(el.childAt(0).is(Alert)).toEqual(true);
|
||||||
expect(el.instance.findByType(Alert)[0].props.show).toEqual(false);
|
expect(el.childAt(0).props().show).toEqual(false);
|
||||||
expect(el.instance.findByType(Alert)[0].props.variant).toEqual('danger');
|
expect(el.childAt(0).props().variant).toEqual('danger');
|
||||||
});
|
});
|
||||||
test('closed success alert', () => {
|
test('closed success alert', () => {
|
||||||
expect(el.instance.children[1].type).toBe('Alert');
|
expect(el.childAt(1).is(Alert)).toEqual(true);
|
||||||
expect(el.instance.findByType(Alert)[1].props.show).toEqual(false);
|
expect(el.childAt(1).props().show).toEqual(false);
|
||||||
expect(el.instance.findByType(Alert)[1].props.variant).toEqual('success');
|
expect(el.childAt(1).props().variant).toEqual('success');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('no errer, no upload success', () => {
|
describe('no errer, no upload success', () => {
|
||||||
@@ -57,19 +57,19 @@ describe('BulkManagementAlerts', () => {
|
|||||||
'success alert open with messages.successDialog',
|
'success alert open with messages.successDialog',
|
||||||
];
|
];
|
||||||
test(`snapshot - ${assertions.join(', ')}`, () => {
|
test(`snapshot - ${assertions.join(', ')}`, () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('open danger alert with bulkImportError content', () => {
|
test('open danger alert with bulkImportError content', () => {
|
||||||
expect(el.instance.children[0].type).toBe('Alert');
|
expect(el.childAt(0).is(Alert)).toEqual(true);
|
||||||
expect(el.instance.findByType(Alert)[0].children[0].el).toEqual(errorMessage);
|
expect(el.childAt(0).children().text()).toEqual(errorMessage);
|
||||||
expect(el.instance.findByType(Alert)[0].props.show).toEqual(true);
|
expect(el.childAt(0).props().show).toEqual(true);
|
||||||
});
|
});
|
||||||
test('open success alert with messages.successDialog content', () => {
|
test('open success alert with messages.successDialog content', () => {
|
||||||
expect(el.instance.children[1].type).toBe('Alert');
|
expect(el.childAt(1).is(Alert)).toEqual(true);
|
||||||
expect(el.shallowWrapper.props.children[1].props.children).toEqual(
|
expect(el.childAt(1).children().getElement()).toEqual(
|
||||||
<FormattedMessage {...messages.successDialog} />,
|
<FormattedMessage {...messages.successDialog} />,
|
||||||
);
|
);
|
||||||
expect(el.instance.children[1].props.show).toEqual(true);
|
expect(el.childAt(1).props().show).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import { bulkManagementColumns } from 'data/constants/app';
|
import { bulkManagementColumns } from 'data/constants/app';
|
||||||
import selectors from 'data/selectors';
|
import selectors from 'data/selectors';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable import/no-named-as-default */
|
/* eslint-disable import/no-named-as-default */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import selectors from 'data/selectors';
|
import selectors from 'data/selectors';
|
||||||
import { bulkManagementColumns } from 'data/constants/app';
|
import { bulkManagementColumns } from 'data/constants/app';
|
||||||
@@ -9,7 +9,7 @@ import { bulkManagementColumns } from 'data/constants/app';
|
|||||||
import ResultsSummary from './ResultsSummary';
|
import ResultsSummary from './ResultsSummary';
|
||||||
import { HistoryTable, mapStateToProps } from './HistoryTable';
|
import { HistoryTable, mapStateToProps } from './HistoryTable';
|
||||||
|
|
||||||
jest.mock('@openedx/paragon', () => ({ DataTable: () => 'DataTable' }));
|
jest.mock('@edx/paragon', () => ({ DataTable: () => 'DataTable' }));
|
||||||
|
|
||||||
jest.mock('@edx/frontend-platform/i18n', () => ({
|
jest.mock('@edx/frontend-platform/i18n', () => ({
|
||||||
defineMessages: m => m,
|
defineMessages: m => m,
|
||||||
@@ -56,12 +56,12 @@ describe('HistoryTable', () => {
|
|||||||
el = shallow(<HistoryTable {...props} />);
|
el = shallow(<HistoryTable {...props} />);
|
||||||
});
|
});
|
||||||
test('snapshot - loads formatted table', () => {
|
test('snapshot - loads formatted table', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
describe('history table', () => {
|
describe('history table', () => {
|
||||||
let table;
|
let table;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
table = el.instance.findByType(DataTable);
|
table = el.find(DataTable);
|
||||||
});
|
});
|
||||||
describe('data (from bulkManagementHistory.map(this.formatHistoryRow)', () => {
|
describe('data (from bulkManagementHistory.map(this.formatHistoryRow)', () => {
|
||||||
const fieldAssertions = [
|
const fieldAssertions = [
|
||||||
@@ -70,10 +70,10 @@ describe('HistoryTable', () => {
|
|||||||
'forwards the rest',
|
'forwards the rest',
|
||||||
];
|
];
|
||||||
test(`snapshot: ${fieldAssertions.join(', ')}`, () => {
|
test(`snapshot: ${fieldAssertions.join(', ')}`, () => {
|
||||||
expect(table[0].props.data).toMatchSnapshot();
|
expect(table.props().data).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test(fieldAssertions.join(', '), () => {
|
test(fieldAssertions.join(', '), () => {
|
||||||
const rows = table[0].props.data;
|
const rows = table.props().data;
|
||||||
expect(rows[0].resultsSummary).toEqual(<ResultsSummary {...entry1.resultsSummary} />);
|
expect(rows[0].resultsSummary).toEqual(<ResultsSummary {...entry1.resultsSummary} />);
|
||||||
expect(rows[0].user).toEqual(<span className="wrap-text-in-cell">{entry1.user}</span>);
|
expect(rows[0].user).toEqual(<span className="wrap-text-in-cell">{entry1.user}</span>);
|
||||||
expect(
|
expect(
|
||||||
@@ -87,7 +87,7 @@ describe('HistoryTable', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('columns from bulkManagementColumns', () => {
|
test('columns from bulkManagementColumns', () => {
|
||||||
expect(table[0].props.columns).toEqual(bulkManagementColumns);
|
expect(table.props().columns).toEqual(bulkManagementColumns);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Hyperlink, Icon } from '@openedx/paragon';
|
import { Hyperlink, Icon } from '@edx/paragon';
|
||||||
import { Download } from '@openedx/paragon/icons';
|
import { Download } from '@edx/paragon/icons';
|
||||||
|
|
||||||
import lms from 'data/services/lms';
|
import lms from 'data/services/lms';
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { Download } from '@openedx/paragon/icons';
|
import { Icon } from '@edx/paragon';
|
||||||
|
import { Download } from '@edx/paragon/icons';
|
||||||
|
|
||||||
import lms from 'data/services/lms';
|
import lms from 'data/services/lms';
|
||||||
import ResultsSummary from './ResultsSummary';
|
import ResultsSummary from './ResultsSummary';
|
||||||
|
|
||||||
jest.mock('@openedx/paragon', () => ({
|
jest.mock('@edx/paragon', () => ({
|
||||||
Hyperlink: () => 'Hyperlink',
|
Hyperlink: () => 'Hyperlink',
|
||||||
Icon: () => 'Icon',
|
Icon: () => 'Icon',
|
||||||
}));
|
}));
|
||||||
jest.mock('@openedx/paragon/icons', () => ({
|
jest.mock('@edx/paragon/icons', () => ({
|
||||||
Download: 'DownloadIcon',
|
Download: 'DownloadIcon',
|
||||||
}));
|
}));
|
||||||
jest.mock('data/services/lms', () => ({
|
jest.mock('data/services/lms', () => ({
|
||||||
@@ -34,19 +35,19 @@ describe('ResultsSummary component', () => {
|
|||||||
el = shallow(<ResultsSummary {...props} />);
|
el = shallow(<ResultsSummary {...props} />);
|
||||||
});
|
});
|
||||||
test(`snapshot - ${assertions.join(', ')}`, () => {
|
test(`snapshot - ${assertions.join(', ')}`, () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('Hyperlink has target="_blank" and rel="noopener noreferrer"', () => {
|
test('Hyperlink has target="_blank" and rel="noopener noreferrer"', () => {
|
||||||
expect(el.instance.props.target).toEqual('_blank');
|
expect(el.props().target).toEqual('_blank');
|
||||||
expect(el.instance.props.rel).toEqual('noopener noreferrer');
|
expect(el.props().rel).toEqual('noopener noreferrer');
|
||||||
});
|
});
|
||||||
test('Hyperlink has href to bulkGradesUrl', () => {
|
test('Hyperlink has href to bulkGradesUrl', () => {
|
||||||
expect(el.instance.props.href).toEqual(lms.urls.bulkGradesUrlByRow(props.rowId));
|
expect(el.props().href).toEqual(lms.urls.bulkGradesUrlByRow(props.rowId));
|
||||||
});
|
});
|
||||||
test('displays Download Icon and text', () => {
|
test('displays Download Icon and text', () => {
|
||||||
const icon = el.instance.children[0];
|
const icon = el.childAt(0);
|
||||||
expect(icon.type).toEqual('Icon');
|
expect(icon.is(Icon)).toEqual(true);
|
||||||
expect(icon.props.src).toEqual(Download);
|
expect(icon.props().src).toEqual(Download);
|
||||||
expect(el.instance.children[1].el).toEqual(props.text);
|
expect(el.childAt(1).text()).toEqual(props.text);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`HistoryTable component snapshot history table data (from bulkManagementHistory.map(this.formatHistoryRow) snapshot: maps resultsSummay to ResultsSummary, wraps filename and user, forwards the rest 1`] = `
|
exports[`HistoryTable component snapshot history table data (from bulkManagementHistory.map(this.formatHistoryRow) snapshot: maps resultsSummay to ResultsSummary, wraps filename and user, forwards the rest 1`] = `
|
||||||
[
|
Array [
|
||||||
{
|
Object {
|
||||||
"filename": <span
|
"filename": <span
|
||||||
className="wrap-text-in-cell"
|
className="wrap-text-in-cell"
|
||||||
>
|
>
|
||||||
@@ -20,7 +20,7 @@ exports[`HistoryTable component snapshot history table data (from bulkManagement
|
|||||||
Eifel
|
Eifel
|
||||||
</span>,
|
</span>,
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"filename": <span
|
"filename": <span
|
||||||
className="wrap-text-in-cell"
|
className="wrap-text-in-cell"
|
||||||
>
|
>
|
||||||
@@ -45,26 +45,26 @@ exports[`HistoryTable component snapshot snapshot - loads formatted table 1`] =
|
|||||||
<DataTable
|
<DataTable
|
||||||
className="table-striped"
|
className="table-striped"
|
||||||
columns={
|
columns={
|
||||||
[
|
Array [
|
||||||
{
|
Object {
|
||||||
"Header": "Gradebook",
|
"Header": "Gradebook",
|
||||||
"accessor": "filename",
|
"accessor": "filename",
|
||||||
"columnSortable": false,
|
"columnSortable": false,
|
||||||
"width": "col-5",
|
"width": "col-5",
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"Header": "Download Summary",
|
"Header": "Download Summary",
|
||||||
"accessor": "resultsSummary",
|
"accessor": "resultsSummary",
|
||||||
"columnSortable": false,
|
"columnSortable": false,
|
||||||
"width": "col",
|
"width": "col",
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"Header": "Who",
|
"Header": "Who",
|
||||||
"accessor": "user",
|
"accessor": "user",
|
||||||
"columnSortable": false,
|
"columnSortable": false,
|
||||||
"width": "col-1",
|
"width": "col-1",
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"Header": "When",
|
"Header": "When",
|
||||||
"accessor": "timeUploaded",
|
"accessor": "timeUploaded",
|
||||||
"columnSortable": false,
|
"columnSortable": false,
|
||||||
@@ -73,8 +73,8 @@ exports[`HistoryTable component snapshot snapshot - loads formatted table 1`] =
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
data={
|
data={
|
||||||
[
|
Array [
|
||||||
{
|
Object {
|
||||||
"filename": <span
|
"filename": <span
|
||||||
className="wrap-text-in-cell"
|
className="wrap-text-in-cell"
|
||||||
>
|
>
|
||||||
@@ -92,7 +92,7 @@ exports[`HistoryTable component snapshot snapshot - loads formatted table 1`] =
|
|||||||
Eifel
|
Eifel
|
||||||
</span>,
|
</span>,
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"filename": <span
|
"filename": <span
|
||||||
className="wrap-text-in-cell"
|
className="wrap-text-in-cell"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ exports[`ResultsSummary component snapshot - safe hyperlink with bulkGradesUrl w
|
|||||||
<Hyperlink
|
<Hyperlink
|
||||||
destination="www.edx.org"
|
destination="www.edx.org"
|
||||||
href={
|
href={
|
||||||
{
|
Object {
|
||||||
"url": {
|
"url": Object {
|
||||||
"rowId": 42,
|
"rowId": 42,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable import/no-named-as-default */
|
/* eslint-disable import/no-named-as-default */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { BulkManagementHistoryView } from '.';
|
import { BulkManagementHistoryView } from '.';
|
||||||
@@ -24,23 +24,20 @@ describe('BulkManagementHistoryView', () => {
|
|||||||
'<HistoryTable />',
|
'<HistoryTable />',
|
||||||
];
|
];
|
||||||
test(`snapshot - loads ${snapshotSegments.join(', ')}`, () => {
|
test(`snapshot - loads ${snapshotSegments.join(', ')}`, () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('heading - h4 loaded from messages', () => {
|
test('heading - h4 loaded from messages', () => {
|
||||||
const heading = el.instance.findByType('h4')[0];
|
const heading = el.find('h4');
|
||||||
const expectedHeading = shallow(
|
expect(heading.getElement()).toEqual((
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage {...messages.heading} />
|
<FormattedMessage {...messages.heading} />
|
||||||
</h4>,
|
</h4>
|
||||||
);
|
));
|
||||||
|
|
||||||
expect(heading.el.type).toEqual(expectedHeading.type);
|
|
||||||
expect(heading.el.props).toEqual(expectedHeading.props);
|
|
||||||
});
|
});
|
||||||
test('heading, then alerts, then upload form, then table', () => {
|
test('heading, then alerts, then upload form, then table', () => {
|
||||||
expect(el.instance.children[0].type).toEqual('h4');
|
expect(el.childAt(0).is('h4')).toEqual(true);
|
||||||
expect(el.instance.children[2].type).toEqual(BulkManagementAlerts);
|
expect(el.childAt(2).is(BulkManagementAlerts)).toEqual(true);
|
||||||
expect(el.instance.children[3].type).toEqual(HistoryTable);
|
expect(el.childAt(3).is(HistoryTable)).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Hyperlink } from '@openedx/paragon';
|
import { Hyperlink } from '@edx/paragon';
|
||||||
import { getConfig } from '@edx/frontend-platform';
|
import { getConfig } from '@edx/frontend-platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { getConfig } from '@edx/frontend-platform';
|
import { getConfig } from '@edx/frontend-platform';
|
||||||
|
|
||||||
import Header from '.';
|
import Header from '.';
|
||||||
|
|
||||||
jest.mock('@openedx/paragon', () => ({
|
jest.mock('@edx/paragon', () => ({
|
||||||
Hyperlink: () => 'Hyperlink',
|
Hyperlink: () => 'Hyperlink',
|
||||||
}));
|
}));
|
||||||
jest.mock('@edx/frontend-platform', () => ({
|
jest.mock('@edx/frontend-platform', () => ({
|
||||||
@@ -16,6 +16,6 @@ describe('Header', () => {
|
|||||||
test('snapshot - has edx link with logo url', () => {
|
test('snapshot - has edx link with logo url', () => {
|
||||||
const url = 'www.ourLogo.url';
|
const url = 'www.ourLogo.url';
|
||||||
getConfig.mockReturnValue({ LOGO_URL: url });
|
getConfig.mockReturnValue({ LOGO_URL: url });
|
||||||
expect(shallow(<Header />).snapshot).toMatchSnapshot();
|
expect(shallow(<Header />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ exports[`AssignmentFilter component render snapshot 1`] = `
|
|||||||
label="Assignment"
|
label="Assignment"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
options={
|
options={
|
||||||
[
|
Array [
|
||||||
<option
|
<option
|
||||||
value=""
|
value=""
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import SelectGroup from '../SelectGroup';
|
import SelectGroup from '../SelectGroup';
|
||||||
@@ -38,10 +38,10 @@ describe('AssignmentFilter component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('filter options', () => {
|
test('filter options', () => {
|
||||||
const { options } = el.instance.findByType(SelectGroup)[0].props;
|
const { options } = el.find(SelectGroup).props();
|
||||||
expect(options.length).toEqual(5);
|
expect(options.length).toEqual(5);
|
||||||
const testOption = assignmentFilterOptions[0];
|
const testOption = assignmentFilterOptions[0];
|
||||||
const optionProps = options[1].props;
|
const optionProps = options[1].props;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import useAssignmentGradeFilterData from './hooks';
|
import useAssignmentGradeFilterData from './hooks';
|
||||||
import messages from '../messages';
|
import messages from '../messages';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import PercentGroup from '../PercentGroup';
|
import PercentGroup from '../PercentGroup';
|
||||||
import useAssignmentGradeFilterData from './hooks';
|
import useAssignmentGradeFilterData from './hooks';
|
||||||
@@ -37,20 +37,20 @@ describe('AssignmentFilter component', () => {
|
|||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
describe('with selected assignment', () => {
|
describe('with selected assignment', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
it('renders a PercentGroup for both Max and Min filters', () => {
|
it('renders a PercentGroup for both Max and Min filters', () => {
|
||||||
let { props } = el.instance.findByType(PercentGroup)[0];
|
let props = el.find(PercentGroup).at(0).props();
|
||||||
expect(props.value).toEqual(hookData.assignmentGradeMin);
|
expect(props.value).toEqual(hookData.assignmentGradeMin);
|
||||||
expect(props.disabled).toEqual(false);
|
expect(props.disabled).toEqual(false);
|
||||||
expect(props.onChange).toEqual(hookData.handleSetMin);
|
expect(props.onChange).toEqual(hookData.handleSetMin);
|
||||||
props = el.instance.findByType(PercentGroup)[1].props;
|
props = el.find(PercentGroup).at(1).props();
|
||||||
expect(props.value).toEqual(hookData.assignmentGradeMax);
|
expect(props.value).toEqual(hookData.assignmentGradeMax);
|
||||||
expect(props.disabled).toEqual(false);
|
expect(props.disabled).toEqual(false);
|
||||||
expect(props.onChange).toEqual(hookData.handleSetMax);
|
expect(props.onChange).toEqual(hookData.handleSetMax);
|
||||||
});
|
});
|
||||||
it('renders a submit button', () => {
|
it('renders a submit button', () => {
|
||||||
const { props } = el.instance.findByType(Button)[0];
|
const props = el.find(Button).props();
|
||||||
expect(props.disabled).toEqual(false);
|
expect(props.disabled).toEqual(false);
|
||||||
expect(props.onClick).toEqual(hookData.handleSubmit);
|
expect(props.onClick).toEqual(hookData.handleSubmit);
|
||||||
});
|
});
|
||||||
@@ -64,12 +64,12 @@ describe('AssignmentFilter component', () => {
|
|||||||
el = shallow(<AssignmentFilter updateQueryParams={updateQueryParams} />);
|
el = shallow(<AssignmentFilter updateQueryParams={updateQueryParams} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
it('disables controls', () => {
|
it('disables controls', () => {
|
||||||
let { props } = el.instance.findByType(PercentGroup)[0];
|
let props = el.find(PercentGroup).at(0).props();
|
||||||
expect(props.disabled).toEqual(true);
|
expect(props.disabled).toEqual(true);
|
||||||
props = el.instance.findByType(PercentGroup)[1].props;
|
props = el.find(PercentGroup).at(1).props();
|
||||||
expect(props.disabled).toEqual(true);
|
expect(props.disabled).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ exports[`AssignmentFilterType component render snapshot 1`] = `
|
|||||||
label="Assignment Types"
|
label="Assignment Types"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
options={
|
options={
|
||||||
[
|
Array [
|
||||||
<option
|
<option
|
||||||
value=""
|
value=""
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import SelectGroup from '../SelectGroup';
|
import SelectGroup from '../SelectGroup';
|
||||||
@@ -34,10 +34,10 @@ describe('AssignmentFilterType component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('filter options', () => {
|
test('filter options', () => {
|
||||||
const { options } = el.instance.findByType(SelectGroup)[0].props;
|
const { options } = el.find(SelectGroup).props();
|
||||||
expect(options.length).toEqual(5);
|
expect(options.length).toEqual(5);
|
||||||
const optionProps = options[1].props;
|
const optionProps = options[1].props;
|
||||||
expect(optionProps.value).toEqual(assignmentTypes[0]);
|
expect(optionProps.value).toEqual(assignmentTypes[0]);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import messages from '../messages';
|
import messages from '../messages';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import PercentGroup from '../PercentGroup';
|
import PercentGroup from '../PercentGroup';
|
||||||
import useCourseGradeFilterData from './hooks';
|
import useCourseGradeFilterData from './hooks';
|
||||||
@@ -42,18 +42,18 @@ describe('CourseFilter component', () => {
|
|||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
describe('with selected assignment', () => {
|
describe('with selected assignment', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
it('renders a PercentGroup for both Max and Min filters', () => {
|
it('renders a PercentGroup for both Max and Min filters', () => {
|
||||||
let { props } = el.instance.findByType(PercentGroup)[0];
|
let props = el.find(PercentGroup).at(0).props();
|
||||||
expect(props.value).toEqual(hookData.min.value);
|
expect(props.value).toEqual(hookData.min.value);
|
||||||
expect(props.onChange).toEqual(hookData.min.onChange);
|
expect(props.onChange).toEqual(hookData.min.onChange);
|
||||||
props = el.instance.findByType(PercentGroup)[1].props;
|
props = el.find(PercentGroup).at(1).props();
|
||||||
expect(props.value).toEqual(hookData.max.value);
|
expect(props.value).toEqual(hookData.max.value);
|
||||||
expect(props.onChange).toEqual(hookData.max.onChange);
|
expect(props.onChange).toEqual(hookData.max.onChange);
|
||||||
});
|
});
|
||||||
it('renders a submit button', () => {
|
it('renders a submit button', () => {
|
||||||
const { props } = el.instance.findByType(Button)[0];
|
const props = el.find(Button).props();
|
||||||
expect(props.disabled).toEqual(false);
|
expect(props.disabled).toEqual(false);
|
||||||
expect(props.onClick).toEqual(hookData.handleApplyClick);
|
expect(props.onClick).toEqual(hookData.handleApplyClick);
|
||||||
});
|
});
|
||||||
@@ -64,10 +64,10 @@ describe('CourseFilter component', () => {
|
|||||||
el = shallow(<CourseFilter updateQueryParams={updateQueryParams} />);
|
el = shallow(<CourseFilter updateQueryParams={updateQueryParams} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
it('disables submit', () => {
|
it('disables submit', () => {
|
||||||
const { props } = el.instance.findByType(Button)[0];
|
const props = el.find(Button).props();
|
||||||
expect(props.disabled).toEqual(true);
|
expect(props.disabled).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
const PercentGroup = ({
|
const PercentGroup = ({
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import PercentGroup from './PercentGroup';
|
import PercentGroup from './PercentGroup';
|
||||||
|
|
||||||
@@ -22,11 +22,11 @@ describe('PercentGroup', () => {
|
|||||||
describe('snapshots', () => {
|
describe('snapshots', () => {
|
||||||
test('basic snapshot', () => {
|
test('basic snapshot', () => {
|
||||||
const el = shallow(<PercentGroup {...props} />);
|
const el = shallow(<PercentGroup {...props} />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('disabled', () => {
|
test('disabled', () => {
|
||||||
const el = shallow(<PercentGroup {...props} disabled />);
|
const el = shallow(<PercentGroup {...props} disabled />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
const SelectGroup = ({
|
const SelectGroup = ({
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import SelectGroup from './SelectGroup';
|
import SelectGroup from './SelectGroup';
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ describe('SelectGroup', () => {
|
|||||||
describe('snapshots', () => {
|
describe('snapshots', () => {
|
||||||
test('basic snapshot', () => {
|
test('basic snapshot', () => {
|
||||||
const el = shallow(<SelectGroup {...props} />);
|
const el = shallow(<SelectGroup {...props} />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('disabled', () => {
|
test('disabled', () => {
|
||||||
const el = shallow(<SelectGroup {...props} disabled />);
|
const el = shallow(<SelectGroup {...props} disabled />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ exports[`StudentGroupsFilter component render snapshot 1`] = `
|
|||||||
label="Tracks"
|
label="Tracks"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
options={
|
options={
|
||||||
[
|
Array [
|
||||||
<option
|
<option
|
||||||
value="Track-All"
|
value="Track-All"
|
||||||
>
|
>
|
||||||
@@ -43,7 +43,7 @@ exports[`StudentGroupsFilter component render snapshot 1`] = `
|
|||||||
label="Cohorts"
|
label="Cohorts"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
options={
|
options={
|
||||||
[
|
Array [
|
||||||
<option
|
<option
|
||||||
value="Cohort-All"
|
value="Cohort-All"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import SelectGroup from '../SelectGroup';
|
import SelectGroup from '../SelectGroup';
|
||||||
@@ -48,14 +48,14 @@ describe('StudentGroupsFilter component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('track options', () => {
|
test('track options', () => {
|
||||||
const {
|
const {
|
||||||
options,
|
options,
|
||||||
onChange,
|
onChange,
|
||||||
value,
|
value,
|
||||||
} = el.instance.findByType(SelectGroup)[0].props;
|
} = el.find(SelectGroup).at(0).props();
|
||||||
expect(value).toEqual(props.tracks.value);
|
expect(value).toEqual(props.tracks.value);
|
||||||
expect(onChange).toEqual(props.tracks.handleChange);
|
expect(onChange).toEqual(props.tracks.handleChange);
|
||||||
expect(options.length).toEqual(5);
|
expect(options.length).toEqual(5);
|
||||||
@@ -70,7 +70,7 @@ describe('StudentGroupsFilter component', () => {
|
|||||||
onChange,
|
onChange,
|
||||||
disabled,
|
disabled,
|
||||||
value,
|
value,
|
||||||
} = el.instance.findByType(SelectGroup)[1].props;
|
} = el.find(SelectGroup).at(1).props();
|
||||||
expect(value).toEqual(props.cohorts.value);
|
expect(value).toEqual(props.cohorts.value);
|
||||||
expect(disabled).toEqual(false);
|
expect(disabled).toEqual(false);
|
||||||
expect(onChange).toEqual(props.cohorts.handleChange);
|
expect(onChange).toEqual(props.cohorts.handleChange);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Form,
|
Form,
|
||||||
} from '@openedx/paragon';
|
} from '@edx/paragon';
|
||||||
import { Close } from '@openedx/paragon/icons';
|
import { Close } from '@edx/paragon/icons';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Collapsible } from '@openedx/paragon';
|
import { Collapsible } from '@edx/paragon';
|
||||||
|
|
||||||
import { formatMessage } from 'testUtils';
|
import { formatMessage } from 'testUtils';
|
||||||
|
|
||||||
@@ -49,10 +49,10 @@ describe('GradebookFilters', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('Assignment filters', () => {
|
test('Assignment filters', () => {
|
||||||
expect(el.instance.findByType(Collapsible)[0].children[0]).toMatchObject(shallow(
|
expect(el.find(Collapsible).at(0).children()).toMatchObject(shallow(
|
||||||
<div>
|
<div>
|
||||||
<AssignmentTypeFilter updateQueryParams={updateQueryParams} />
|
<AssignmentTypeFilter updateQueryParams={updateQueryParams} />
|
||||||
<AssignmentFilter updateQueryParams={updateQueryParams} />
|
<AssignmentFilter updateQueryParams={updateQueryParams} />
|
||||||
@@ -61,22 +61,22 @@ describe('GradebookFilters', () => {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
test('CourseGrade filters', () => {
|
test('CourseGrade filters', () => {
|
||||||
expect(el.instance.findByType(Collapsible)[1].children[0]).toMatchObject(shallow(
|
expect(el.find(Collapsible).at(1).children()).toMatchObject(shallow(
|
||||||
<CourseGradeFilter updateQueryParams={updateQueryParams} />,
|
<CourseGradeFilter updateQueryParams={updateQueryParams} />,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
test('StudentGroups filters', () => {
|
test('StudentGroups filters', () => {
|
||||||
expect(el.instance.findByType(Collapsible)[2].children[0]).toMatchObject(shallow(
|
expect(el.find(Collapsible).at(2).children()).toMatchObject(shallow(
|
||||||
<StudentGroupsFilter updateQueryParams={updateQueryParams} />,
|
<StudentGroupsFilter updateQueryParams={updateQueryParams} />,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
test('includeCourseTeamMembers', () => {
|
test('includeCourseTeamMembers', () => {
|
||||||
const checkbox = el.instance.findByType(Collapsible)[3].children[0];
|
const checkbox = el.find(Collapsible).at(3).children();
|
||||||
expect(checkbox.props).toEqual({
|
expect(checkbox.props()).toEqual({
|
||||||
checked: true,
|
checked: true,
|
||||||
onChange: hookProps.includeCourseTeamMembers.handleChange,
|
onChange: hookProps.includeCourseTeamMembers.handleChange,
|
||||||
});
|
children: formatMessage(messages.includeCourseTeamMembers),
|
||||||
expect(checkbox.children[0].el).toEqual(formatMessage(messages.includeCourseTeamMembers));
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ exports[`GradebookHeader component render default view shapshot 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="subtitle-row d-flex justify-content-between align-items-center"
|
className="subtitle-row d-flex justify-content-between align-items-center"
|
||||||
>
|
>
|
||||||
<h2
|
<h2>
|
||||||
className="text-break"
|
|
||||||
>
|
|
||||||
test-course-id
|
test-course-id
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,9 +49,7 @@ exports[`GradebookHeader component render frozen grades snapshot: show frozen wa
|
|||||||
<div
|
<div
|
||||||
className="subtitle-row d-flex justify-content-between align-items-center"
|
className="subtitle-row d-flex justify-content-between align-items-center"
|
||||||
>
|
>
|
||||||
<h2
|
<h2>
|
||||||
className="text-break"
|
|
||||||
>
|
|
||||||
test-course-id
|
test-course-id
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,9 +83,7 @@ exports[`GradebookHeader component render show bulk management snapshot: show to
|
|||||||
<div
|
<div
|
||||||
className="subtitle-row d-flex justify-content-between align-items-center"
|
className="subtitle-row d-flex justify-content-between align-items-center"
|
||||||
>
|
>
|
||||||
<h2
|
<h2>
|
||||||
className="text-break"
|
|
||||||
>
|
|
||||||
test-course-id
|
test-course-id
|
||||||
</h2>
|
</h2>
|
||||||
<Button
|
<Button
|
||||||
@@ -123,9 +117,7 @@ exports[`GradebookHeader component render user cannot view gradebook snapshot: s
|
|||||||
<div
|
<div
|
||||||
className="subtitle-row d-flex justify-content-between align-items-center"
|
className="subtitle-row d-flex justify-content-between align-items-center"
|
||||||
>
|
>
|
||||||
<h2
|
<h2>
|
||||||
className="text-break"
|
|
||||||
>
|
|
||||||
test-course-id
|
test-course-id
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import { instructorDashboardUrl } from 'data/services/lms/urls';
|
import { instructorDashboardUrl } from 'data/services/lms/urls';
|
||||||
import useGradebookHeaderData from './hooks';
|
import useGradebookHeaderData from './hooks';
|
||||||
@@ -26,7 +26,7 @@ export const GradebookHeader = () => {
|
|||||||
</a>
|
</a>
|
||||||
<h1>{formatMessage(messages.gradebook)}</h1>
|
<h1>{formatMessage(messages.gradebook)}</h1>
|
||||||
<div className="subtitle-row d-flex justify-content-between align-items-center">
|
<div className="subtitle-row d-flex justify-content-between align-items-center">
|
||||||
<h2 className="text-break">{courseId}</h2>
|
<h2>{courseId}</h2>
|
||||||
{showBulkManagement && (
|
{showBulkManagement && (
|
||||||
<Button variant="tertiary" onClick={handleToggleViewClick}>
|
<Button variant="tertiary" onClick={handleToggleViewClick}>
|
||||||
{formatMessage(toggleViewMessage)}
|
{formatMessage(toggleViewMessage)}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import { formatMessage } from 'testUtils';
|
import { formatMessage } from 'testUtils';
|
||||||
import { instructorDashboardUrl } from 'data/services/lms/urls';
|
import { instructorDashboardUrl } from 'data/services/lms/urls';
|
||||||
@@ -40,7 +40,7 @@ describe('GradebookHeader component', () => {
|
|||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
describe('default view', () => {
|
describe('default view', () => {
|
||||||
test('shapshot', () => {
|
test('shapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('show bulk management', () => {
|
describe('show bulk management', () => {
|
||||||
@@ -49,10 +49,10 @@ describe('GradebookHeader component', () => {
|
|||||||
el = shallow(<GradebookHeader />);
|
el = shallow(<GradebookHeader />);
|
||||||
});
|
});
|
||||||
test('snapshot: show toggle view message button with handleToggleViewClick method', () => {
|
test('snapshot: show toggle view message button with handleToggleViewClick method', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
const { onClick } = el.instance.findByType(Button)[0].props;
|
const { onClick, children } = el.find(Button).props();
|
||||||
expect(onClick).toEqual(hookProps.handleToggleViewClick);
|
expect(onClick).toEqual(hookProps.handleToggleViewClick);
|
||||||
expect(el.instance.findByType(Button)[0].children[0].el).toEqual(formatMessage(hookProps.toggleViewMessage));
|
expect(children).toEqual(formatMessage(hookProps.toggleViewMessage));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('frozen grades', () => {
|
describe('frozen grades', () => {
|
||||||
@@ -61,7 +61,7 @@ describe('GradebookHeader component', () => {
|
|||||||
el = shallow(<GradebookHeader />);
|
el = shallow(<GradebookHeader />);
|
||||||
});
|
});
|
||||||
test('snapshot: show frozen warning', () => {
|
test('snapshot: show frozen warning', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('user cannot view gradebook', () => {
|
describe('user cannot view gradebook', () => {
|
||||||
@@ -70,7 +70,7 @@ describe('GradebookHeader component', () => {
|
|||||||
el = shallow(<GradebookHeader />);
|
el = shallow(<GradebookHeader />);
|
||||||
});
|
});
|
||||||
test('snapshot: show unauthorized warning', () => {
|
test('snapshot: show unauthorized warning', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ exports[`BulkManagementControls render snapshot - show - network and import butt
|
|||||||
>
|
>
|
||||||
<NetworkButton
|
<NetworkButton
|
||||||
label={
|
label={
|
||||||
{
|
Object {
|
||||||
"defaultMessage": "Download Grades",
|
"defaultMessage": "Download Grades",
|
||||||
"description": "A labeled button that allows an admin user to download course grades all at once (in bulk).",
|
"description": "A labeled button that allows an admin user to download course grades all at once (in bulk).",
|
||||||
"id": "gradebook.GradesView.BulkManagementControls.bulkManagementLabel",
|
"id": "gradebook.GradesView.BulkManagementControls.bulkManagementLabel",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import useBulkManagementControlsData from './hooks';
|
import useBulkManagementControlsData from './hooks';
|
||||||
import BulkManagementControls from '.';
|
import BulkManagementControls from '.';
|
||||||
@@ -22,7 +22,7 @@ describe('BulkManagementControls', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot - show - network and import buttons', () => {
|
test('snapshot - show - network and import buttons', () => {
|
||||||
expect(shallow(<BulkManagementControls />).snapshot).toMatchSnapshot();
|
expect(shallow(<BulkManagementControls />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('snapshot - empty if show is not truthy', () => {
|
test('snapshot - empty if show is not truthy', () => {
|
||||||
useBulkManagementControlsData.mockReturnValueOnce({ ...hookProps, show: false });
|
useBulkManagementControlsData.mockReturnValueOnce({ ...hookProps, show: false });
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import HistoryHeader from './HistoryHeader';
|
import HistoryHeader from './HistoryHeader';
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ describe('HistoryHeader', () => {
|
|||||||
};
|
};
|
||||||
describe('Component', () => {
|
describe('Component', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(shallow(<HistoryHeader {...props} />).snapshot).toMatchSnapshot();
|
expect(shallow(<HistoryHeader {...props} />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const HistoryKeys = StrictDict({
|
|||||||
*/
|
*/
|
||||||
export const ModalHeaders = () => {
|
export const ModalHeaders = () => {
|
||||||
const { assignmentName, updateUserName } = selectors.app.useModalData();
|
const { assignmentName, updateUserName } = selectors.app.useModalData();
|
||||||
const { gradeOverrideCurrentEarnedGradedOverride, gradeOriginalEarnedGraded } = selectors.grades.useGradeData();
|
const { currentGrade, originalGrade } = selectors.grades.useGradeData();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -39,12 +39,12 @@ export const ModalHeaders = () => {
|
|||||||
<HistoryHeader
|
<HistoryHeader
|
||||||
id={HistoryKeys.originalGrade}
|
id={HistoryKeys.originalGrade}
|
||||||
label={formatMessage(messages.originalGradeHeader)}
|
label={formatMessage(messages.originalGradeHeader)}
|
||||||
value={gradeOriginalEarnedGraded}
|
value={originalGrade}
|
||||||
/>
|
/>
|
||||||
<HistoryHeader
|
<HistoryHeader
|
||||||
id={HistoryKeys.currentGrade}
|
id={HistoryKeys.currentGrade}
|
||||||
label={formatMessage(messages.currentGradeHeader)}
|
label={formatMessage(messages.currentGradeHeader)}
|
||||||
value={gradeOverrideCurrentEarnedGradedOverride}
|
value={currentGrade}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { selectors } from 'data/redux/hooks';
|
import { selectors } from 'data/redux/hooks';
|
||||||
@@ -25,8 +25,8 @@ const modalData = {
|
|||||||
};
|
};
|
||||||
selectors.app.useModalData.mockReturnValue(modalData);
|
selectors.app.useModalData.mockReturnValue(modalData);
|
||||||
const gradeData = {
|
const gradeData = {
|
||||||
gradeOverrideCurrentEarnedGradedOverride: 'test-current-grade',
|
currentGrade: 'test-current-grade',
|
||||||
gradeOriginalEarnedGraded: 'test-original-grade',
|
originalGrade: 'test-original-grade',
|
||||||
};
|
};
|
||||||
selectors.grades.useGradeData.mockReturnValue(gradeData);
|
selectors.grades.useGradeData.mockReturnValue(gradeData);
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ describe('ModalHeaders', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('assignment header', () => {
|
test('assignment header', () => {
|
||||||
const headerProps = el.instance.findByType(HistoryHeader)[0].props;
|
const headerProps = el.find(HistoryHeader).at(0).props();
|
||||||
expect(headerProps).toMatchObject({
|
expect(headerProps).toMatchObject({
|
||||||
id: HistoryKeys.assignment,
|
id: HistoryKeys.assignment,
|
||||||
label: formatMessage(messages.assignmentHeader),
|
label: formatMessage(messages.assignmentHeader),
|
||||||
@@ -58,7 +58,7 @@ describe('ModalHeaders', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('student header', () => {
|
test('student header', () => {
|
||||||
const headerProps = el.instance.findByType(HistoryHeader)[1].props;
|
const headerProps = el.find(HistoryHeader).at(1).props();
|
||||||
expect(headerProps).toMatchObject({
|
expect(headerProps).toMatchObject({
|
||||||
id: HistoryKeys.student,
|
id: HistoryKeys.student,
|
||||||
label: formatMessage(messages.studentHeader),
|
label: formatMessage(messages.studentHeader),
|
||||||
@@ -66,19 +66,19 @@ describe('ModalHeaders', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('originalGrade header', () => {
|
test('originalGrade header', () => {
|
||||||
const headerProps = el.instance.findByType(HistoryHeader)[2].props;
|
const headerProps = el.find(HistoryHeader).at(2).props();
|
||||||
expect(headerProps).toMatchObject({
|
expect(headerProps).toMatchObject({
|
||||||
id: HistoryKeys.originalGrade,
|
id: HistoryKeys.originalGrade,
|
||||||
label: formatMessage(messages.originalGradeHeader),
|
label: formatMessage(messages.originalGradeHeader),
|
||||||
value: gradeData.gradeOriginalEarnedGraded,
|
value: gradeData.originalGrade,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('currentGrade header', () => {
|
test('currentGrade header', () => {
|
||||||
const headerProps = el.instance.findByType(HistoryHeader)[3].props;
|
const headerProps = el.find(HistoryHeader).at(3).props();
|
||||||
expect(headerProps).toMatchObject({
|
expect(headerProps).toMatchObject({
|
||||||
id: HistoryKeys.currentGrade,
|
id: HistoryKeys.currentGrade,
|
||||||
label: formatMessage(messages.currentGradeHeader),
|
label: formatMessage(messages.currentGradeHeader),
|
||||||
value: gradeData.gradeOverrideCurrentEarnedGradedOverride,
|
value: gradeData.currentGrade,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import useAdjustedGradeInputData from './hooks';
|
import useAdjustedGradeInputData from './hooks';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import useAdjustedGradeInputData from './hooks';
|
import useAdjustedGradeInputData from './hooks';
|
||||||
import AdjustedGradeInput from '.';
|
import AdjustedGradeInput from '.';
|
||||||
@@ -28,11 +28,11 @@ describe('AdjustedGradeInput component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
const control = el.instance.findByType(Form.Control)[0];
|
const control = el.find(Form.Control);
|
||||||
expect(control.props.value).toEqual(hookProps.value);
|
expect(control.props().value).toEqual(hookProps.value);
|
||||||
expect(control.props.onChange).toEqual(hookProps.onChange);
|
expect(control.props().onChange).toEqual(hookProps.onChange);
|
||||||
expect(el.instance.children[1].el).toContain(hookProps.hintText);
|
expect(el.contains(hookProps.hintText)).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import useReasonInputData from './hooks';
|
import useReasonInputData from './hooks';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import useReasonInputData from './hooks';
|
import useReasonInputData from './hooks';
|
||||||
import ReasonInput from '.';
|
import ReasonInput from '.';
|
||||||
@@ -28,10 +28,10 @@ describe('ReasonInput component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
const control = el.instance.findByType(Form.Control)[0];
|
const control = el.find(Form.Control);
|
||||||
expect(control.props.value).toEqual(hookProps.value);
|
expect(control.props().value).toEqual(hookProps.value);
|
||||||
expect(control.props.onChange).toEqual(hookProps.onChange);
|
expect(control.props().onChange).toEqual(hookProps.onChange);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import useReasonInputData from './hooks';
|
|||||||
import ReasonInput, { controlTestId } from '.';
|
import ReasonInput, { controlTestId } from '.';
|
||||||
|
|
||||||
jest.unmock('react');
|
jest.unmock('react');
|
||||||
jest.unmock('@openedx/paragon');
|
jest.unmock('@edx/paragon');
|
||||||
jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() }));
|
jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() }));
|
||||||
|
|
||||||
const focus = jest.fn();
|
const focus = jest.fn();
|
||||||
|
|||||||
@@ -4,22 +4,22 @@ exports[`OverrideTable component render snapshot 1`] = `
|
|||||||
<DataTable
|
<DataTable
|
||||||
columns="test-columns"
|
columns="test-columns"
|
||||||
data={
|
data={
|
||||||
[
|
Array [
|
||||||
{
|
Object {
|
||||||
"test": "data",
|
"test": "data",
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"andOther": "test-data",
|
"andOther": "test-data",
|
||||||
},
|
},
|
||||||
{
|
Object {
|
||||||
"adjustedGrade": <AdjustedGradeInput />,
|
"adjustedGrade": <AdjustedGradeInput />,
|
||||||
"date": {
|
"date": Object {
|
||||||
"formatted": 2000-01-01T00:00:00.000Z,
|
"formatted": 2000-01-01T00:00:00.000Z,
|
||||||
},
|
},
|
||||||
"reason": <ReasonInput />,
|
"reason": <ReasonInput />,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
itemCount={3}
|
itemCount={2}
|
||||||
/>
|
/>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const useOverrideTableData = () => {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const hide = selectors.grades.useHasOverrideErrors();
|
const hide = selectors.grades.useHasOverrideErrors();
|
||||||
const gradeOverrides = selectors.grades.useGradeData().gradeOverrideHistoryResults || [];
|
const gradeOverrides = selectors.grades.useGradeData().gradeOverrideHistoryResults;
|
||||||
const tableProps = {};
|
const tableProps = {};
|
||||||
if (!hide) {
|
if (!hide) {
|
||||||
tableProps.columns = [
|
tableProps.columns = [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable react/sort-comp, react/button-has-type, import/no-named-as-default */
|
/* eslint-disable react/sort-comp, react/button-has-type, import/no-named-as-default */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import { formatDateForDisplay } from 'utils';
|
import { formatDateForDisplay } from 'utils';
|
||||||
|
|
||||||
@@ -20,20 +20,18 @@ export const OverrideTable = () => {
|
|||||||
|
|
||||||
if (hide) { return null; }
|
if (hide) { return null; }
|
||||||
|
|
||||||
const tableData = [
|
return (
|
||||||
|
<DataTable
|
||||||
|
columns={columns}
|
||||||
|
data={[
|
||||||
...data,
|
...data,
|
||||||
{
|
{
|
||||||
adjustedGrade: <AdjustedGradeInput />,
|
adjustedGrade: <AdjustedGradeInput />,
|
||||||
date: formatDateForDisplay(new Date()),
|
date: formatDateForDisplay(new Date()),
|
||||||
reason: <ReasonInput />,
|
reason: <ReasonInput />,
|
||||||
},
|
},
|
||||||
];
|
]}
|
||||||
|
itemCount={data.length}
|
||||||
return (
|
|
||||||
<DataTable
|
|
||||||
columns={columns}
|
|
||||||
data={tableData}
|
|
||||||
itemCount={tableData.length}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import { formatDateForDisplay } from 'utils';
|
import { formatDateForDisplay } from 'utils';
|
||||||
|
|
||||||
@@ -48,10 +48,10 @@ describe('OverrideTable component', () => {
|
|||||||
expect(el.isEmptyRender()).toEqual(true);
|
expect(el.isEmptyRender()).toEqual(true);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
const table = el.instance.findByType(DataTable)[0];
|
const table = el.find(DataTable);
|
||||||
expect(table.props.columns).toEqual(hookProps.columns);
|
expect(table.props().columns).toEqual(hookProps.columns);
|
||||||
const data = [...table.props.data];
|
const data = [...table.props().data];
|
||||||
const inputRow = data.pop();
|
const inputRow = data.pop();
|
||||||
const formattedDate = formatDateForDisplay(new Date());
|
const formattedDate = formatDateForDisplay(new Date());
|
||||||
expect(data).toEqual(hookProps.data);
|
expect(data).toEqual(hookProps.data);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
Alert,
|
Alert,
|
||||||
ModalDialog,
|
ModalDialog,
|
||||||
ActionRow,
|
ActionRow,
|
||||||
} from '@openedx/paragon';
|
} from '@edx/paragon';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import OverrideTable from './OverrideTable';
|
import OverrideTable from './OverrideTable';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionRow,
|
ActionRow,
|
||||||
ModalDialog,
|
ModalDialog,
|
||||||
} from '@openedx/paragon';
|
} from '@edx/paragon';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { formatMessage } from 'testUtils';
|
import { formatMessage } from 'testUtils';
|
||||||
@@ -43,56 +43,60 @@ describe('EditModal component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('modal props', () => {
|
test('modal props', () => {
|
||||||
const modalProps = el.instance.findByType(ModalDialog)[0].props;
|
const modalProps = el.find(ModalDialog).props();
|
||||||
expect(modalProps.title).toEqual(formatMessage(messages.title));
|
expect(modalProps.title).toEqual(formatMessage(messages.title));
|
||||||
expect(modalProps.isOpen).toEqual(hookProps.isOpen);
|
expect(modalProps.isOpen).toEqual(hookProps.isOpen);
|
||||||
expect(modalProps.onClose).toEqual(hookProps.onClose);
|
expect(modalProps.onClose).toEqual(hookProps.onClose);
|
||||||
});
|
});
|
||||||
const loadBody = () => {
|
const loadBody = () => {
|
||||||
const body = el.instance.findByType(ModalDialog)[0].children[0];
|
const body = el.find(ModalDialog).children().at(0);
|
||||||
const { children } = body.children[0];
|
const children = body.find('div').children();
|
||||||
return { body, children };
|
return { body, children };
|
||||||
};
|
};
|
||||||
const testBody = () => {
|
const testBody = () => {
|
||||||
test('type', () => {
|
test('type', () => {
|
||||||
const { body } = loadBody();
|
const { body } = loadBody();
|
||||||
expect(body.type).toEqual('ModalDialog.Body');
|
expect(body.type()).toEqual('ModalDialog.Body');
|
||||||
});
|
});
|
||||||
test('headers row', () => {
|
test('headers row', () => {
|
||||||
const { children } = loadBody();
|
const { children } = loadBody();
|
||||||
expect(children[0]).toMatchObject(shallow(<ModalHeaders />));
|
expect(children.at(0)).toMatchObject(shallow(<ModalHeaders />));
|
||||||
});
|
});
|
||||||
test('table row', () => {
|
test('table row', () => {
|
||||||
const { children } = loadBody();
|
const { children } = loadBody();
|
||||||
expect(children[2]).toMatchObject(shallow(<OverrideTable />));
|
expect(children.at(2)).toMatchObject(shallow(<OverrideTable />));
|
||||||
});
|
});
|
||||||
test('messages', () => {
|
test('messages', () => {
|
||||||
const { children } = loadBody();
|
const { children } = loadBody();
|
||||||
expect(children[3].children[0].el).toEqual(formatMessage(messages.visibility));
|
expect(
|
||||||
expect(children[4].children[0].el).toEqual(formatMessage(messages.saveVisibility));
|
children.at(3).contains(formatMessage(messages.visibility)),
|
||||||
|
).toEqual(true);
|
||||||
|
expect(
|
||||||
|
children.at(4).contains(formatMessage(messages.saveVisibility)),
|
||||||
|
).toEqual(true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const testFooter = () => {
|
const testFooter = () => {
|
||||||
let footer;
|
let footer;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
footer = el.instance.findByType(ModalDialog)[0].children;
|
footer = el.find(ModalDialog).children().at(1);
|
||||||
});
|
});
|
||||||
test('type', () => {
|
test('type', () => {
|
||||||
expect(footer[1].type).toEqual('ModalDialog.Footer');
|
expect(footer.type()).toEqual('ModalDialog.Footer');
|
||||||
});
|
});
|
||||||
test('contains action row', () => {
|
test('contains action row', () => {
|
||||||
expect(footer[1].children[0].type).toEqual('ActionRow');
|
expect(footer.children().at(0).type()).toEqual('ActionRow');
|
||||||
});
|
});
|
||||||
test('close button', () => {
|
test('close button', () => {
|
||||||
const button = footer[1].findByType(ActionRow)[0].children[0];
|
const button = footer.find(ActionRow).children().at(0);
|
||||||
expect(button.children[0].el).toEqual(formatMessage(messages.closeText));
|
expect(button.contains(formatMessage(messages.closeText))).toEqual(true);
|
||||||
expect(button.type).toEqual('ModalDialog.CloseButton');
|
expect(button.type()).toEqual('ModalDialog.CloseButton');
|
||||||
});
|
});
|
||||||
test('adjusted grade button', () => {
|
test('adjusted grade button', () => {
|
||||||
const button = footer[1].findByType(ActionRow)[0].children[1];
|
const button = footer.find(ActionRow).children().at(1);
|
||||||
expect(button.children[0].el).toEqual(formatMessage(messages.saveGrade));
|
expect(button.contains(formatMessage(messages.saveGrade))).toEqual(true);
|
||||||
expect(button.type).toEqual('Button');
|
expect(button.type()).toEqual('Button');
|
||||||
expect(button.props.onClick).toEqual(hookProps.handleAdjustedGradeClick);
|
expect(button.props().onClick).toEqual(hookProps.handleAdjustedGradeClick);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
describe('without error', () => {
|
describe('without error', () => {
|
||||||
@@ -101,26 +105,26 @@ describe('EditModal component', () => {
|
|||||||
el = shallow(<EditModal />);
|
el = shallow(<EditModal />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
testBody();
|
testBody();
|
||||||
testFooter();
|
testFooter();
|
||||||
test('alert row', () => {
|
test('alert row', () => {
|
||||||
const alert = loadBody().children[1];
|
const alert = loadBody().children.at(1);
|
||||||
expect(alert.type).toEqual('Alert');
|
expect(alert.type()).toEqual('Alert');
|
||||||
expect(alert.props.show).toEqual(false);
|
expect(alert.props().show).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('with error', () => {
|
describe('with error', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
testBody();
|
testBody();
|
||||||
test('alert row', () => {
|
test('alert row', () => {
|
||||||
const alert = loadBody().children[1];
|
const alert = loadBody().children.at(1);
|
||||||
expect(alert.type).toEqual('Alert');
|
expect(alert.type()).toEqual('Alert');
|
||||||
expect(alert.props.show).toEqual(true);
|
expect(alert.props().show).toEqual(true);
|
||||||
expect(alert.children[0].el).toEqual(hookProps.error);
|
expect(alert.contains(hookProps.error)).toEqual(true);
|
||||||
});
|
});
|
||||||
testFooter();
|
testFooter();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { selectors } from 'data/redux/hooks';
|
import { selectors } from 'data/redux/hooks';
|
||||||
@@ -32,8 +32,8 @@ export const FilterBadge = ({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span className="badge badge-info">
|
<span className="badge badge-info">
|
||||||
<span data-testid="display-name">{formatMessage(displayName)}</span>
|
<span>{formatMessage(displayName)}</span>
|
||||||
<span data-testid="filter-value">
|
<span>
|
||||||
{!hideValue ? `: ${value}` : ''}
|
{!hideValue ? `: ${value}` : ''}
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { formatMessage } from 'testUtils';
|
import { formatMessage } from 'testUtils';
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
import { selectors } from 'data/redux/hooks';
|
import { selectors } from 'data/redux/hooks';
|
||||||
import FilterBadge from './FilterBadge';
|
import FilterBadge from './FilterBadge';
|
||||||
|
|
||||||
jest.mock('@openedx/paragon', () => ({
|
jest.mock('@edx/paragon', () => ({
|
||||||
Button: () => 'Button',
|
Button: () => 'Button',
|
||||||
}));
|
}));
|
||||||
jest.mock('data/redux/hooks', () => ({
|
jest.mock('data/redux/hooks', () => ({
|
||||||
@@ -48,12 +48,12 @@ describe('FilterBadge', () => {
|
|||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
const testDisplayName = () => {
|
const testDisplayName = () => {
|
||||||
test('formatted display name appears on badge', () => {
|
test('formatted display name appears on badge', () => {
|
||||||
expect(el.instance.findByTestId('display-name')[0].children[0].el).toEqual(formatMessage(hookProps.displayName));
|
expect(el.contains(formatMessage(hookProps.displayName))).toEqual(true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const testCloseButton = () => {
|
const testCloseButton = () => {
|
||||||
test('close button forwards close method', () => {
|
test('close button forwards close method', () => {
|
||||||
expect(el.instance.findByType(Button)[0].props.onClick).toEqual(handleClose(hookProps.connectedFilters));
|
expect(el.find(Button).props().onClick).toEqual(handleClose(hookProps.connectedFilters));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
test('empty render if isDefault', () => {
|
test('empty render if isDefault', () => {
|
||||||
@@ -75,20 +75,20 @@ describe('FilterBadge', () => {
|
|||||||
testDisplayName();
|
testDisplayName();
|
||||||
testCloseButton();
|
testCloseButton();
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('value is note present in the badge', () => {
|
test('value is note present in the badge', () => {
|
||||||
expect(el.instance.findByTestId('filter-value')[0].children).toHaveLength(0);
|
expect(el.contains(hookProps.value)).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('do not hide value', () => {
|
describe('do not hide value', () => {
|
||||||
testDisplayName();
|
testDisplayName();
|
||||||
testCloseButton();
|
testCloseButton();
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('value is present in the badge', () => {
|
test('value is note present in the badge', () => {
|
||||||
expect(el.instance.findByTestId('filter-value')[0].children[0].el).toBe(`: ${hookProps.value}`);
|
expect(el.text().includes(hookProps.value)).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,22 +5,18 @@ exports[`FilterBadge render do not hide value snapshot 1`] = `
|
|||||||
<span
|
<span
|
||||||
className="badge badge-info"
|
className="badge badge-info"
|
||||||
>
|
>
|
||||||
<span
|
<span>
|
||||||
data-testid="display-name"
|
|
||||||
>
|
|
||||||
a common name
|
a common name
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span>
|
||||||
data-testid="filter-value"
|
|
||||||
>
|
|
||||||
: a common value
|
: a common value
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
className="btn-info"
|
className="btn-info"
|
||||||
onClick={
|
onClick={
|
||||||
{
|
Object {
|
||||||
"handleClose": [
|
"handleClose": Array [
|
||||||
"some",
|
"some",
|
||||||
"filters",
|
"filters",
|
||||||
],
|
],
|
||||||
@@ -43,20 +39,16 @@ exports[`FilterBadge render hide Value snapshot 1`] = `
|
|||||||
<span
|
<span
|
||||||
className="badge badge-info"
|
className="badge badge-info"
|
||||||
>
|
>
|
||||||
<span
|
<span>
|
||||||
data-testid="display-name"
|
|
||||||
>
|
|
||||||
a common name
|
a common name
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span />
|
||||||
data-testid="filter-value"
|
|
||||||
/>
|
|
||||||
<Button
|
<Button
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
className="btn-info"
|
className="btn-info"
|
||||||
onClick={
|
onClick={
|
||||||
{
|
Object {
|
||||||
"handleClose": [
|
"handleClose": Array [
|
||||||
"some",
|
"some",
|
||||||
"filters",
|
"filters",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable import/no-named-as-default */
|
/* eslint-disable import/no-named-as-default */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import FilterBadges from '.';
|
import FilterBadges from '.';
|
||||||
import FilterBadge from './FilterBadge';
|
import FilterBadge from './FilterBadge';
|
||||||
@@ -22,14 +22,14 @@ describe('FilterBadges', () => {
|
|||||||
el = shallow(<FilterBadges handleClose={handleClose} />);
|
el = shallow(<FilterBadges handleClose={handleClose} />);
|
||||||
});
|
});
|
||||||
test('snapshot - has a filterbadge with handleClose for each filter in badgeOrder', () => {
|
test('snapshot - has a filterbadge with handleClose for each filter in badgeOrder', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('has a filterbadge with handleClose for each filter in badgeOrder', () => {
|
test('has a filterbadge with handleClose for each filter in badgeOrder', () => {
|
||||||
const badgeProps = el.instance.findByType(FilterBadge).map(badgeEl => badgeEl.props);
|
const badgeProps = el.find(FilterBadge).map(badgeEl => badgeEl.props());
|
||||||
// key prop is not rendered by react
|
// key prop is not rendered by react
|
||||||
expect(badgeProps[0]).toMatchObject({ filterName: order[0], handleClose });
|
expect(badgeProps[0]).toEqual({ filterName: order[0], handleClose });
|
||||||
expect(badgeProps[1]).toMatchObject({ filterName: order[1], handleClose });
|
expect(badgeProps[1]).toEqual({ filterName: order[1], handleClose });
|
||||||
expect(badgeProps[2]).toMatchObject({ filterName: order[2], handleClose });
|
expect(badgeProps[2]).toEqual({ filterName: order[2], handleClose });
|
||||||
expect(badgeProps.length).toEqual(3);
|
expect(badgeProps.length).toEqual(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ exports[`FilterMenuToggle component render snapshot 1`] = `
|
|||||||
onClick={[MockFunction hooks.toggleFilterMenu]}
|
onClick={[MockFunction hooks.toggleFilterMenu]}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
className="mr-1"
|
|
||||||
src="FilterAlt"
|
src="FilterAlt"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Button, Icon } from '@openedx/paragon';
|
import { Button, Icon } from '@edx/paragon';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { FilterAlt } from '@openedx/paragon/icons';
|
import { FilterAlt } from '@edx/paragon/icons';
|
||||||
|
|
||||||
import { thunkActions } from 'data/redux/hooks';
|
import { thunkActions } from 'data/redux/hooks';
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ export const FilterMenuToggle = () => {
|
|||||||
className="btn-primary align-self-start"
|
className="btn-primary align-self-start"
|
||||||
onClick={toggleFilterMenu}
|
onClick={toggleFilterMenu}
|
||||||
>
|
>
|
||||||
<Icon src={FilterAlt} className="mr-1" /> {formatMessage(messages.editFilters)}
|
<Icon src={FilterAlt} /> {formatMessage(messages.editFilters)}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@ describe('FilterMenuToggle component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
expect(el.instance.type).toEqual('Button');
|
expect(el.type()).toEqual('Button');
|
||||||
expect(el.instance.props.onClick).toEqual(toggleFilterMenu);
|
expect(el.props().onClick).toEqual(toggleFilterMenu);
|
||||||
expect(el.instance.children[2].el).toContain(formatMessage(messages.editFilters));
|
expect(el.text().includes(formatMessage(messages.editFilters)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
exports[`FilteredUsersLabel component render snapshot 1`] = `
|
exports[`FilteredUsersLabel component render snapshot 1`] = `
|
||||||
<format-message-function
|
<format-message-function
|
||||||
message={
|
message={
|
||||||
{
|
Object {
|
||||||
"defaultMessage": "Showing {filteredUsers} of {totalUsers} total learners",
|
"defaultMessage": "Showing {filteredUsers} of {totalUsers} total learners",
|
||||||
"description": "Users visibility label",
|
"description": "Users visibility label",
|
||||||
"id": "gradebook.GradesTab.usersVisibilityLabel",
|
"id": "gradebook.GradesTab.usersVisibilityLabel",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
values={
|
values={
|
||||||
{
|
Object {
|
||||||
"filteredUsers": <BoldText
|
"filteredUsers": <BoldText
|
||||||
text={100}
|
text={100}
|
||||||
/>,
|
/>,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ describe('FilteredUsersLabel component', () => {
|
|||||||
expect(shallow(<FilteredUsersLabel />).isEmptyRender()).toEqual(true);
|
expect(shallow(<FilteredUsersLabel />).isEmptyRender()).toEqual(true);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
expect(el.instance).toMatchObject(shallow(formatMessage(messages.visibilityLabel, {
|
expect(el).toMatchObject(shallow(formatMessage(messages.visibilityLabel, {
|
||||||
filteredUsers: <BoldText text={userCounts.filteredUsersCount} />,
|
filteredUsers: <BoldText text={userCounts.filteredUsersCount} />,
|
||||||
totalUsers: <BoldText text={userCounts.totalUsersCount} />,
|
totalUsers: <BoldText text={userCounts.totalUsersCount} />,
|
||||||
})));
|
})));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import Fields from './Fields';
|
import Fields from './Fields';
|
||||||
|
|
||||||
@@ -16,13 +16,14 @@ describe('Gradebook Table Fields', () => {
|
|||||||
el = shallow(<Fields.Username {...props} />);
|
el = shallow(<Fields.Username {...props} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('wraps external user key and username', () => {
|
test('wraps external user key and username', () => {
|
||||||
expect(el.instance.findByType('span')[0].el).toMatchSnapshot();
|
expect(el.find('span').childAt(0)).toMatchSnapshot();
|
||||||
const content = el.instance.findByType('span')[0].children[0];
|
expect(el.find('span').childAt(0)).toMatchSnapshot();
|
||||||
expect(content.children[0].children[0].el).toEqual(username);
|
const content = el.find('span').childAt(0);
|
||||||
expect(content.children[1].children[0].el).toEqual(props.userKey);
|
expect(content.childAt(0).text()).toEqual(username);
|
||||||
|
expect(content.childAt(1).text()).toEqual(props.userKey);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('without external_user_key', () => {
|
describe('without external_user_key', () => {
|
||||||
@@ -30,12 +31,12 @@ describe('Gradebook Table Fields', () => {
|
|||||||
el = shallow(<Fields.Username username={username} />);
|
el = shallow(<Fields.Username username={username} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('wraps username only', () => {
|
test('wraps username only', () => {
|
||||||
const content = el.instance.findByType('span')[0].children[0];
|
const content = el.find('span').childAt(0);
|
||||||
expect(content.children[0].children[0].el).toEqual(username);
|
expect(content.childAt(0).text()).toEqual(username);
|
||||||
expect(content.children).toHaveLength(1);
|
expect(content.children()).toHaveLength(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -43,10 +44,10 @@ describe('Gradebook Table Fields', () => {
|
|||||||
describe('Text', () => {
|
describe('Text', () => {
|
||||||
const value = 'myTag@place.com';
|
const value = 'myTag@place.com';
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(shallow(<Fields.Text value={value} />).snapshot).toMatchSnapshot();
|
expect(shallow(<Fields.Text value={value} />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('wraps entry value', () => {
|
test('wraps entry value', () => {
|
||||||
expect(shallow(<Fields.Text value={value} />).instance.children[0].el).toEqual(value);
|
expect(shallow(<Fields.Text value={value} />).text()).toEqual(value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Button } from '@openedx/paragon';
|
import { Button } from '@edx/paragon';
|
||||||
|
|
||||||
import { selectors, thunkActions } from 'data/redux/hooks';
|
import { selectors, thunkActions } from 'data/redux/hooks';
|
||||||
import transforms from 'data/redux/transforms';
|
import transforms from 'data/redux/transforms';
|
||||||
@@ -11,7 +11,7 @@ export const useGradeButtonData = ({ entry, subsection }) => {
|
|||||||
const areGradesFrozen = selectors.assignmentTypes.useAreGradesFrozen();
|
const areGradesFrozen = selectors.assignmentTypes.useAreGradesFrozen();
|
||||||
const { gradeFormat } = selectors.grades.useGradeData();
|
const { gradeFormat } = selectors.grades.useGradeData();
|
||||||
const setModalState = thunkActions.app.useSetModalStateFromTable();
|
const setModalState = thunkActions.app.useSetModalStateFromTable();
|
||||||
const label = transforms.grades.subsectionGrade({ gradeFormat, subsection })();
|
const label = transforms.grades.subsectionGrade({ gradeFormat, subsection });
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
setModalState({
|
setModalState({
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { selectors, thunkActions } from 'data/redux/hooks';
|
import { selectors, thunkActions } from 'data/redux/hooks';
|
||||||
import transforms from 'data/redux/transforms';
|
import transforms from 'data/redux/transforms';
|
||||||
@@ -41,7 +41,7 @@ const props = {
|
|||||||
};
|
};
|
||||||
const gradeFormat = 'percent';
|
const gradeFormat = 'percent';
|
||||||
const setModalState = jest.fn();
|
const setModalState = jest.fn();
|
||||||
const subsectionGrade = () => 'test-subsection-grade';
|
const subsectionGrade = 'test-subsection-grade';
|
||||||
selectors.assignmentTypes.useAreGradesFrozen.mockReturnValue(false);
|
selectors.assignmentTypes.useAreGradesFrozen.mockReturnValue(false);
|
||||||
selectors.grades.useGradeData.mockReturnValue({ gradeFormat });
|
selectors.grades.useGradeData.mockReturnValue({ gradeFormat });
|
||||||
thunkActions.app.useSetModalStateFromTable.mockReturnValue(setModalState);
|
thunkActions.app.useSetModalStateFromTable.mockReturnValue(setModalState);
|
||||||
@@ -73,7 +73,7 @@ describe('GradeButton', () => {
|
|||||||
expect(out.areGradesFrozen).toEqual(false);
|
expect(out.areGradesFrozen).toEqual(false);
|
||||||
});
|
});
|
||||||
test('label passed from subsection grade redux hook', () => {
|
test('label passed from subsection grade redux hook', () => {
|
||||||
expect(out.label).toEqual(subsectionGrade());
|
expect(out.label).toEqual(subsectionGrade);
|
||||||
});
|
});
|
||||||
test('onClick sets modal state with user entry and subsection', () => {
|
test('onClick sets modal state with user entry and subsection', () => {
|
||||||
out.onClick();
|
out.onClick();
|
||||||
@@ -101,8 +101,8 @@ describe('GradeButton', () => {
|
|||||||
el = shallow(<GradeButton {...props} />);
|
el = shallow(<GradeButton {...props} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
expect(el.instance.el).toEqual(hookProps.label);
|
expect(el.text()).toEqual(hookProps.label);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('not frozen grades', () => {
|
describe('not frozen grades', () => {
|
||||||
@@ -111,10 +111,10 @@ describe('GradeButton', () => {
|
|||||||
el = shallow(<GradeButton {...props} />);
|
el = shallow(<GradeButton {...props} />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
expect(el.instance.type).toEqual('Button');
|
expect(el.type()).toEqual('Button');
|
||||||
expect(el.instance.props.onClick).toEqual(hookProps.onClick);
|
expect(el.props().onClick).toEqual(hookProps.onClick);
|
||||||
expect(el.instance.children[0].el).toEqual(hookProps.label);
|
expect(el.contains(hookProps.label)).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
OverlayTrigger,
|
OverlayTrigger,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@openedx/paragon';
|
} from '@edx/paragon';
|
||||||
|
|
||||||
import { StrictDict } from 'utils';
|
import { StrictDict } from 'utils';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
import { getLocale } from '@edx/frontend-platform/i18n';
|
import { getLocale } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { OverlayTrigger } from '@openedx/paragon';
|
import { OverlayTrigger } from '@edx/paragon';
|
||||||
|
|
||||||
import LabelReplacements from './LabelReplacements';
|
import LabelReplacements from './LabelReplacements';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ const {
|
|||||||
MastersOnlyLabelReplacement,
|
MastersOnlyLabelReplacement,
|
||||||
} = LabelReplacements;
|
} = LabelReplacements;
|
||||||
|
|
||||||
jest.mock('@openedx/paragon', () => ({
|
jest.mock('@edx/paragon', () => ({
|
||||||
Icon: () => 'Icon',
|
Icon: () => 'Icon',
|
||||||
OverlayTrigger: () => 'OverlayTrigger',
|
OverlayTrigger: () => 'OverlayTrigger',
|
||||||
Tooltip: () => 'Tooltip',
|
Tooltip: () => 'Tooltip',
|
||||||
@@ -25,15 +25,15 @@ describe('LabelReplacements', () => {
|
|||||||
el = shallow(<TotalGradeLabelReplacement />);
|
el = shallow(<TotalGradeLabelReplacement />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('displays overlay tooltip', () => {
|
test('displays overlay tooltip', () => {
|
||||||
expect(el.instance.findByType(OverlayTrigger)[0].props.overlay).toMatchSnapshot();
|
expect(el.find(OverlayTrigger).props().overlay).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('UsernameLabelReplacement', () => {
|
describe('UsernameLabelReplacement', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(shallow(<UsernameLabelReplacement />).snapshot).toMatchSnapshot();
|
expect(shallow(<UsernameLabelReplacement />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('MastersOnlyLabelReplacement', () => {
|
describe('MastersOnlyLabelReplacement', () => {
|
||||||
@@ -43,7 +43,7 @@ describe('LabelReplacements', () => {
|
|||||||
defaultMessage: 'defaultMessAge',
|
defaultMessage: 'defaultMessAge',
|
||||||
description: 'desCripTion',
|
description: 'desCripTion',
|
||||||
};
|
};
|
||||||
expect(shallow(<MastersOnlyLabelReplacement {...message} />).snapshot).toMatchSnapshot();
|
expect(shallow(<MastersOnlyLabelReplacement {...message} />)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -53,11 +53,11 @@ describe('snapshot', () => {
|
|||||||
test('right to left overlay placement', () => {
|
test('right to left overlay placement', () => {
|
||||||
getLocale.mockImplementation(() => 'en');
|
getLocale.mockImplementation(() => 'en');
|
||||||
el = shallow(<TotalGradeLabelReplacement />);
|
el = shallow(<TotalGradeLabelReplacement />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('left to right overlay placement', () => {
|
test('left to right overlay placement', () => {
|
||||||
getLocale.mockImplementation(() => 'ar');
|
getLocale.mockImplementation(() => 'ar');
|
||||||
el = shallow(<TotalGradeLabelReplacement />);
|
el = shallow(<TotalGradeLabelReplacement />);
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,36 +28,29 @@ exports[`Gradebook Table Fields Username with external_user_key snapshot 1`] = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Gradebook Table Fields Username with external_user_key wraps external user key and username 1`] = `
|
exports[`Gradebook Table Fields Username with external_user_key wraps external user key and username 1`] = `
|
||||||
{
|
<div>
|
||||||
"children": [
|
<div>
|
||||||
{
|
MyNameFromHere
|
||||||
"children": [
|
</div>
|
||||||
{
|
<div
|
||||||
"children": [
|
className="student-key"
|
||||||
"MyNameFromHere",
|
>
|
||||||
],
|
My name from another land
|
||||||
"props": {},
|
</div>
|
||||||
"type": "div",
|
</div>
|
||||||
},
|
`;
|
||||||
{
|
|
||||||
"children": [
|
exports[`Gradebook Table Fields Username with external_user_key wraps external user key and username 2`] = `
|
||||||
"My name from another land",
|
<div>
|
||||||
],
|
<div>
|
||||||
"props": {
|
MyNameFromHere
|
||||||
"className": "student-key",
|
</div>
|
||||||
},
|
<div
|
||||||
"type": "div",
|
className="student-key"
|
||||||
},
|
>
|
||||||
],
|
My name from another land
|
||||||
"props": {},
|
</div>
|
||||||
"type": "div",
|
</div>
|
||||||
},
|
|
||||||
],
|
|
||||||
"props": {
|
|
||||||
"className": "wrap-text-in-cell",
|
|
||||||
},
|
|
||||||
"type": "span",
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Gradebook Table Fields Username without external_user_key snapshot 1`] = `
|
exports[`Gradebook Table Fields Username without external_user_key snapshot 1`] = `
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ exports[`LabelReplacements TotalGradeLabelReplacement snapshot 1`] = `
|
|||||||
}
|
}
|
||||||
placement="left"
|
placement="left"
|
||||||
trigger={
|
trigger={
|
||||||
[
|
Array [
|
||||||
"hover",
|
"hover",
|
||||||
"focus",
|
"focus",
|
||||||
]
|
]
|
||||||
@@ -84,7 +84,7 @@ exports[`snapshot left to right overlay placement 1`] = `
|
|||||||
}
|
}
|
||||||
placement="right"
|
placement="right"
|
||||||
trigger={
|
trigger={
|
||||||
[
|
Array [
|
||||||
"hover",
|
"hover",
|
||||||
"focus",
|
"focus",
|
||||||
]
|
]
|
||||||
@@ -118,7 +118,7 @@ exports[`snapshot right to left overlay placement 1`] = `
|
|||||||
}
|
}
|
||||||
placement="left"
|
placement="left"
|
||||||
trigger={
|
trigger={
|
||||||
[
|
Array [
|
||||||
"hover",
|
"hover",
|
||||||
"focus",
|
"focus",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ exports[`GradebookTable snapshot 1`] = `
|
|||||||
<DataTable
|
<DataTable
|
||||||
RowStatusComponent={[MockFunction hooks.nullMethod]}
|
RowStatusComponent={[MockFunction hooks.nullMethod]}
|
||||||
columns={
|
columns={
|
||||||
[
|
Array [
|
||||||
"some",
|
"some",
|
||||||
"columns",
|
"columns",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
data={
|
data={
|
||||||
[
|
Array [
|
||||||
"some",
|
"some",
|
||||||
"data",
|
"data",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const useGradebookTableData = () => {
|
|||||||
[Headings.username]: (
|
[Headings.username]: (
|
||||||
<Fields.Username username={entry.username} userKey={entry.external_user_key} />
|
<Fields.Username username={entry.username} userKey={entry.external_user_key} />
|
||||||
),
|
),
|
||||||
[Headings.email]: (<Fields.Text value={entry.email} />),
|
[Headings.email]: (<Fields.Email email={entry.email} />),
|
||||||
[Headings.totalGrade]: `${roundGrade(entry.percent * 100)}${getLocalizedPercentSign()}`,
|
[Headings.totalGrade]: `${roundGrade(entry.percent * 100)}${getLocalizedPercentSign()}`,
|
||||||
...entry.section_breakdown.reduce((acc, subsection) => ({
|
...entry.section_breakdown.reduce((acc, subsection) => ({
|
||||||
...acc,
|
...acc,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ jest.mock('i18n/utils', () => ({
|
|||||||
jest.mock('./GradeButton', () => 'GradeButton');
|
jest.mock('./GradeButton', () => 'GradeButton');
|
||||||
jest.mock('./Fields', () => jest.requireActual('testUtils').mockNestedComponents({
|
jest.mock('./Fields', () => jest.requireActual('testUtils').mockNestedComponents({
|
||||||
Username: 'Fields.Username',
|
Username: 'Fields.Username',
|
||||||
Text: 'Fields.Text',
|
Email: 'Fields.Email',
|
||||||
}));
|
}));
|
||||||
jest.mock('./LabelReplacements', () => jest.requireActual('testUtils').mockNestedComponents({
|
jest.mock('./LabelReplacements', () => jest.requireActual('testUtils').mockNestedComponents({
|
||||||
TotalGradeLabelReplacement: 'LabelReplacements.TotalGradeLabelReplacement',
|
TotalGradeLabelReplacement: 'LabelReplacements.TotalGradeLabelReplacement',
|
||||||
@@ -158,7 +158,7 @@ describe('useGradebookTableData', () => {
|
|||||||
test('email field', () => {
|
test('email field', () => {
|
||||||
allGrades.forEach((entry, index) => {
|
allGrades.forEach((entry, index) => {
|
||||||
expect(out.data[index][Headings.email]).toMatchObject(
|
expect(out.data[index][Headings.email]).toMatchObject(
|
||||||
<Fields.Text value={entry.email} />,
|
<Fields.Email email={entry.email} />,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import useGradebookTableData from './hooks';
|
import useGradebookTableData from './hooks';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { DataTable } from '@openedx/paragon';
|
import { DataTable } from '@edx/paragon';
|
||||||
|
|
||||||
import useGradebookTableData from './hooks';
|
import useGradebookTableData from './hooks';
|
||||||
import GradebookTable from '.';
|
import GradebookTable from '.';
|
||||||
@@ -24,16 +24,16 @@ describe('GradebookTable', () => {
|
|||||||
el = shallow(<GradebookTable />);
|
el = shallow(<GradebookTable />);
|
||||||
});
|
});
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('Datatable props', () => {
|
test('Datatable props', () => {
|
||||||
const datatable = el.instance.findByType(DataTable)[0];
|
const datatable = el.find(DataTable);
|
||||||
const { props } = datatable;
|
const props = datatable.props();
|
||||||
expect(props.columns).toEqual(hookProps.columns);
|
expect(props.columns).toEqual(hookProps.columns);
|
||||||
expect(props.data).toEqual(hookProps.data);
|
expect(props.data).toEqual(hookProps.data);
|
||||||
expect(props.itemCount).toEqual(hookProps.grades.length);
|
expect(props.itemCount).toEqual(hookProps.grades.length);
|
||||||
expect(props.RowStatusComponent).toEqual(hookProps.nullMethod);
|
expect(props.RowStatusComponent).toEqual(hookProps.nullMethod);
|
||||||
expect(datatable.children[2].type).toEqual('DataTable.EmptyTable');
|
expect(datatable.children().at(2).type()).toEqual('DataTable.EmptyTable');
|
||||||
expect(datatable.children[2].props.content).toEqual(hookProps.emptyContent);
|
expect(datatable.children().at(2).props().content).toEqual(hookProps.emptyContent);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
}
|
}
|
||||||
.grade-history-header{
|
.grade-history-header{
|
||||||
float: left;
|
float: left;
|
||||||
min-width: 170px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grade-history-assignment{
|
.grade-history-assignment{
|
||||||
@@ -66,7 +65,7 @@
|
|||||||
.gradebook-container {
|
.gradebook-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
max-height: 600px;
|
height: 600px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -123,34 +122,3 @@ select#ScoreView.form-control {
|
|||||||
border-right-color: $black;
|
border-right-color: $black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#edit-filters-btn {
|
|
||||||
@include media-breakpoint-down(xs) {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-container {
|
|
||||||
@include media-breakpoint-down(xs) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pgn__modal-body-content .pgn__data-table-layout-wrapper {
|
|
||||||
@include media-breakpoint-down(sm) {
|
|
||||||
clear: both;
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-gradebook {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.sidebar-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
aside.sidebar {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,24 +1,5 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`ImportGradesButton component render Form 1`] = `
|
|
||||||
<Form
|
|
||||||
action="test-grade-export-url"
|
|
||||||
method="post"
|
|
||||||
>
|
|
||||||
<Form.Group
|
|
||||||
controlId="csv"
|
|
||||||
>
|
|
||||||
<Form.Control
|
|
||||||
className="d-none"
|
|
||||||
data-testid="file-control"
|
|
||||||
label="Upload Grade CSV"
|
|
||||||
onChange={[MockFunction props.handleFileInputChange]}
|
|
||||||
type="file"
|
|
||||||
/>
|
|
||||||
</Form.Group>
|
|
||||||
</Form>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ImportGradesButton component render snapshot 1`] = `
|
exports[`ImportGradesButton component render snapshot 1`] = `
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Form
|
<Form
|
||||||
@@ -32,7 +13,7 @@ exports[`ImportGradesButton component render snapshot 1`] = `
|
|||||||
className="d-none"
|
className="d-none"
|
||||||
data-testid="file-control"
|
data-testid="file-control"
|
||||||
label="Upload Grade CSV"
|
label="Upload Grade CSV"
|
||||||
onChange={[MockFunction props.handleFileInputChange]}
|
onChange={[MockFunction]}
|
||||||
type="file"
|
type="file"
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
@@ -41,13 +22,13 @@ exports[`ImportGradesButton component render snapshot 1`] = `
|
|||||||
className="import-grades-btn"
|
className="import-grades-btn"
|
||||||
import={true}
|
import={true}
|
||||||
label={
|
label={
|
||||||
{
|
Object {
|
||||||
"defaultMessage": "Import Grades",
|
"defaultMessage": "Import Grades",
|
||||||
"description": "A labeled button to import grades in the BulkManagement Tab File Upload Form",
|
"description": "A labeled button to import grades in the BulkManagement Tab File Upload Form",
|
||||||
"id": "gradebook.GradesView.importGradesBtnText",
|
"id": "gradebook.GradesView.importGradesBtnText",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClick={[MockFunction props.handleClickImportGrades]}
|
onClick={[MockFunction]}
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import NetworkButton from 'components/NetworkButton';
|
import NetworkButton from 'components/NetworkButton';
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
import { Form } from '@openedx/paragon';
|
import { Form } from '@edx/paragon';
|
||||||
|
|
||||||
import NetworkButton from 'components/NetworkButton';
|
import NetworkButton from 'components/NetworkButton';
|
||||||
import useImportGradesButtonData from './hooks';
|
import useImportGradesButtonData from './hooks';
|
||||||
@@ -18,8 +18,8 @@ describe('ImportGradesButton component', () => {
|
|||||||
props = {
|
props = {
|
||||||
fileInputRef: { current: null },
|
fileInputRef: { current: null },
|
||||||
gradeExportUrl: 'test-grade-export-url',
|
gradeExportUrl: 'test-grade-export-url',
|
||||||
handleClickImportGrades: jest.fn().mockName('props.handleClickImportGrades'),
|
handleClickImportGrades: jest.fn(),
|
||||||
handleFileInputChange: jest.fn().mockName('props.handleFileInputChange'),
|
handleFileInputChange: jest.fn(),
|
||||||
};
|
};
|
||||||
useImportGradesButtonData.mockReturnValue(props);
|
useImportGradesButtonData.mockReturnValue(props);
|
||||||
el = shallow(<ImportGradesButton />);
|
el = shallow(<ImportGradesButton />);
|
||||||
@@ -32,15 +32,14 @@ describe('ImportGradesButton component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('Form', () => {
|
test('Form', () => {
|
||||||
expect(el.instance.findByType(Form)[0].snapshot).toMatchSnapshot();
|
expect(el.find(Form).props().action).toEqual(props.gradeExportUrl);
|
||||||
expect(el.instance.findByType(Form)[0].props.action).toEqual(props.gradeExportUrl);
|
expect(el.find(Form.Control).props().onChange).toEqual(props.handleFileInputChange);
|
||||||
expect(el.instance.findByType(Form.Control)[0].props.onChange).toEqual(props.handleFileInputChange);
|
|
||||||
});
|
});
|
||||||
test('import button', () => {
|
test('import button', () => {
|
||||||
expect(el.instance.findByType(NetworkButton)[0].props.onClick).toEqual(props.handleClickImportGrades);
|
expect(el.find(NetworkButton).props().onClick).toEqual(props.handleClickImportGrades);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import useImportGradesButtonData from './hooks';
|
|||||||
import ImportGradesButton from '.';
|
import ImportGradesButton from '.';
|
||||||
|
|
||||||
jest.unmock('react');
|
jest.unmock('react');
|
||||||
jest.unmock('@openedx/paragon');
|
jest.unmock('@edx/paragon');
|
||||||
jest.mock('components/NetworkButton', () => 'network-button');
|
jest.mock('components/NetworkButton', () => 'network-button');
|
||||||
jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() }));
|
jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() }));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Toast } from '@openedx/paragon';
|
import { Toast } from '@edx/paragon';
|
||||||
|
|
||||||
import useImportSuccessToastData from './hooks';
|
import useImportSuccessToastData from './hooks';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from '@edx/react-unit-test-utils';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import useImportSuccessToastData from './hooks';
|
import useImportSuccessToastData from './hooks';
|
||||||
import ImportSuccessToast from '.';
|
import ImportSuccessToast from '.';
|
||||||
@@ -26,14 +26,14 @@ describe('ImportSuccessToast component', () => {
|
|||||||
});
|
});
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
test('snapshot', () => {
|
test('snapshot', () => {
|
||||||
expect(el.snapshot).toMatchSnapshot();
|
expect(el).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
test('Toast', () => {
|
test('Toast', () => {
|
||||||
expect(el.instance.type).toEqual('Toast');
|
expect(el.type()).toEqual('Toast');
|
||||||
expect(el.instance.props.action).toEqual(hookProps.action);
|
expect(el.props().action).toEqual(hookProps.action);
|
||||||
expect(el.instance.props.onClose).toEqual(hookProps.onClose);
|
expect(el.props().onClose).toEqual(hookProps.onClose);
|
||||||
expect(el.instance.props.show).toEqual(hookProps.show);
|
expect(el.props().show).toEqual(hookProps.show);
|
||||||
expect(el.instance.children[0].el).toEqual(hookProps.description);
|
expect(el.text()).toEqual(hookProps.description);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ exports[`InterventionsReport component output snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<NetworkButton
|
<NetworkButton
|
||||||
label={
|
label={
|
||||||
{
|
Object {
|
||||||
"defaultMessage": "Download Interventions",
|
"defaultMessage": "Download Interventions",
|
||||||
"description": "The labeled button to download the Intervention report from the Grades View",
|
"description": "The labeled button to download the Intervention report from the Grades View",
|
||||||
"id": "gradebook.GradesView.InterventionsReport.downloadBtn",
|
"id": "gradebook.GradesView.InterventionsReport.downloadBtn",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user