Skip to content

Commit 1a05e81

Browse files
Fastly/WASM Support
- adds plumbing to run fastly depended specs via viceroy - swaps from using feature flags to using architecture cfg flags - these play nicer with nextest - also allows us to exclude httpmock from the dev deps if we are targeting wasm as httpmock does not support wasm - updates existing unit tests to be cfg flagged - excludes them from compilation if the target is wasm - im sorry but i could not find another way to accomplish this
1 parent 0835e7b commit 1a05e81

File tree

16 files changed

+155
-24
lines changed

16 files changed

+155
-24
lines changed

.cargo/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[target.wasm32-wasip1]
2+
runner = "viceroy run -C fastly.unit-test.toml -- "

.cargo/nextest.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[profile.default]
2+
platform = { target_arch = "wasm32" }

Cargo.toml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,20 @@ flume = "0.10.14"
2626

2727
flagsmith-flag-engine = "0.4.0"
2828

29+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
30+
reqwest = { version = "0.11", features = ["json", "blocking"] }
31+
32+
[target.'cfg(target_arch = "wasm32")'.dependencies]
2933
reqwest = { version = "0.11", features = ["json"] }
30-
fastly = { version = "^0.11.5", optional = true }
34+
fastly = { version = "^0.11.5" }
3135

3236
[dev-dependencies]
33-
httpmock = "0.6"
3437
rstest = "0.12.0"
3538

39+
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
40+
httpmock = "0.6"
41+
3642
[features]
37-
default = ["blocking"]
38-
non_blocking = ["fastly"]
39-
blocking = ["reqwest/blocking"]
43+
# default = ["blocking"]
44+
# non_blocking = ["fastly"]
45+
# blocking = ["reqwest/blocking"]

fastly.unit-test.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This file describes a Fastly Compute@Edge package. To learn more visit:
2+
# https://developer.fastly.com/reference/fastly-toml/
3+
4+
authors = [
5+
"Gagan Trivedi <[email protected]>",
6+
"Kim Gustyr <[email protected]>",
7+
]
8+
description = "Flagsmith Rust Client."
9+
language = "rust"
10+
manifest_version = 2
11+
name = "flagsmith-rust-client"
12+
service_id = ""
13+
14+
[scripts]
15+
build = "cargo build --release --target wasm32-wasip1 --color always"

scripts/fastly-unit-test.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
function run-specs() {
4+
cargo nextest run --target wasm32-wasip1 flagsmith::client
5+
}
6+
7+
if [ "$0" = "${BASH_SOURCE[0]}" ]; then
8+
set -eo pipefail
9+
run-specs "${@:-}"
10+
exit $?
11+
fi

scripts/test.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
3+
function run-default-tests() {
4+
echo "Running default tests"
5+
cargo test
6+
}
7+
8+
function run-fastly-tests() {
9+
echo "Running fastly/wasm tests"
10+
./scripts/fastly-unit-test.sh
11+
}
12+
13+
if [ "$0" = "${BASH_SOURCE[0]}" ]; then
14+
set -eo pipefail
15+
16+
run-default-tests && run-fastly-tests
17+
18+
exit $?
19+
fi

src/flagsmith/analytics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn flush(client: &SafeClient, analytics_data: &HashMap<String, u32>, analytics_e
8787
}
8888
}
8989

90-
#[cfg(test)]
90+
#[cfg(all(test, not(target_arch = "wasm32")))]
9191
mod tests {
9292
use super::*;
9393
use httpmock::prelude::*;

src/flagsmith/client/blocking_client.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ impl ResponseStatusCode for reqwest::StatusCode {
3232
fn is_success(&self) -> bool {
3333
self.is_success()
3434
}
35+
36+
fn as_u16(&self) -> u16 {
37+
self.as_u16()
38+
}
3539
}
3640

3741
impl ClientResponse for reqwest::blocking::Response {

src/flagsmith/client/client.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use std::time::Duration;
33
use reqwest::header::HeaderMap;
44
use serde::de::DeserializeOwned;
55

6-
#[cfg(not(feature = "non_blocking"))]
6+
#[cfg(not(target_arch = "wasm32"))]
77
use crate::flagsmith::client::blocking_client::BlockingClient;
8-
#[cfg(feature = "non_blocking")]
8+
#[cfg(target_arch = "wasm32")]
99
use crate::flagsmith::client::fastly_client::FastlyClient;
1010

1111
pub enum Method {
@@ -22,6 +22,10 @@ pub enum Method {
2222

2323
pub trait ResponseStatusCode {
2424
fn is_success(&self) -> bool;
25+
26+
/// Exists for Unit Testing purposes
27+
#[allow(dead_code)]
28+
fn as_u16(&self) -> u16;
2529
}
2630

2731
pub trait ClientRequestBuilder {
@@ -48,22 +52,22 @@ pub trait ClientLike {
4852

4953
#[derive(Clone)]
5054
pub struct SafeClient {
51-
#[cfg(not(feature = "non_blocking"))]
55+
#[cfg(not(target_arch = "wasm32"))]
5256
pub inner: BlockingClient,
5357

54-
#[cfg(feature = "non_blocking")]
58+
#[cfg(target_arch = "wasm32")]
5559
pub inner: FastlyClient,
5660
}
5761

5862
impl SafeClient {
59-
#[cfg(not(feature = "non_blocking"))]
63+
#[cfg(not(target_arch = "wasm32"))]
6064
pub fn new(headers: HeaderMap, timeout: Duration) -> Self {
6165
Self {
6266
inner: BlockingClient::new(headers, timeout),
6367
}
6468
}
6569

66-
#[cfg(feature = "non_blocking")]
70+
#[cfg(target_arch = "wasm32")]
6771
pub fn new(headers: HeaderMap, timeout: Duration) -> Self {
6872
Self {
6973
inner: FastlyClient::new(headers, timeout),

src/flagsmith/client/fastly_client.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ impl super::client::ResponseStatusCode for http::StatusCode {
3232

3333
raw >= 200 && raw <= 299
3434
}
35+
36+
fn as_u16(&self) -> u16 {
37+
self.as_u16()
38+
}
3539
}
3640

3741
impl super::client::ClientResponse for http::Response {
@@ -57,9 +61,9 @@ impl super::client::ClientResponse for http::Response {
5761
}
5862

5963
/// Wrapper to help with abstraction of the client interface.
60-
struct FastlyRequestBuilder {
64+
pub struct FastlyRequestBuilder {
6165
backend: String,
62-
request: Result<http::Request, ()>,
66+
pub request: Result<http::Request, ()>,
6367
}
6468

6569
impl ClientRequestBuilder for FastlyRequestBuilder {
@@ -113,3 +117,64 @@ impl ClientLike for FastlyClient {
113117
}
114118
}
115119
}
120+
121+
#[cfg(all(test, target_arch = "wasm32"))]
122+
mod tests {
123+
use fastly::Response;
124+
use serde::{Deserialize, Serialize};
125+
use serde_json::json;
126+
127+
use super::*;
128+
129+
#[derive(Serialize, Deserialize, PartialEq, Debug)]
130+
struct TestData {
131+
key: String,
132+
}
133+
134+
#[test]
135+
fn test_status_code_is_success() {
136+
let status = http::StatusCode::from_u16(199).unwrap();
137+
assert!(!status.is_success());
138+
139+
let status = http::StatusCode::from_u16(300).unwrap();
140+
assert!(!status.is_success());
141+
142+
for i in 200..=299 {
143+
let status = http::StatusCode::from_u16(i).unwrap();
144+
145+
assert!(status.is_success(), "{} should be success", i);
146+
}
147+
}
148+
149+
#[test]
150+
fn test_response_status_returns_status() {
151+
let resp = Response::from_status(418);
152+
153+
assert_eq!(resp.status().as_u16(), 418);
154+
}
155+
156+
#[test]
157+
fn test_response_text_returns_body() {
158+
let resp = Response::from_body("This is a test body.");
159+
160+
let text = resp.text();
161+
162+
assert!(text.is_ok());
163+
assert_eq!(text.unwrap(), "This is a test body.");
164+
}
165+
166+
#[test]
167+
fn test_response_json_returns_body() {
168+
let resp = Response::from_body(json!({ "key": "value" }).to_string());
169+
170+
let result = resp.json::<TestData>();
171+
172+
assert!(result.is_ok());
173+
assert_eq!(
174+
result.unwrap(),
175+
TestData {
176+
key: "value".to_string()
177+
}
178+
);
179+
}
180+
}

0 commit comments

Comments
 (0)