|
| 1 | +mod common; |
| 2 | + |
| 3 | +use common::http_server::TestHttpServer; |
| 4 | +use common::{cli_cmd, query_manager, seed_workspace}; |
| 5 | +use predicates::str::contains; |
| 6 | +use std::fs; |
| 7 | +use tempfile::TempDir; |
| 8 | +use yaak_models::models::{HttpRequest, HttpRequestHeader}; |
| 9 | +use yaak_models::util::UpdateSource; |
| 10 | + |
| 11 | +/// A template function that runs `ctx.filter` and returns the host's reply as JSON. |
| 12 | +const PROBE_PLUGIN: &str = r#"exports.plugin = { |
| 13 | + templateFunctions: [{ |
| 14 | + name: "filter_probe", |
| 15 | + args: [ |
| 16 | + { type: "text", name: "language" }, |
| 17 | + { type: "text", name: "text" }, |
| 18 | + { type: "text", name: "query" }, |
| 19 | + ], |
| 20 | + async onRender(ctx, args) { |
| 21 | + const { language, text, query } = args.values; |
| 22 | + const result = language === "xpath" |
| 23 | + ? await ctx.filter.xPath(text, query) |
| 24 | + : await ctx.filter.jsonPath(text, query); |
| 25 | + return JSON.stringify(result); |
| 26 | + }, |
| 27 | + }], |
| 28 | +};"#; |
| 29 | + |
| 30 | +/// The plugin runtime, the CLI's plugin host, and yaak-filter, end to end: the |
| 31 | +/// rendered header values are what the host replied to the plugin. |
| 32 | +#[test] |
| 33 | +fn plugins_filter_text_through_the_host() { |
| 34 | + let temp_dir = TempDir::new().expect("Failed to create temp dir"); |
| 35 | + let data_dir = temp_dir.path(); |
| 36 | + |
| 37 | + // Bundled plugins are extracted next to this on launch; extras are kept. |
| 38 | + let probe_dir = data_dir.join("vendored-plugins").join("filter-probe"); |
| 39 | + fs::create_dir_all(probe_dir.join("build")).expect("Failed to create probe plugin dir"); |
| 40 | + fs::write(probe_dir.join("package.json"), r#"{"name":"@yaak/filter-probe","version":"0.0.0"}"#) |
| 41 | + .expect("Failed to write probe package.json"); |
| 42 | + fs::write(probe_dir.join("build").join("index.js"), PROBE_PLUGIN) |
| 43 | + .expect("Failed to write probe plugin"); |
| 44 | + |
| 45 | + seed_workspace(data_dir, "wk_test"); |
| 46 | + let server = TestHttpServer::spawn_ok("ok"); |
| 47 | + let header = |name: &str, value: &str| HttpRequestHeader { |
| 48 | + enabled: true, |
| 49 | + name: name.to_string(), |
| 50 | + value: value.to_string(), |
| 51 | + id: None, |
| 52 | + }; |
| 53 | + let request = HttpRequest { |
| 54 | + id: "rq_filter".to_string(), |
| 55 | + workspace_id: "wk_test".to_string(), |
| 56 | + method: "GET".to_string(), |
| 57 | + url: server.url.clone(), |
| 58 | + headers: vec![ |
| 59 | + header( |
| 60 | + "x-json", |
| 61 | + r#"${[ filter_probe(language='jsonpath', text='{"a":[1,2]}', query='$.a[1]') ]}"#, |
| 62 | + ), |
| 63 | + header( |
| 64 | + "x-xml", |
| 65 | + "${[ filter_probe(language='xpath', text='<a><b>x</b></a>', query='//b') ]}", |
| 66 | + ), |
| 67 | + header( |
| 68 | + "x-bad", |
| 69 | + "${[ filter_probe(language='jsonpath', text='{}', query='$[?(@ ==)]') ]}", |
| 70 | + ), |
| 71 | + ], |
| 72 | + ..Default::default() |
| 73 | + }; |
| 74 | + query_manager(data_dir) |
| 75 | + .with_tx(|tx| tx.upsert_http_request(&request, &UpdateSource::Sync)) |
| 76 | + .expect("Failed to seed request"); |
| 77 | + |
| 78 | + cli_cmd(data_dir) |
| 79 | + .args(["--verbose", "request", "send", "rq_filter"]) |
| 80 | + .assert() |
| 81 | + .success() |
| 82 | + .stdout(contains(r#"> x-json: {"content":"[\n 2\n]"}"#)) |
| 83 | + .stdout(contains(r#"> x-xml: {"content":"<b>x</b>"}"#)) |
| 84 | + .stdout(contains(r#"> x-bad: {"content":"","error":"Invalid filter: "#)); |
| 85 | +} |
0 commit comments