Skip to content

Commit

Permalink
Had to Fix Tests and Command Line Generator too
Browse files Browse the repository at this point in the history
Gonna test it manually on cloud later
  • Loading branch information
zelosleone committed Jan 6, 2025
1 parent ce49dff commit e9dbd93
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 4 deletions.
64 changes: 60 additions & 4 deletions golem-cli/src/oss/clients/api_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ use golem_client::model::{HttpApiDefinitionRequest, HttpApiDefinitionResponseDat
use golem_worker_service_base::gateway_api_definition::http::{
openapi_export::{OpenApiExporter, OpenApiFormat},
swagger_ui::{create_api_route, SwaggerUiConfig, SwaggerUiAuthConfig},
rib_converter::{RibConverter, fix_additional_properties},
};
use golem_wasm_ast::analysis::{AnalysedType, TypeRecord, NameTypePair, TypeStr, TypeList, TypeBool};
use poem::listener::TcpListener;
use poem_openapi::{
OpenApi,
Tags,
payload::Json,
registry::Registry,
};
use serde_json::Value;
use tokio::fs::{read_to_string, write};
Expand Down Expand Up @@ -131,21 +134,74 @@ impl<C: golem_client::api::ApiDefinitionClient + Sync + Send> ApiDefinitionClien
api_def: &HttpApiDefinitionResponseData,
format: &ApiDefinitionFileFormat,
) -> Result<String, GolemError> {
// First convert to JSON Value
let api_value = serde_json::to_value(api_def)
.map_err(|e| GolemError(format!("Failed to convert API definition to JSON: {}", e)))?;
// Create RibConverter in OpenAPI mode
let mut converter = RibConverter::new_openapi();

// Create a new Registry for OpenAPI schema generation
let mut registry = Registry::new();

// Convert API definition to OpenAPI schema
let schema = converter
.convert_type(&api_def.into(), &registry)
.map_err(|e| GolemError(format!("Failed to convert API definition to OpenAPI: {}", e)))?;

// Convert schema to JSON Value
let mut api_value = serde_json::to_value(schema)
.map_err(|e| GolemError(format!("Failed to convert schema to JSON: {}", e)))?;

// Clean up the schema
fix_additional_properties(&mut api_value);

// Create OpenAPI exporter
let exporter = OpenApiExporter;
let openapi_format = OpenApiFormat {
json: matches!(format, ApiDefinitionFileFormat::Json),
};

// Export using the exporter - pass ApiSpec directly, not as a reference
// Export using the exporter - pass ApiSpec directly
Ok(exporter.export_openapi(ApiSpec(api_value), &openapi_format))
}
}

impl From<&HttpApiDefinitionResponseData> for AnalysedType {
fn from(data: &HttpApiDefinitionResponseData) -> Self {
// Convert HttpApiDefinitionResponseData to a record type
AnalysedType::Record(TypeRecord {
fields: vec![
NameTypePair {
name: "id".to_string(),
typ: AnalysedType::Str(TypeStr),
},
NameTypePair {
name: "version".to_string(),
typ: AnalysedType::Str(TypeStr),
},
NameTypePair {
name: "routes".to_string(),
typ: AnalysedType::List(TypeList {
inner: Box::new(AnalysedType::Record(TypeRecord {
fields: vec![
NameTypePair {
name: "method".to_string(),
typ: AnalysedType::Str(TypeStr),
},
NameTypePair {
name: "path".to_string(),
typ: AnalysedType::Str(TypeStr),
},
],
})),
}),
},
NameTypePair {
name: "draft".to_string(),
typ: AnalysedType::Bool(TypeBool),
},
],
})
}
}

#[async_trait]
impl<C: golem_client::api::ApiDefinitionClient + Sync + Send> ApiDefinitionClient
for ApiDefinitionClientLive<C>
Expand Down
97 changes: 97 additions & 0 deletions golem-cli/tests/api_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,25 @@ fn make(r: &mut DynamicTestRegistration, suffix: &'static str, name: &'static st
api_definition_delete((deps, name.to_string(), cli.with_args(short)))
}
);
add_test!(
r,
format!("api_definition_export{suffix}"),
TestType::IntegrationTest,
move |deps: &EnvBasedTestDependencies, cli: &CliLive, _tracing: &Tracing| {
api_definition_export(
(deps, name.to_string(), cli.with_args(short)),
&ApiDefinitionFileFormat::Json,
)
}
);
add_test!(
r,
format!("api_definition_ui{suffix}"),
TestType::IntegrationTest,
move |deps: &EnvBasedTestDependencies, cli: &CliLive, _tracing: &Tracing| {
api_definition_ui((deps, name.to_string(), cli.with_args(short)))
}
);
}

pub fn make_shopping_cart_component(
Expand Down Expand Up @@ -1014,3 +1033,81 @@ fn api_definition_delete(

Ok(())
}

fn api_definition_export(
(deps, name, cli): (
&(impl TestDependencies + Send + Sync + 'static),
String,
CliLive,
),
api_definition_format: &ApiDefinitionFileFormat,
) -> anyhow::Result<()> {
let component_name = format!("api_definition_export{name}");
let component = make_shopping_cart_component(deps, &component_name, &cli)?;
let component_id = component.component_urn.id.0.to_string();
let path = "/{user-id}/get-cart-contents";
let def = native_api_definition_request(&component_name, &component_id, None, path);
let path = make_json_file(&def.id, &def)?;

// First create an API definition
let _: HttpApiDefinitionResponseData = cli.run(&["api-definition", "add", path.to_str().unwrap()])?;

let cfg = &cli.config;

// Then export it
let res: String = cli.run(&[
"api-definition",
"export",
&cfg.arg('i', "id"),
&component_name,
&cfg.arg('V', "version"),
"0.1.0",
&cfg.arg('f', "format"),
api_definition_format.to_string().as_str(),
])?;

// Verify the export contains expected content
assert!(res.contains(&component_name));
assert!(res.contains(&component_id));
assert!(res.contains(path));

Ok(())
}

fn api_definition_ui(
(deps, name, cli): (
&(impl TestDependencies + Send + Sync + 'static),
String,
CliLive,
),
) -> anyhow::Result<()> {
let component_name = format!("api_definition_ui{name}");
let component = make_shopping_cart_component(deps, &component_name, &cli)?;
let component_id = component.component_urn.id.0.to_string();
let path = "/{user-id}/get-cart-contents";
let def = native_api_definition_request(&component_name, &component_id, None, path);
let path = make_json_file(&def.id, &def)?;

// First create an API definition
let _: HttpApiDefinitionResponseData = cli.run(&["api-definition", "add", path.to_str().unwrap()])?;

let cfg = &cli.config;
let test_port = 3001;

// Then start the UI
let res: String = cli.run(&[
"api-definition",
"ui",
&cfg.arg('i', "id"),
&component_name,
&cfg.arg('V', "version"),
"0.1.0",
&cfg.arg('p', "port"),
&test_port.to_string(),
])?;

// Verify the response contains the expected URL
assert!(res.contains(&format!("http://127.0.0.1:{}/docs", test_port)));

Ok(())
}

0 comments on commit e9dbd93

Please sign in to comment.