Skip to content

Commit 2ca5a29

Browse files
committed
fetch/fetch_feedback failure tests
1 parent b30b1b1 commit 2ca5a29

File tree

2 files changed

+247
-23
lines changed

2 files changed

+247
-23
lines changed

nbgrader/tests/labextension_ui-tests/tests/test_assignment_list.spec.ts

+162
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,54 @@ test('Fetch assignments', async({
309309

310310
});
311311

312+
/*
313+
* Test fetch failure
314+
*/
315+
test('Fetch failure', async({
316+
page,
317+
baseURL,
318+
tmpPath
319+
}) => {
320+
321+
test.skip(is_windows, 'This feature is not implemented for Windows');
322+
323+
if (baseURL === undefined) throw new Error("BaseURL is undefined.");
324+
325+
// create directories and config files, and open assignment_list tab
326+
await create_env(page, tmpPath, exchange_dir, cache_dir, is_windows);
327+
await add_courses(page, baseURL, tmpPath);
328+
await open_assignment_list(page);
329+
330+
// release some assignments
331+
await execute_command("nbgrader generate_assignment 'Problem Set 1' --force");
332+
await execute_command("nbgrader release_assignment 'Problem Set 1' --course 'abc101' --force");
333+
await execute_command("nbgrader generate_assignment 'ps.01' --force");
334+
await execute_command("nbgrader release_assignment 'ps.01' --course 'xyz 200' --force");
335+
336+
// refresh assignment list
337+
await page.locator('#refresh_assignments_list').click();
338+
339+
// select one course
340+
await select_course(page, 'abc101');
341+
342+
// remove write permissions
343+
// check that there is only one released, and try fetch it
344+
// then restore permissions again
345+
await fs.chmod("nbgrader-assignment-list-test", 0o555, err => {});
346+
var rows = await wait_for_list(page, 'released', 1);
347+
await rows.first().locator('.item_status button').click();
348+
await new Promise(resolve => setTimeout(resolve, 1000)); // to make sure permissions are not restored too fast
349+
await fs.chmod("nbgrader-assignment-list-test", 0o777, err => {});
350+
351+
// check that there is still only one released
352+
rows = await wait_for_list(page, 'released', 1);
353+
354+
// Check and close the error message
355+
await wait_for_error_modal(page);
356+
await close_error_modal(page);
357+
358+
});
359+
312360
/*
313361
* Test submit assignment
314362
*/
@@ -711,3 +759,117 @@ test('Missing exchange directory', async({
711759
expect(rows.first().locator('.item_course')).toHaveText("abc101");
712760

713761
});
762+
763+
/*
764+
* Test fetching feedback
765+
*/
766+
test('Fetch feedback', async({
767+
page,
768+
baseURL,
769+
tmpPath
770+
}) => {
771+
772+
test.skip(is_windows, 'This feature is not implemented for Windows');
773+
774+
if (baseURL === undefined) throw new Error("BaseURL is undefined.");
775+
776+
// create directories and config files, and open assignment_list tab
777+
await create_env(page, tmpPath, exchange_dir, cache_dir, is_windows);
778+
await add_courses(page, baseURL, tmpPath);
779+
await open_assignment_list(page);
780+
781+
// release some assignments
782+
await execute_command("nbgrader generate_assignment 'Problem Set 1' --force");
783+
await execute_command("nbgrader release_assignment 'Problem Set 1' --course 'abc101' --force");
784+
await execute_command("nbgrader generate_assignment 'ps.01' --force");
785+
await execute_command("nbgrader release_assignment 'ps.01' --course 'xyz 200' --force");
786+
787+
// refresh assignment list
788+
await page.locator('#refresh_assignments_list').click();
789+
790+
// select one course
791+
await select_course(page, 'xyz 200');
792+
793+
// check that there is only one released, and fetch it
794+
var rows = await wait_for_list(page, 'released', 1);
795+
await rows.first().locator('.item_status button').click();
796+
797+
// check that there is only one fetched and submit
798+
rows = await wait_for_list(page, 'fetched', 1);
799+
await rows.first().locator('.item_status button:text("Submit")').click();
800+
801+
// collect submitted assignment and process it
802+
await execute_command("nbgrader collect 'ps.01' --course 'xyz 200'");
803+
await execute_command("nbgrader autograde 'ps.01' --course 'xyz 200'");
804+
await execute_command("nbgrader generate_feedback 'ps.01' --course 'xyz 200'");
805+
await execute_command("nbgrader release_feedback 'ps.01' --course 'xyz 200'");
806+
807+
// check that there is only one submitted and fetch feedback
808+
rows = await wait_for_list(page, 'submitted', 1);
809+
await rows.first().locator('.item_status button:text("Fetch feedback")').click();
810+
811+
// check that there is only one fetched
812+
rows = await wait_for_list(page, 'submitted', 1);
813+
expect(rows.first().locator('.item_name').first()).toHaveText("ps.01");
814+
expect(rows.first().locator('.item_course').first()).toHaveText("xyz 200");
815+
816+
// check that the directory has been created
817+
const contents = galata.newContentsHelper(baseURL);
818+
expect(contents.directoryExists('ps.01/feedback'));
819+
});
820+
821+
/*
822+
* Test fetch feedback failure
823+
*/
824+
test('Fetch feedback failure', async({
825+
page,
826+
baseURL,
827+
tmpPath
828+
}) => {
829+
830+
test.skip(is_windows, 'This feature is not implemented for Windows');
831+
832+
if (baseURL === undefined) throw new Error("BaseURL is undefined.");
833+
834+
// create directories and config files, and open assignment_list tab
835+
await create_env(page, tmpPath, exchange_dir, cache_dir, is_windows);
836+
await add_courses(page, baseURL, tmpPath);
837+
await open_assignment_list(page);
838+
839+
// release some assignments
840+
await execute_command("nbgrader generate_assignment 'Problem Set 1' --force");
841+
await execute_command("nbgrader release_assignment 'Problem Set 1' --course 'abc101' --force");
842+
await execute_command("nbgrader generate_assignment 'ps.01' --force");
843+
await execute_command("nbgrader release_assignment 'ps.01' --course 'xyz 200' --force");
844+
845+
// refresh assignment list
846+
await page.locator('#refresh_assignments_list').click();
847+
848+
// select one course
849+
await select_course(page, 'xyz 200');
850+
851+
// check that there is only one released, and fetch it
852+
var rows = await wait_for_list(page, 'released', 1);
853+
await rows.first().locator('.item_status button').click();
854+
855+
// check that there is only one fetched and submit
856+
rows = await wait_for_list(page, 'fetched', 1);
857+
await rows.first().locator('.item_status button:text("Submit")').click();
858+
859+
// collect submitted assignment and process it
860+
await execute_command("nbgrader collect 'ps.01' --course 'xyz 200'");
861+
await execute_command("nbgrader autograde 'ps.01' --course 'xyz 200'");
862+
await execute_command("nbgrader generate_feedback 'ps.01' --course 'xyz 200'");
863+
await execute_command("nbgrader release_feedback 'ps.01' --course 'xyz 200'");
864+
865+
// check that there is only one submitted and try fetching feedback
866+
await fs.chmod("nbgrader-assignment-list-test/ps.01", 0o555, err => {console.log(err)});
867+
rows = await wait_for_list(page, 'submitted', 1);
868+
await rows.first().locator('.item_status button:text("Fetch Feedback")').click();
869+
await new Promise(resolve => setTimeout(resolve, 5000)); // to make sure permissions are not restored too fast
870+
await fs.chmod("nbgrader-assignment-list-test/ps.01", 0o777, err => {});
871+
872+
// Check and close the error message
873+
await wait_for_error_modal(page);
874+
await close_error_modal(page);
875+
});

nbgrader/tests/nbextensions/test_assignment_list.py

+85-23
Original file line numberDiff line numberDiff line change
@@ -470,35 +470,97 @@ def test_validate_failure(browser, port, class_files, tempdir):
470470

471471
@pytest.mark.nbextensions
472472
@notwindows
473-
def test_missing_exchange(exchange, browser, port, class_files, tempdir):
474-
# remove the exchange directory and fetched assignments
475-
rmtree(exchange)
476-
rmtree(os.path.join(tempdir, "Problem Set 1"))
477-
473+
def test_fetch_failure(browser, port, class_files, tempdir):
474+
# remove already fetched assignment to try fetching again
475+
shutil.rmtree('ps.01')
478476
_load_assignments_list(browser, port)
479477
_wait_until_loaded(browser)
480478

481-
# make sure all the errors are showing
482-
_wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#released_assignments_list_error")))
483-
_wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#fetched_assignments_list_error")))
484-
_wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#submitted_assignments_list_error")))
479+
# choose the course "xyz 200"
480+
_change_course(browser, "xyz 200")
485481

486-
# verify that the dropdown list shows an error too
487-
default = browser.find_element(By.CSS_SELECTOR, "#course_list_default")
488-
assert default.text == "Error fetching courses!"
482+
# remove write permissions, click the "fetch" button, and restore permissions
483+
os.chmod(tempdir, 0o555)
484+
rows = _wait_for_list(browser, "released", 1)
485+
rows[0].find_element(By.CSS_SELECTOR, ".item_status button").click()
486+
os.chmod(tempdir, 0o777)
489487

490-
# recreate the exchange and make sure refreshing works as expected
491-
os.makedirs(exchange)
488+
# wait for the modal dialog to appear
489+
_wait_for_modal(browser)
492490

493-
# release an assignment
494-
run_nbgrader(["generate_assignment", "Problem Set 1", "--force"])
495-
run_nbgrader(["release_assignment", "Problem Set 1", "--course", "abc101", "--force"])
491+
# check that error message is given
492+
modal = browser.find_element(By.ID, "fetch-message")
493+
assert modal.text[:23] == "Assignment not fetched:"
496494

497-
# click the refresh button
498-
browser.find_element(By.CSS_SELECTOR, "#refresh_assignments_list").click()
495+
# close the modal dialog
496+
_dismiss_modal(browser)
497+
498+
499+
@pytest.mark.nbextensions
500+
@notwindows
501+
def test_fetch_feedback_failure(browser, port, class_files, tempdir):
502+
_load_assignments_list(browser, port)
499503
_wait_until_loaded(browser)
500504

501-
# wait for the released assignments to update
502-
rows = _wait_for_list(browser, "released", 1)
503-
assert rows[0].find_element(By.CLASS_NAME, "item_name").text == "Problem Set 1"
504-
assert rows[0].find_element(By.CLASS_NAME, "item_course").text == "abc101"
505+
# generate fetchable feedback
506+
run_nbgrader(["fetch_assignment", "ps.01", "--course", "xyz 200"])
507+
run_nbgrader(["submit", "ps.01", "--course", "xyz 200"])
508+
run_nbgrader(["collect", "ps.01", "--course", "xyz 200"])
509+
run_nbgrader(["autograde", "ps.01", "--course", "xyz 200"])
510+
run_nbgrader(["generate_feedback", "ps.01", "--course", "xyz 200"])
511+
run_nbgrader(["release_feedback", "ps.01", "--course", "xyz 200"])
512+
513+
# choose the course "xyz 200"
514+
_change_course(browser, "xyz 200")
515+
516+
# try fetching feedback without write permissions
517+
os.chmod(os.path.join(tempdir, "ps.01"), 0o555)
518+
rows = _wait_for_list(browser, "submitted", 1)
519+
rows[0].find_element(By.CSS_SELECTOR, ".item_status button").click()
520+
os.chmod(os.path.join(tempdir, "ps.01"), 0o777)
521+
522+
# wait for the modal dialog to appear
523+
_wait_for_modal(browser)
524+
525+
# check that error message is given
526+
modal = browser.find_element(By.ID, "fetchfeedback-message")
527+
assert modal.text[:21] == "Feedback not fetched:"
528+
529+
# close the modal dialog
530+
_dismiss_modal(browser)
531+
532+
533+
# @pytest.mark.nbextensions
534+
# @notwindows
535+
# def test_missing_exchange(exchange, browser, port, class_files, tempdir):
536+
# # remove the exchange directory and fetched assignments
537+
# rmtree(exchange)
538+
# rmtree(os.path.join(tempdir, "Problem Set 1"))
539+
#
540+
# _load_assignments_list(browser, port)
541+
# _wait_until_loaded(browser)
542+
#
543+
# # make sure all the errors are showing
544+
# _wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#released_assignments_list_error")))
545+
# _wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#fetched_assignments_list_error")))
546+
# _wait(browser).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#submitted_assignments_list_error")))
547+
#
548+
# # verify that the dropdown list shows an error too
549+
# default = browser.find_element(By.CSS_SELECTOR, "#course_list_default")
550+
# assert default.text == "Error fetching courses!"
551+
#
552+
# # recreate the exchange and make sure refreshing works as expected
553+
# os.makedirs(exchange)
554+
#
555+
# # release an assignment
556+
# run_nbgrader(["generate_assignment", "Problem Set 1", "--force"])
557+
# run_nbgrader(["release_assignment", "Problem Set 1", "--course", "abc101", "--force"])
558+
#
559+
# # click the refresh button
560+
# browser.find_element(By.CSS_SELECTOR, "#refresh_assignments_list").click()
561+
# _wait_until_loaded(browser)
562+
#
563+
# # wait for the released assignments to update
564+
# rows = _wait_for_list(browser, "released", 1)
565+
# assert rows[0].find_element(By.CLASS_NAME, "item_name").text == "Problem Set 1"
566+
# assert rows[0].find_element(By.CLASS_NAME, "item_course").text == "abc101"

0 commit comments

Comments
 (0)