use assert_cmd::Command; use mockito::Server; use tempfile::NamedTempFile; #[test] fn render_md_reads_json_and_outputs_markdown_to_stdout() { let input = NamedTempFile::new().unwrap(); std::fs::write( input.path(), r#"{ "meta": { "repo": "org/repo", "pr_index": 1, "title": "t", "description": "PR body", "state": "open", "author": "a", "base_branch": "main", "head_branch": "f", "created_at": "2026-04-08T10:00:00Z", "updated_at": "2026-04-08T11:00:00Z", "merged_at": null }, "commits": [], "diff_stat": { "files_changed": 0, "additions": 0, "deletions": 0, "files": [] }, "reviews": [], "threads": [] }"#, ) .unwrap(); let mut cmd = Command::cargo_bin("gitea-pr-review").unwrap(); let assert = cmd .args(["render-md", "--in", input.path().to_str().unwrap()]) .assert() .success(); let stdout = String::from_utf8(assert.get_output().stdout.clone()).unwrap(); assert!(stdout.contains("# org/repo `#1` t")); assert!(stdout.contains("## Metadata")); } #[test] fn render_md_writes_to_out_file_when_requested() { let input = NamedTempFile::new().unwrap(); std::fs::write( input.path(), r#"{ "meta": { "repo": "org/repo", "pr_index": 2, "title": "t2", "description": "PR body", "state": "open", "author": "a", "base_branch": "main", "head_branch": "f", "created_at": "2026-04-08T10:00:00Z", "updated_at": "2026-04-08T11:00:00Z", "merged_at": null }, "commits": [], "diff_stat": { "files_changed": 0, "additions": 0, "deletions": 0, "files": [] }, "reviews": [], "threads": [] }"#, ) .unwrap(); let output = NamedTempFile::new().unwrap(); Command::cargo_bin("gitea-pr-review") .unwrap() .args([ "render-md", "--in", input.path().to_str().unwrap(), "--out", output.path().to_str().unwrap(), ]) .assert() .success(); let written = std::fs::read_to_string(output.path()).unwrap(); assert!(written.contains("# org/repo `#2` t2")); assert!(written.contains("## Metadata")); } #[test] fn fetch_fails_when_required_env_is_missing() { let assert = Command::cargo_bin("gitea-pr-review") .unwrap() .args(["fetch", "1"]) .env_remove("GITEA_PR_CLI_API_TOKEN") .env_remove("GITEA_PR_CLI_URL") .env_remove("GITEA_PR_CLI_REPO") .assert() .failure(); let stderr = String::from_utf8(assert.get_output().stderr.clone()).unwrap(); assert!( stderr.contains("missing required environment variable: GITEA_PR_CLI_API_TOKEN"), "stderr was: {stderr}" ); } #[test] fn fetch_writes_markdown_to_stdout_by_default() { let mut server = Server::new(); let pull_path = "/api/v1/repos/org/repo/pulls/7"; server .mock("GET", pull_path) .with_status(200) .with_body( r#"{ "number": 7, "title": "Fix parser", "state": "open", "body": "PR body", "user": { "login": "alice" }, "base": { "ref": "main" }, "head": { "ref": "feature/x" }, "created_at": "2026-04-08T10:00:00Z", "updated_at": "2026-04-08T11:00:00Z", "merged_at": null, "additions": 3, "deletions": 1, "changed_files": 1 }"#, ) .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/7/reviews") .with_status(200) .with_body( r#"[ { "id": 55, "state": "COMMENT", "user": { "login": "bob" }, "submitted_at": "2026-04-08T12:00:00Z" } ]"#, ) .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/7/reviews/55/comments") .with_status(200) .with_body( r#"[ { "id": 501, "body": "please fix", "created_at": "2026-04-08T12:01:00Z", "updated_at": null, "user": { "login": "bob" }, "path": "src/main.rs", "line": 12, "pull_request_review_id": 55, "original_position": 1, "position": 1, "commit_id": "abcdef123456", "original_commit_id": "abcdef123456", "diff_hunk": "@@ -1,1 +1,1 @@" } ]"#, ) .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/7/commits") .with_status(200) .with_body( r#"[ { "sha": "abcdef1234567890", "commit": { "message": "fix: parser\n\nbody", "author": { "name": "alice", "date": "2026-04-08T10:30:00Z" } } } ]"#, ) .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/7/files") .with_status(200) .with_body( r#"[ { "filename": "src/main.rs", "additions": 3, "deletions": 1, "changes": 4, "status": "modified", "previous_filename": null } ]"#, ) .create(); let assert = Command::cargo_bin("gitea-pr-review") .unwrap() .args(["fetch", "7"]) .env("GITEA_PR_CLI_API_TOKEN", "token") .env("GITEA_PR_CLI_URL", server.url()) .env("GITEA_PR_CLI_REPO", "org/repo") .assert() .success(); let stdout = String::from_utf8(assert.get_output().stdout.clone()).unwrap(); assert!(stdout.contains("# org/repo `#7` Fix parser")); assert!(stdout.contains("## Commits")); assert!(stdout.contains("## Diff Stat")); assert!(stdout.contains("## Review 7.1 (COMMENT)")); } #[test] fn fetch_writes_json_to_out_file_when_requested() { let mut server = Server::new(); let pull_path = "/api/v1/repos/org/repo/pulls/8"; server .mock("GET", pull_path) .with_status(200) .with_body( r#"{ "number": 8, "title": "Add feature", "state": "open", "body": "PR body", "user": { "login": "alice" }, "base": { "ref": "main" }, "head": { "ref": "feature/y" }, "created_at": "2026-04-08T10:00:00Z", "updated_at": "2026-04-08T11:00:00Z", "merged_at": null, "additions": 0, "deletions": 0, "changed_files": 0 }"#, ) .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/8/reviews") .with_status(200) .with_body("[]") .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/8/commits") .with_status(200) .with_body("[]") .create(); server .mock("GET", "/api/v1/repos/org/repo/pulls/8/files") .with_status(200) .with_body("[]") .create(); let output = NamedTempFile::new().unwrap(); Command::cargo_bin("gitea-pr-review") .unwrap() .args([ "fetch", "8", "--format", "json", "--out", output.path().to_str().unwrap(), ]) .env("GITEA_PR_CLI_API_TOKEN", "token") .env("GITEA_PR_CLI_URL", server.url()) .env("GITEA_PR_CLI_REPO", "org/repo") .assert() .success(); let written = std::fs::read_to_string(output.path()).unwrap(); assert!(written.contains("\"repo\": \"org/repo\"")); assert!(written.contains("\"pr_index\": 8")); assert!(written.contains("\"head_branch\": \"feature/y\"")); }