Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for relative links #1489

Merged
merged 15 commits into from
Oct 26, 2024
8 changes: 8 additions & 0 deletions fixtures/resolve_paths/about/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<head>
<title>About</title>
</head>
<body>
<h1 id="fragment">About</h1>
</body>
</html>
Empty file.
21 changes: 21 additions & 0 deletions fixtures/resolve_paths/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<html>
<head>
<title>Index</title>
</head>
<body>
<h1>Index Title</h1>
<p>
<ul>
<li>
<a href="/">home</a>
</li>
<li>
<a href="/about">About</a>
</li>
<li>
<a href="/another page">About</a>
</li>
</ul>
</p>
</body>
</html>
1 change: 1 addition & 0 deletions lychee-bin/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub(crate) fn create(cfg: &Config, cookie_jar: Option<&Arc<CookieStoreMutex>>) -

ClientBuilder::builder()
.remaps(remaps)
.base(cfg.base.clone())
.includes(includes)
.excludes(excludes)
.exclude_all_private(cfg.exclude_all_private)
Expand Down
10 changes: 4 additions & 6 deletions lychee-bin/src/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,14 +429,12 @@ mod tests {

#[tokio::test]
async fn test_invalid_url() {
// Run a normal request with an invalid Url
let client = ClientBuilder::builder().build().client().unwrap();
let request = Request::try_from("http://\"").unwrap();
let response = check_url(&client, request).await;
assert!(response.status().is_error());
let uri = Uri::try_from("http://\"").unwrap();
let response = client.check_website(&uri, None).await.unwrap();
assert!(matches!(
response.status(),
Status::Error(ErrorKind::InvalidURI(_))
response,
Status::Unsupported(ErrorKind::BuildRequestClient(_))
));
}

Expand Down
10 changes: 8 additions & 2 deletions lychee-bin/src/formatters/response/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ mod tests {
}
}

#[cfg(test)]
/// Helper function to strip ANSI color codes for tests
fn strip_ansi_codes(s: &str) -> String {
console::strip_ansi_codes(s).to_string()
}

#[test]
fn test_format_response_with_ok_status() {
let formatter = ColorFormatter;
let body = mock_response_body(Status::Ok(StatusCode::OK), "https://example.com");
assert_eq!(
formatter.format_response(&body),
strip_ansi_codes(&formatter.format_response(&body)),
" [200] https://example.com/"
);
}
Expand All @@ -83,7 +89,7 @@ mod tests {
"https://example.com/404",
);
assert_eq!(
formatter.format_response(&body),
strip_ansi_codes(&formatter.format_response(&body)),
" [ERROR] https://example.com/404"
);
}
Expand Down
67 changes: 56 additions & 11 deletions lychee-bin/tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,17 @@ mod cli {
#[test]
fn test_resolve_paths() {
let mut cmd = main_command();
let offline_dir = fixtures_path().join("offline");
let dir = fixtures_path().join("resolve_paths");

cmd.arg("--offline")
.arg("--base")
.arg(&offline_dir)
.arg(offline_dir.join("index.html"))
.arg(&dir)
.arg(dir.join("index.html"))
.env_clear()
.assert()
.success()
.stdout(contains("4 Total"))
.stdout(contains("4 OK"));
.stdout(contains("3 Total"))
.stdout(contains("3 OK"));
}

#[test]
Expand Down Expand Up @@ -944,13 +944,17 @@ mod cli {

// check content of cache file
let data = fs::read_to_string(&cache_file)?;

if data.is_empty() {
println!("Cache file is empty!");
}

assert!(data.contains(&format!("{}/,200", mock_server_ok.uri())));
assert!(!data.contains(&format!("{}/,204", mock_server_no_content.uri())));
assert!(!data.contains(&format!("{}/,429", mock_server_too_many_requests.uri())));

// clear the cache file
fs::remove_file(&cache_file)?;

Ok(())
}

Expand Down Expand Up @@ -1216,8 +1220,9 @@ mod cli {
Ok(())
}

/// If base-dir is not set, don't throw an error in case we encounter
/// an absolute local link within a file (e.g. `/about`).
/// If `base-dir` is not set, don't throw an error in case we encounter
/// an absolute local link (e.g. `/about`) within a file.
/// Instead, simply ignore the link.
#[test]
fn test_ignore_absolute_local_links_without_base() -> Result<()> {
let mut cmd = main_command();
Expand Down Expand Up @@ -1409,9 +1414,7 @@ mod cli {
.arg("./NOT-A-REAL-TEST-FIXTURE.md")
.assert()
.failure()
.stderr(contains(
"Cannot find local file ./NOT-A-REAL-TEST-FIXTURE.md",
));
.stderr(contains("Invalid file path: ./NOT-A-REAL-TEST-FIXTURE.md"));

Ok(())
}
Expand Down Expand Up @@ -1667,4 +1670,46 @@ mod cli {
.success()
.stdout(contains("0 Errors"));
}

/// Test relative paths
///
/// Imagine a web server hosting a site with the following structure:
/// root
/// └── test
/// ├── index.html
/// └── next.html
///
/// where `root/test/index.html` contains `<a href="next.html">next</a>`
/// When checking the link in `root/test/index.html` we should be able to
/// resolve the relative path to `root/test/next.html`
///
/// Note that the relative path is not resolved to the root of the server
/// but relative to the file that contains the link.
#[tokio::test]
async fn test_resolve_relative_paths_in_subfolder() -> Result<()> {
let mock_server = wiremock::MockServer::start().await;

let body = r#"<a href="next.html">next</a>"#;
wiremock::Mock::given(wiremock::matchers::method("GET"))
.and(wiremock::matchers::path("/test/index.html"))
.respond_with(wiremock::ResponseTemplate::new(200).set_body_string(body))
.mount(&mock_server)
.await;

wiremock::Mock::given(wiremock::matchers::method("GET"))
.and(wiremock::matchers::path("/test/next.html"))
.respond_with(wiremock::ResponseTemplate::new(200))
.mount(&mock_server)
.await;

let mut cmd = main_command();
cmd.arg("--verbose")
.arg(format!("{}/test/index.html", mock_server.uri()))
.assert()
.success()
.stdout(contains("1 Total"))
.stdout(contains("0 Errors"));

Ok(())
}
}
80 changes: 0 additions & 80 deletions lychee-lib/src/checker.rs

This file was deleted.

Loading
Loading