Skip to content

Commit 3aa0e37

Browse files
Merge branch 'main' into dev
2 parents e1c10ea + a054d42 commit 3aa0e37

7 files changed

Lines changed: 50 additions & 151 deletions

File tree

src/commands/command_util.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,8 +507,10 @@ static CONFIG_FILE_NAME: &str = "course_config.toml";
507507

508508
/// Checks if current directory or given path
509509
/// contains valid exercise (i.e config file)
510-
/// Returns Err(msg) if given invalid path (including root )
511-
pub fn find_submit_or_paste_config(
510+
/// Returns Err(msg) if given invalid path (including root)
511+
/// Returns Ok(()) if no path given, but if current dir is not
512+
/// an exercise, leaves course_config as None
513+
pub fn find_course_config_for_exercise(
512514
exercise_slug: &mut String,
513515
course_config: &mut Option<CourseConfig>,
514516
exercise_dir: &mut PathBuf,
@@ -581,7 +583,7 @@ pub fn read_new_course_config(course_config_path: &Path) -> Result<Option<Course
581583
}
582584
}
583585

584-
// retrieves exercise id for exercise from CourseConfig
586+
/// Retrieves exercise id for exercise from CourseConfig
585587
pub fn get_exercise_id_from_config(
586588
course_config: &CourseConfig,
587589
exercise_slug: &str,
@@ -593,7 +595,7 @@ pub fn get_exercise_id_from_config(
593595
}
594596
}
595597

596-
// generates return_url for submissions and pastes
598+
/// Generates return_url for submissions and pastes
597599
pub fn generate_return_url(exercise_id: usize) -> String {
598600
format!(
599601
"{}/api/v8/core/exercises/{}/submissions",
@@ -609,7 +611,8 @@ pub fn get_projects_dir() -> PathBuf {
609611
tmc_langs::get_projects_dir(PLUGIN).unwrap()
610612
}
611613

612-
/// Gives a list of all courses in projects-folder
614+
/// Choose course and then exercise interactively, return exercise path
615+
/// or Err(String) if either menu is interrupted or no items found
613616
pub fn choose_exercise() -> Result<PathBuf, String> {
614617
let mut courses: Vec<String> = Vec::new();
615618

src/commands/download_command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::PathBuf;
22
use std::process::Command;
33

44
use super::command_util;
5-
use super::command_util::*;
5+
use super::command_util::{get_projects_dir, Client};
66
use crate::interactive;
77
use crate::io_module::{Io, PrintColor};
88
use crate::progress_reporting;

src/commands/exercises_command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::command_util::*;
1+
use super::command_util::{get_course_id_by_name, Client};
22
use crate::io_module::{Io, PrintColor};
33

44
use tmc_client::CourseExercise;

src/commands/paste_command.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::command_util;
2-
use super::command_util::{ask_exercise_interactive, find_submit_or_paste_config, Client};
2+
use super::command_util::{ask_exercise_interactive, find_course_config_for_exercise, Client};
33
use crate::io_module::{Io, PrintColor};
44
use crate::progress_reporting;
55
use crate::progress_reporting::ProgressBarManager;
@@ -24,7 +24,7 @@ pub fn paste(io: &mut dyn Io, client: &mut dyn Client, path: &str) {
2424
let mut course_config = None;
2525
let mut exercise_dir = std::path::PathBuf::new();
2626

27-
if let Err(error) = find_submit_or_paste_config(
27+
if let Err(error) = find_course_config_for_exercise(
2828
&mut exercise_name,
2929
&mut course_config,
3030
&mut exercise_dir,

src/commands/submit_command.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::command_util;
2-
use super::command_util::*;
2+
use super::command_util::{ask_exercise_interactive, find_course_config_for_exercise, Client};
33
use crate::io_module::{Io, PrintColor};
44
use crate::progress_reporting;
55
use crate::progress_reporting::ProgressBarManager;
@@ -33,7 +33,7 @@ fn submit_logic(io: &mut dyn Io, client: &mut dyn Client, path: &str) {
3333
let mut course_config = None;
3434
let mut exercise_dir = std::path::PathBuf::new();
3535

36-
if let Err(error) = find_submit_or_paste_config(
36+
if let Err(error) = find_course_config_for_exercise(
3737
&mut exercise_name,
3838
&mut course_config,
3939
&mut exercise_dir,
@@ -205,8 +205,8 @@ fn into_locale(arg: &str) -> Result<Language> {
205205
#[cfg(test)]
206206
mod tests {
207207
use super::*;
208+
use command_util::MockClient;
208209
use std::slice::Iter;
209-
210210
pub struct IoTest<'a> {
211211
list: &'a mut Vec<String>,
212212
input: &'a mut Iter<'a, &'a str>,

src/commands/test_command.rs

Lines changed: 34 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,48 @@
11
use crate::commands::command_util;
2-
use crate::commands::command_util::ask_exercise_interactive;
2+
use crate::commands::command_util::{ask_exercise_interactive, find_course_config_for_exercise};
33
use crate::io_module::{Io, PrintColor};
4-
use std::env;
5-
use std::path::{Path, PathBuf};
4+
use std::path::Path;
65
use tmc_langs::RunResult;
76

8-
/// Executes tmc tests for exercise(s)
7+
/// Executes tmc tests for one exercise. If path not given, check if current folder is an exercise.
8+
/// If not, asks exercise with an interactive menu.
99
pub fn test(io: &mut dyn Io, exercise_folder: Option<&str>) {
10-
let status = match env::current_dir() {
11-
Ok(mut pathbuf) => {
12-
if let Some(exercise) = exercise_folder {
13-
pathbuf.push(exercise);
14-
}
10+
let mut exercise_name = "".to_string();
11+
let mut course_config = None;
12+
let mut exercise_dir = std::path::PathBuf::new();
1513

16-
match tmc_langs::find_exercise_directories(pathbuf.as_path()) {
17-
Ok(exercises) => match exercises.len() {
18-
0 => ask_interactively_and_test(io),
19-
1 => test_exercise_path(io, exercises[0].as_path()),
20-
_ => test_exercises(io, exercises),
21-
},
22-
Err(_) => ask_interactively_and_test(io),
23-
}
24-
}
25-
Err(error) => Err(format!(
26-
"Invalid directory / Insufficient permissions: {}",
27-
error
28-
)),
29-
};
14+
let path = std::env::current_dir().unwrap();
15+
let mut path = path.to_str().unwrap();
16+
if let Some(folder) = exercise_folder {
17+
path = folder;
18+
}
3019

31-
if let Err(err) = status {
32-
io.println(&err, PrintColor::Failed);
20+
if let Err(error) = find_course_config_for_exercise(
21+
&mut exercise_name,
22+
&mut course_config,
23+
&mut exercise_dir,
24+
path,
25+
) {
26+
if exercise_folder.is_some() {
27+
io.println(&error, PrintColor::Failed);
28+
return;
29+
}
3330
}
34-
}
3531

36-
/// Asks with interactive menu what exercise should be tested and runs tests
37-
fn ask_interactively_and_test(io: &mut dyn Io) -> Result<(), String> {
38-
// No exercises found, ask with interactive menu
39-
let mut exercise_name = String::from("");
40-
let mut exercise_dir: PathBuf = PathBuf::new();
41-
let mut course_config = None;
42-
match ask_exercise_interactive(&mut exercise_name, &mut exercise_dir, &mut course_config) {
43-
Ok(()) => (),
44-
Err(msg) => {
45-
return Err(msg);
32+
if course_config.is_none() {
33+
// Did not find course config, use interactive selection if possible
34+
match ask_exercise_interactive(&mut exercise_name, &mut exercise_dir, &mut course_config) {
35+
Ok(()) => (),
36+
Err(msg) => {
37+
io.println(&msg, PrintColor::Failed);
38+
return;
39+
}
4640
}
4741
}
48-
test_exercise_path(io, &exercise_dir)
42+
43+
if let Err(err) = test_exercise_path(io, &exercise_dir) {
44+
io.println(&err, PrintColor::Failed);
45+
}
4946
}
5047

5148
/// Wrapper around test_exercise funtion to get uniform Result type
@@ -56,25 +53,6 @@ fn test_exercise_path(io: &mut dyn Io, path: &Path) -> Result<(), String> {
5653
Ok(())
5754
}
5855
}
59-
/// Executes tmc tests for multiple exercises
60-
fn test_exercises(io: &mut dyn Io, paths: Vec<PathBuf>) -> Result<(), String> {
61-
let mut exercises_completed = 0_usize;
62-
let mut exercises_total = 0_usize;
63-
for exercise_path in paths {
64-
match test_exercise(io, exercise_path.as_path(), false) {
65-
Ok(passed) => {
66-
exercises_total += 1;
67-
if passed {
68-
exercises_completed += 1;
69-
}
70-
}
71-
Err(err) => return Err(err), // Stops iteration on first error
72-
}
73-
}
74-
75-
print_result_tests(io, exercises_completed, exercises_total);
76-
Ok(())
77-
}
7856

7957
/// Executes tests for a single exercise, returns true if all tests passed (false if not).
8058
fn test_exercise(io: &mut dyn Io, path: &Path, print_progress: bool) -> Result<bool, String> {
@@ -97,22 +75,6 @@ fn test_exercise(io: &mut dyn Io, path: &Path, print_progress: bool) -> Result<b
9775
}
9876
}
9977

100-
/// Prints the end result of running multiple tests
101-
fn print_result_tests(io: &mut dyn Io, exercises_completed: usize, exercises_total: usize) {
102-
io.println("", PrintColor::Normal);
103-
io.println(
104-
&format!(
105-
"Total results: {}/{} exercises passed",
106-
exercises_completed, exercises_total
107-
),
108-
PrintColor::Normal,
109-
);
110-
io.println(
111-
&command_util::get_progress_string(exercises_completed, exercises_total, 64),
112-
PrintColor::Normal,
113-
);
114-
}
115-
11678
/// Prints the result of running tests for a single exercise
11779
fn print_result_test(
11880
io: &mut dyn Io,
@@ -485,71 +447,5 @@ mod tests {
485447
"print_result_test returned true, expected false"
486448
);
487449
}
488-
489-
#[test]
490-
fn print_multiple_completed_tests_results_test() {
491-
let mut v: Vec<String> = Vec::new();
492-
let input = vec![];
493-
let mut input = input.iter();
494-
495-
let mut io = IoTest {
496-
list: &mut v,
497-
input: &mut input,
498-
};
499-
500-
print_result_tests(&mut io, 10, 10);
501-
502-
assert_eq!(io.list[0], "");
503-
504-
assert!(
505-
io.list[1].contains("Total results"),
506-
"line does not contain 'Total results'"
507-
);
508-
assert!(
509-
io.list[1].contains("10/10"),
510-
"line does not contain total completed exercises '10/10'"
511-
);
512-
assert!(
513-
io.list[2].contains("█"),
514-
"line does not contain progress char '█'"
515-
);
516-
assert!(
517-
!io.list[2].contains("░"),
518-
"line contains progress char '░', which should not appear at 100% completed"
519-
);
520-
}
521-
522-
#[test]
523-
fn print_multiple_failed_tests_results_test() {
524-
let mut v: Vec<String> = Vec::new();
525-
let input = vec![];
526-
let mut input = input.iter();
527-
528-
let mut io = IoTest {
529-
list: &mut v,
530-
input: &mut input,
531-
};
532-
533-
print_result_tests(&mut io, 5, 10);
534-
535-
assert_eq!(io.list[0], "");
536-
537-
assert!(
538-
io.list[1].contains("Total results"),
539-
"line does not contain 'Total results'"
540-
);
541-
assert!(
542-
io.list[1].contains("5/10"),
543-
"line does not contain total completed exercises '10/10'"
544-
);
545-
assert!(
546-
io.list[2].contains("█"),
547-
"line does not contain progress char '█'"
548-
);
549-
assert!(
550-
io.list[2].contains("░"),
551-
"line does not contain progress char '░'"
552-
);
553-
}
554450
}
555451
}

tests/command_line_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn all_integration_tests() -> Result<(), Box<dyn std::error::Error>> {
124124
.arg("folder/nonexistant_ex");
125125
cmd.assert()
126126
.success()
127-
.stdout(predicate::str::contains("No exercises found"));
127+
.stdout(predicate::str::contains("Invalid exercise path given"));
128128

129129
// tmc-cli-rust --testmode --no-update logout
130130
let mut cmd = Command::cargo_bin(PKG_NAME.unwrap())?;

0 commit comments

Comments
 (0)