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

Feature/test status codes #714

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ members = [
"websockets/chat",
"websockets/echo-actorless",
"websockets/echo",
"test/status-codes",
]

[workspace.package]
Expand Down
11 changes: 11 additions & 0 deletions test/status-codes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "status-codes"
version = "0.1.0"
publish.workspace = true
edition.workspace = true
rust-version.workspace = true

[dependencies]
actix-web.workspace = true
env_logger.workspace = true
log.workspace = true
18 changes: 18 additions & 0 deletions test/status-codes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Status Code

The [StatusCode](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html) trait contains the methods to test for the status codes.
There are mainly two ways to test for the returning status code:

1. Test for the exact status code (defined [here](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html#impl-StatusCode-1))
2. Test for the status code classes `informational`, `success`, `redirect`, `client_error` and `server_error` (defined [here](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html#method.is_success))

You can find the list of status codes definitions and their constants [here](https://docs.rs/http/0.2.9/src/http/status.rs.html#323-515).

RFC 7231 [docs](https://datatracker.ietf.org/doc/html/rfc7231#section-6.2).

## server

```sh
cd test/status-codes
cargo test
```
143 changes: 143 additions & 0 deletions test/status-codes/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use actix_web::{get, middleware, App, HttpResponse, HttpServer, Responder};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

log::info!("starting HTTP server at http://localhost:8080");

HttpServer::new(|| {
App::new()
.wrap(middleware::Logger::default())
.service(information_handler)
.service(success_handler)
.service(redirect_handler)
.service(client_error_handler)
.service(server_error_handler)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}

#[get("/")]
async fn information_handler() -> impl Responder {
HttpResponse::Ok().finish()
}

#[get("/")]
async fn success_handler() -> impl Responder {
HttpResponse::Ok().finish()
}

#[get("/")]
async fn redirect_handler() -> impl Responder {
HttpResponse::TemporaryRedirect().finish()
}

#[get("/")]
async fn client_error_handler() -> impl Responder {
HttpResponse::ImATeapot().finish()
}

#[get("/")]
async fn server_error_handler() -> impl Responder {
HttpResponse::NotImplemented().finish()
}

#[cfg(test)]
mod tests {
use actix_web::{dev::Service, http, test, App, Error};

use super::*;

#[actix_web::test]
/// Test informational status codes `1xx`
async fn test_informational() -> Result<(), Error> {
let app = App::new().service(information_handler);
let app = test::init_service(app).await;

let req = test::TestRequest::get().uri("/").to_request();
let resp = app.call(req).await?;

// This matches the exact value returned from `information_handler`
assert_eq!(resp.status(), http::StatusCode::CONTINUE);

// This matches all values considered _informational_ `1xx`
assert!(resp.status().is_informational());

Ok(())
}

#[actix_web::test]
/// Test success status codes `2xx`
async fn test_success() -> Result<(), Error> {
let app = App::new().service(success_handler);
let app = test::init_service(app).await;

let req = test::TestRequest::get().uri("/").to_request();
let resp = app.call(req).await?;

// This matches the exact value returned from `success_handler`
assert_eq!(resp.status(), http::StatusCode::OK);

// This matches all values considered _successfull_ `2xx`
assert!(resp.status().is_success());

Ok(())
}

#[actix_web::test]
/// Test redirect status codes `3xx`
async fn test_redirect() -> Result<(), Error> {
let app = App::new().service(redirect_handler);
let app = test::init_service(app).await;

let req = test::TestRequest::get().uri("/").to_request();
let resp = app.call(req).await?;

// This matches the exact value returned from `redirect_handler`
assert_eq!(resp.status(), http::StatusCode::TEMPORARY_REDIRECT);

// This matches all values considered _redirects_ `3xx`
assert!(resp.status().is_redirection());

Ok(())
}

#[actix_web::test]
/// Test client error status codes `4xx`
async fn test_client_error() -> Result<(), Error> {
let app = App::new().service(client_error_handler);
let app = test::init_service(app).await;

let req = test::TestRequest::get().uri("/").to_request();
let resp = app.call(req).await?;

// This matches the exact value returned from `client_error_handler`
assert_eq!(resp.status(), http::StatusCode::IM_A_TEAPOT);

// This matches all values considered _client error_ `4xx`
assert!(resp.status().is_client_error());

Ok(())
}

#[actix_web::test]
/// Test server error status codes `5xx`
async fn test_server_error() -> Result<(), Error> {
let app = App::new().service(server_error_handler);
let app = test::init_service(app).await;

let req = test::TestRequest::get().uri("/").to_request();
let resp = app.call(req).await?;

// This matches the exact value returned from `server_error_handler`
assert_eq!(resp.status(), http::StatusCode::NOT_IMPLEMENTED);

// This matches all values considered _server error_ `5xx`
assert!(resp.status().is_server_error());

Ok(())
}
}