pub struct Client { /* private fields */ }Expand description
An HTTP client for request tests, with a cookie jar, like a browser tab (Rails’ integration session).
Every request carries Sec-Fetch-Site: same-origin, as a browser’s
same-site form does, so Ocre’s cross-site request check passes; use
Client::cross_site to test the check. Cookies from Set-Cookie
are sent back on the next requests, so a sign-in, the session and flash
messages carry over. Redirects are not followed automatically: assert on
them, then call Client::follow_redirect. Two clients are two
independent visitors (Rails’ open_session).
§Examples
use ocre::testing::Client;
let mut client = Client::new();
client.get("/up").assert_status(200).assert_contains("OK");Implementations§
Source§impl Client
impl Client
Sourcepub fn with_base_url(base: &str) -> Self
pub fn with_base_url(base: &str) -> Self
A client for the app at base (http://localhost:8787), e.g. a running ocre dev.
§Examples
let mut client = ocre::testing::Client::with_base_url("http://localhost:8787");
client.get("/up").assert_status(200);Sourcepub fn header(self, name: &str, value: &str) -> Self
pub fn header(self, name: &str, value: &str) -> Self
Sends name: value with every request (Rails’ headers:); replaces
an earlier value of the same header.
§Examples
let mut client = ocre::testing::Client::new().header("Accept-Language", "fr");
client.get("/").assert_contains("Bienvenue");Sourcepub fn cross_site(self) -> Self
pub fn cross_site(self) -> Self
Requests as a form posted from another site would (Sec-Fetch-Site: cross-site):
Ocre’s CSRF protection answers 403 to unsafe methods.
§Examples
let mut client = ocre::testing::Client::new().cross_site();
client.post("/posts", &[("title", "x")]).assert_status(403);Sourcepub fn htmx(self) -> Self
pub fn htmx(self) -> Self
Requests as htmx does (HX-Request: true), Rails’ xhr: true.
§Examples
let mut client = ocre::testing::Client::new().htmx();
client.get("/posts").assert_not_contains("<html");Sourcepub fn post(&mut self, path: &str, form: &impl Serialize) -> Response
pub fn post(&mut self, path: &str, form: &impl Serialize) -> Response
POST path with an application/x-www-form-urlencoded body, as an HTML form sends it.
form is anything serde_urlencoded takes: a slice of (name, value)
pairs, a factory’s form(), a struct deriving Serialize, or &() for an empty body.
§Panics
When form is not a flat list of fields.
§Examples
let mut client = ocre::testing::Client::new();
client.post("/posts", &[("title", "Hello"), ("body", "World")]).assert_status(303);
client.post("/posts/1/delete", &()).assert_redirect_to("/posts");Sourcepub fn post_json(&mut self, path: &str, value: &impl Serialize) -> Response
pub fn post_json(&mut self, path: &str, value: &impl Serialize) -> Response
POST path with value as a JSON body.
§Examples
let mut client = ocre::testing::Client::new();
let created = client.post_json("/api/posts", &ocre::serde_json::json!({"title": "Hello"}));
assert_eq!(created.assert_status(201).json::<ocre::serde_json::Value>()["title"], "Hello");Sourcepub fn patch_json(&mut self, path: &str, value: &impl Serialize) -> Response
pub fn patch_json(&mut self, path: &str, value: &impl Serialize) -> Response
PATCH path with value as a JSON body.
§Examples
let mut client = ocre::testing::Client::new();
client.patch_json("/api/posts/1", &ocre::serde_json::json!({"title": "New"})).assert_status(200);Sourcepub fn put_json(&mut self, path: &str, value: &impl Serialize) -> Response
pub fn put_json(&mut self, path: &str, value: &impl Serialize) -> Response
PUT path with value as a JSON body.
§Examples
let mut client = ocre::testing::Client::new();
client.put_json("/api/settings", &ocre::serde_json::json!({"theme": "dark"})).assert_success();Sourcepub fn request(
&mut self,
method: &str,
path: &str,
body: Option<(&str, Vec<u8>)>,
) -> Response
pub fn request( &mut self, method: &str, path: &str, body: Option<(&str, Vec<u8>)>, ) -> Response
Sends method path with an optional (content type, body): any
method, any body (multipart uploads, raw bytes).
§Panics
When the server cannot be reached.
§Examples
let mut client = ocre::testing::Client::new();
client.request("HEAD", "/up", None).assert_status(200);
client.request("POST", "/api/raw", Some(("text/plain", b"bytes".to_vec()))).assert_success();Sourcepub fn follow_redirect(&mut self, response: &Response) -> Response
pub fn follow_redirect(&mut self, response: &Response) -> Response
Follows the redirect response answered: GET of its Location (Rails’ follow_redirect!).
§Panics
When response has no Location header.
§Examples
let mut client = ocre::testing::Client::new();
let created = client.post("/posts", &[("title", "Hello"), ("body", "World")]);
client.follow_redirect(&created).assert_contains("Post was successfully created.");The cookie name as the server set it (percent-encoded), if the jar has it.
§Examples
let mut client = ocre::testing::Client::new();
client.get("/");
assert!(client.cookie("_ocre_session").is_none());Sets a cookie sent with the next requests, as if the server had set it.
§Examples
let mut client = ocre::testing::Client::new();
client.set_cookie("locale", "fr");Sourcepub fn session(&self) -> Map<String, Value>
pub fn session(&self) -> Map<String, Value>
The session data (Rails’ session in tests), decrypted with the
app’s SECRET_KEY_BASE (the environment variable, else .dev.vars):
empty without a session cookie. Flash messages set for the next
request are under _flash: Client::flash reads them.
§Panics
When there is a session cookie but no SECRET_KEY_BASE, or the
cookie does not decrypt with it.
§Examples
let mut client = ocre::testing::Client::new();
client.post("/session", &[("email", "ada@example.com"), ("password", "secret")]);
assert!(client.session().contains_key("user_id"));Sourcepub fn flash(&self, kind: &str) -> Option<String>
pub fn flash(&self, kind: &str) -> Option<String>
The flash message of kind (notice, alert…) set by the last
request for the next page (Rails’ flash[:notice] after an action).
§Examples
let mut client = ocre::testing::Client::new();
client.post("/posts", &[("title", "Hello"), ("body", "World")]);
assert_eq!(client.flash("notice").as_deref(), Some("Post was successfully created."));Sourcepub fn deliveries(&mut self) -> Vec<Email>
pub fn deliveries(&mut self) -> Vec<Email>
Emails the app sent with MAIL_ADAPTER = "log" (Rails’
ActionMailer::Base.deliveries), oldest first: the last 20, kept by
the Worker instance. Reads GET /ocre/dev/mailers/sent.json, which
exists when routes() merges ocre::mail::dev_routes (ocre g mailer adds it).
§Panics
When the endpoint does not answer a JSON list.
§Examples
let mut client = ocre::testing::Client::new();
let before = client.deliveries().len();
client.post("/passwords", &[("email", "ada@example.com")]);
let sent = client.deliveries();
assert_eq!(sent.len(), before + 1);
assert_eq!(sent.last().unwrap().to, ["ada@example.com"]);Sourcepub fn broadcasts(&mut self) -> Vec<Broadcast>
pub fn broadcasts(&mut self) -> Vec<Broadcast>
Messages the app broadcast to realtime channels (Rails’
assert_broadcasts), oldest first: the last 50, kept by the Worker
instance. Reads GET /ocre/dev/realtime/sent.json, which exists when
routes() merges ocre::realtime::dev_routes() (ocre g scaffold ... --realtime adds it).
§Panics
When the endpoint does not answer a JSON list.
§Examples
let mut client = ocre::testing::Client::new();
client.post("/posts", &[("title", "Live"), ("body", "b")]);
let last = client.broadcasts().pop().unwrap();
assert_eq!(last.channel, "posts");
assert!(last.message.contains("Live"));Sourcepub fn jobs(&mut self) -> Jobs
pub fn jobs(&mut self) -> Jobs
Jobs the app enqueued and ran (Rails’ assert_enqueued_with,
assert_performed_jobs): the last 50 of each, oldest first, kept by
the Worker instance. Reads GET /ocre/dev/jobs.json, which the first
ocre g job merges into routes() (ocre::jobs::dev_routes()).
Local queues deliver within a second or so: wait for a run with
eventually.
§Panics
When the endpoint does not answer the expected JSON.
§Examples
use ocre::testing::{Client, eventually};
let mut client = Client::new();
client.post("/signups", &[("email", "ada@example.com")]);
let jobs = client.jobs();
assert_eq!(jobs.enqueued.last().unwrap().name(), Some("send_welcome"));
eventually(|| client.jobs().performed.iter().any(|run| run.job == "send_welcome" && run.outcome == "done").then_some(()));Sourcepub fn receive_email(
&mut self,
from: &str,
to: &str,
subject: &str,
body: &str,
) -> Response
pub fn receive_email( &mut self, from: &str, to: &str, subject: &str, body: &str, ) -> Response
Delivers an email to the app’s mailbox (ocre g mailbox), as
Cloudflare Email Routing would (Rails’ receive_inbound_email_from_mail):
a plain-text message posted to the local server’s email endpoint
(POST /cdn-cgi/local/email?from=&to=), which runs the Worker’s
email event. The response says whether the mailbox accepted it.
§Examples
let mut client = ocre::testing::Client::new();
client.receive_email("ada@example.com", "support@example.com", "Help", "My order is late.").assert_success();