Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .buildkite/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
steps:
- label: ":wordpress: :rust: WordPress.org API"
command: |
echo "--- :rust: Testing"
make test-rust-integration-wordpress-org-api
env:
TEST_ALL_PLUGINS: true

notify:
- slack:
channels:
- "#wordpress-rs"
message: "Nightly build."
2 changes: 2 additions & 0 deletions Cargo.lock

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

5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ docker_container_repo_dir=/app
rust_docker_container := public.ecr.aws/docker/library/rust:1.80

docker_opts_shared := --rm -v "$(PWD)":$(docker_container_repo_dir) -w $(docker_container_repo_dir)
rust_docker_run := docker run -v $(PWD):/$(docker_container_repo_dir) -w $(docker_container_repo_dir) -it -e CARGO_HOME=/app/.cargo $(rust_docker_container)
rust_docker_run := docker run -v $(PWD):/$(docker_container_repo_dir) -w $(docker_container_repo_dir) -it -e TEST_ALL_PLUGINS -e CARGO_HOME=/app/.cargo $(rust_docker_container)
docker_build_and_run := docker build -t foo . && docker run $(docker_opts_shared) -it foo

swift_package_platform_version = $(shell swift package dump-package | jq -r '.platforms[] | select(.platformName=="$1") | .version')
Expand Down Expand Up @@ -204,8 +204,7 @@ test-rust-integration:
docker exec -i wordpress /bin/bash < ./scripts/run-rust-integration-tests.sh

test-rust-integration-wordpress-org-api:
@test -d target/wordpress-org-plugin-directory || ./scripts/plugin-directory.sh download_from_s3
$(rust_docker_run) cargo test --package wordpress_org_api
$(rust_docker_run) cargo test --package wordpress_org_api -- --nocapture

test-kotlin-integration:
@# Help: Run Kotlin integration tests in test server.
Expand Down
71 changes: 0 additions & 71 deletions scripts/plugin-directory.sh

This file was deleted.

2 changes: 2 additions & 0 deletions wordpress_org_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ serde = { workspace = true, features = [ "derive" ] }
serde_json = { workspace = true }

[dev-dependencies]
reqwest = { workspace = true, features = [ "json" ] }
rstest = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = [ "full" ] }
218 changes: 218 additions & 0 deletions wordpress_org_api/src/plugin_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct PluginInformation {
#[serde(deserialize_with = "deserialize_default_values")]
pub author_profile: String,
#[serde(deserialize_with = "deserialize_default_values")]
#[serde(default)]
pub contributors: HashMap<String, ContributorDetails>,
#[serde(deserialize_with = "deserialize_default_values")]
pub requires: String,
Expand All @@ -26,30 +27,40 @@ pub struct PluginInformation {
pub rating: u32,
pub ratings: Ratings,
pub num_ratings: u32,
#[serde(default)]
pub support_url: String,
pub support_threads: u32,
pub support_threads_resolved: u32,
pub active_installs: u64,
pub last_updated: String,
pub added: String,
pub homepage: String,
#[serde(default)]
pub sections: HashMap<String, String>,
pub download_link: String,
#[serde(deserialize_with = "deserialize_default_values")]
#[serde(default)]
pub upgrade_notice: HashMap<String, String>,
#[serde(default)]
pub screenshots: Screenshots,
#[serde(deserialize_with = "deserialize_default_values")]
pub tags: HashMap<String, String>,
#[serde(deserialize_with = "deserialize_default_values")]
#[serde(default)]
pub versions: HashMap<String, String>,
#[serde(deserialize_with = "deserialize_default_values")]
#[serde(default)]
pub business_model: String,
#[serde(default)]
pub repository_url: String,
#[serde(default)]
pub commercial_support_url: String,
pub donate_link: String,
#[serde(deserialize_with = "deserialize_default_values")]
#[serde(default)]
pub banners: Banners,
pub icons: Option<Icons>,
#[serde(default)]
pub preview_link: String,
}

Expand Down Expand Up @@ -82,6 +93,12 @@ pub enum Screenshots {
List(Vec<Screenshot>),
}

impl Default for Screenshots {
fn default() -> Self {
Screenshots::List(vec![])
}
}

#[derive(Deserialize, Debug)]
pub struct Screenshot {
pub src: String,
Expand All @@ -105,3 +122,204 @@ pub struct Icons {
pub svg: Option<String>,
pub default: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct QueryPluginResponse {
pub info: QueryPluginResponseInfo,
pub plugins: Vec<PluginInformation>,
}

#[derive(Deserialize, Debug)]
pub struct QueryPluginResponseInfo {
pub page: u64,
pub pages: u64,
pub results: u64,
}

#[cfg(test)]
mod tests {
use super::*;
use rstest::*;

struct Plugin {
parsed: PluginInformation,
raw_json: serde_json::Value,
}

impl Plugin {
fn parse(json_string: &str) -> Self {
let parsed = serde_json::from_str::<PluginInformation>(json_string);
let raw_json = serde_json::from_str(json_string);
assert!(parsed.is_ok(), "Failed to parse JSON: {:?}", parsed.err());
assert!(
raw_json.is_ok(),
"Failed to parse JSON: {:?}",
raw_json.err()
);

Self {
parsed: parsed.unwrap(),
raw_json: raw_json.unwrap(),
}
}
}

#[fixture]
fn plugin_with_variant_types() -> Plugin {
let json_string = include_str!("../tests/plugin-with-different-types-of-values.json");
Plugin::parse(json_string)
}

#[fixture]
fn plugin_with_expected_types() -> Plugin {
let json_string = include_str!("../tests/plugin-with-expected-types.json");
Plugin::parse(json_string)
}

#[rstest]
fn test_plugin_with_different_types_of_author_profile(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(plugin_with_variant_types.raw_json["author_profile"], false);
assert_eq!(plugin_with_variant_types.parsed.author_profile, "");

assert!(plugin_with_expected_types.raw_json["author_profile"].is_string());
assert!(!plugin_with_expected_types.parsed.author_profile.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_contributors(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(
plugin_with_variant_types.raw_json["contributors"].as_array(),
Some(vec![]).as_ref()
);
assert_eq!(
plugin_with_variant_types.parsed.contributors,
HashMap::new()
);

assert!(plugin_with_expected_types.raw_json["contributors"].is_object());
assert!(!plugin_with_expected_types.parsed.contributors.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_requires(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(plugin_with_variant_types.raw_json["requires"], false);
assert_eq!(plugin_with_variant_types.parsed.requires, "");

assert!(plugin_with_expected_types.raw_json["requires"].is_string());
assert!(!plugin_with_expected_types.parsed.requires.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_tested(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(plugin_with_variant_types.raw_json["tested"], false);
assert_eq!(plugin_with_variant_types.parsed.tested, "");

assert!(plugin_with_expected_types.raw_json["tested"].is_string());
assert!(!plugin_with_expected_types.parsed.tested.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_requires_php(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(plugin_with_variant_types.raw_json["requires_php"], false);
assert_eq!(plugin_with_variant_types.parsed.requires_php, "");

assert!(plugin_with_expected_types.raw_json["requires_php"].is_string());
assert!(!plugin_with_expected_types.parsed.requires_php.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_upgrade_notice(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(
plugin_with_variant_types.raw_json["upgrade_notice"].as_array(),
Some(vec![]).as_ref()
);
assert_eq!(
plugin_with_variant_types.parsed.upgrade_notice,
HashMap::new()
);

assert!(plugin_with_expected_types.raw_json["upgrade_notice"].is_object());
assert!(!plugin_with_expected_types.parsed.upgrade_notice.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_tags(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(
plugin_with_variant_types.raw_json["tags"].as_array(),
Some(vec![]).as_ref()
);
assert_eq!(plugin_with_variant_types.parsed.tags, HashMap::new());

assert!(plugin_with_expected_types.raw_json["tags"].is_object());
assert!(!plugin_with_expected_types.parsed.tags.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_versions(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(
plugin_with_variant_types.raw_json["versions"].as_array(),
Some(vec![]).as_ref()
);
assert_eq!(plugin_with_variant_types.parsed.versions, HashMap::new());

assert!(plugin_with_expected_types.raw_json["versions"].is_object());
assert!(!plugin_with_expected_types.parsed.versions.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_business_model(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(plugin_with_variant_types.raw_json["business_model"], false);
assert_eq!(plugin_with_variant_types.parsed.business_model, "");

assert!(plugin_with_expected_types.raw_json["business_model"].is_string());
assert!(!plugin_with_expected_types.parsed.business_model.is_empty());
}

#[rstest]
fn test_plugin_with_different_types_of_banners(
plugin_with_variant_types: Plugin,
plugin_with_expected_types: Plugin,
) {
assert_eq!(
plugin_with_variant_types.raw_json["banners"].as_array(),
Some(vec![]).as_ref()
);
assert_eq!(plugin_with_variant_types.parsed.banners, Banners::default());

assert!(plugin_with_expected_types.raw_json["banners"].is_object());
}

#[test]
fn test_plugin_query_result() {
let json_string = include_str!("../tests/plugin-query-result.json");
let parsed = serde_json::from_str::<QueryPluginResponse>(json_string);
assert!(parsed.is_ok(), "Failed to parse JSON: {:?}", parsed.err());
}
}
Loading
Loading