Integration Test for getComponentGroups method (#3483)

This PR contains minimal integration with new engine's method and an integration test printing the method's return value. It was written as a part of https://www.pivotaltracker.com/story/show/181743571

# Important Notes
The test requires 2022.1.1-nightly.2022-04-26 engine version or later.
This commit is contained in:
Adam Obuchowicz 2022-05-27 13:47:44 +02:00 committed by GitHub
parent 58581b69d0
commit 9c13a7fcbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 49 deletions

1
Cargo.lock generated
View File

@ -1970,6 +1970,7 @@ name = "enso-integration-test"
version = "0.1.0"
dependencies = [
"approx 0.5.1",
"engine-protocol",
"enso-frp",
"enso-gui",
"enso-prelude",

View File

@ -16,8 +16,8 @@ minimumSupportedVersion": "2.0.0-alpha.6"
# The minimum engine version supported by the application. The projects opened with the older versions
# will have the "Unsupported engine version" message displayed.
engineVersionSupported: "0.2.31"
engineVersionSupported: "2022.1.1-nightly.2022-04-26"
# The minimum language edition supported by the application. It will be displayed as edition user
# should put in their package.yaml file to have project compatible with the IDE.
languageEditionSupported: "2021.19"
languageEditionSupported: "2022.1.1-nightly.2022-04-26"

View File

@ -49,92 +49,92 @@ trait API {
/// Initialize the connection used to send the textual protocol messages. This initialisation
/// is important such that the client identifier can be correlated between the textual and data
/// connections.
#[MethodInput=InitProtocolInput,rpc_name="session/initProtocolConnection"]
fn init_protocol_connection(&self, client_id:Uuid) -> response::InitProtocolConnection;
#[MethodInput=InitProtocolInput, rpc_name="session/initProtocolConnection"]
fn init_protocol_connection(&self, client_id: Uuid) -> response::InitProtocolConnection;
/// Copy a specified file system object to another location.
#[MethodInput=CopyFileInput,rpc_name="file/copy"]
fn copy_file(&self, from:Path, to:Path) -> ();
#[MethodInput=CopyFileInput, rpc_name="file/copy"]
fn copy_file(&self, from: Path, to: Path) -> ();
/// Delete the specified file system object.
#[MethodInput=DeleteFileInput,rpc_name="file/delete"]
fn delete_file(&self, path:Path) -> ();
#[MethodInput=DeleteFileInput, rpc_name="file/delete"]
fn delete_file(&self, path: Path) -> ();
/// Check if file system object exists.
#[MethodInput=FileExistsInput,rpc_name="file/exists"]
fn file_exists(&self, path:Path) -> response::FileExists;
#[MethodInput=FileExistsInput, rpc_name="file/exists"]
fn file_exists(&self, path: Path) -> response::FileExists;
/// List all file-system objects in the specified path.
#[MethodInput=FileListInput,rpc_name="file/list"]
fn file_list(&self, path:Path) -> response::FileList;
#[MethodInput=FileListInput, rpc_name="file/list"]
fn file_list(&self, path: Path) -> response::FileList;
/// Move file system object to another location.
#[MethodInput=MoveFileInput,rpc_name="file/move"]
fn move_file(&self, from:Path, to:Path) -> ();
#[MethodInput=MoveFileInput, rpc_name="file/move"]
fn move_file(&self, from: Path, to: Path) -> ();
/// Reads file's content as a String.
#[MethodInput=ReadFileInput,rpc_name="file/read"]
fn read_file(&self, path:Path) -> response::Read;
#[MethodInput=ReadFileInput, rpc_name="file/read"]
fn read_file(&self, path: Path) -> response::Read;
/// Gets file system object's attributes information.
#[MethodInput=FileInfoInput,rpc_name="file/info"]
fn file_info(&self, path:Path) -> response::FileInfo;
#[MethodInput=FileInfoInput, rpc_name="file/info"]
fn file_info(&self, path: Path) -> response::FileInfo;
/// Requests that the language server provide the checksum of the provided file.
#[MethodInput=FileChecksumInput,rpc_name="file/checksum"]
fn file_checksum(&self, path:Path) -> response::FileChecksum;
#[MethodInput=FileChecksumInput, rpc_name="file/checksum"]
fn file_checksum(&self, path: Path) -> response::FileChecksum;
/// Creates the specified file system object.
#[MethodInput=CreateInput,rpc_name="file/create"]
fn create_file(&self, object:FileSystemObject) -> ();
#[MethodInput=CreateInput, rpc_name="file/create"]
fn create_file(&self, object: FileSystemObject) -> ();
/// Writes String contents to a file in the specified path.
#[MethodInput=FileWriteInput,rpc_name="file/write"]
fn write_file(&self, path:Path, contents:String) -> ();
#[MethodInput=FileWriteInput, rpc_name="file/write"]
fn write_file(&self, path: Path, contents: String) -> ();
/// Acquire capability permission.
#[MethodInput=AcquireCapabilityInput,rpc_name="capability/acquire"]
fn acquire_capability(&self, method:String, register_options:RegisterOptions) -> ();
#[MethodInput=AcquireCapabilityInput, rpc_name="capability/acquire"]
fn acquire_capability(&self, method: String, register_options: RegisterOptions) -> ();
/// Open the specified file. If no user has write lock on the opened file, the write lock
/// capability is granted to the caller.
#[MethodInput=OpenTextFileInput,rpc_name="text/openFile"]
fn open_text_file(&self, path:Path) -> response::OpenTextFile;
#[MethodInput=OpenTextFileInput, rpc_name="text/openFile"]
fn open_text_file(&self, path: Path) -> response::OpenTextFile;
/// Informs the language server that a client has closed the specified file.
#[MethodInput=CloseTextFileInput,rpc_name="text/closeFile"]
fn close_text_file(&self, path:Path) -> ();
#[MethodInput=CloseTextFileInput, rpc_name="text/closeFile"]
fn close_text_file(&self, path: Path) -> ();
/// Save the specified file. It may fail if the user does not have permission to edit that file.
#[MethodInput=SaveTextFileInput,rpc_name="text/save"]
fn save_text_file(&self, path:Path, current_version:Sha3_224) -> ();
#[MethodInput=SaveTextFileInput, rpc_name="text/save"]
fn save_text_file(&self, path: Path, current_version:Sha3_224) -> ();
/// Apply edits to the specified text file. This operation may fail if the user does not
/// have permission to edit the resources for which edits are sent. This failure may be partial,
/// in that some edits are applied and others are not.
#[MethodInput=ApplyTextFileEditInput,rpc_name="text/applyEdit"]
fn apply_text_file_edit(&self, edit:FileEdit) -> ();
#[MethodInput=ApplyTextFileEditInput, rpc_name="text/applyEdit"]
fn apply_text_file_edit(&self, edit: FileEdit) -> ();
/// Create a new execution context. Return capabilities executionContext/canModify and
/// executionContext/receivesUpdates containing freshly created ContextId
#[MethodInput=CreateExecutionContextInput,rpc_name="executionContext/create"]
#[MethodInput=CreateExecutionContextInput, rpc_name="executionContext/create"]
fn create_execution_context(&self) -> response::CreateExecutionContext;
/// Destroy an execution context and free its resources.
#[MethodInput=DestroyExecutionContextInput,rpc_name="executionContext/destroy"]
fn destroy_execution_context(&self, context_id:ContextId) -> ();
#[MethodInput=DestroyExecutionContextInput, rpc_name="executionContext/destroy"]
fn destroy_execution_context(&self, context_id: ContextId) -> ();
/// Move the execution context to a new location deeper down the stack.
#[MethodInput=PushToExecutionContextInput,rpc_name="executionContext/push"]
fn push_to_execution_context(&self, context_id:ContextId, stack_item:StackItem) -> ();
#[MethodInput=PushToExecutionContextInput, rpc_name="executionContext/push"]
fn push_to_execution_context(&self, context_id: ContextId, stack_item: StackItem) -> ();
/// Move the execution context up the stack.
#[MethodInput=PopFromExecutionContextInput,rpc_name="executionContext/pop"]
fn pop_from_execution_context(&self, context_id:ContextId) -> ();
#[MethodInput=PopFromExecutionContextInput, rpc_name="executionContext/pop"]
fn pop_from_execution_context(&self, context_id: ContextId) -> ();
/// Attach a visualisation, potentially preprocessed by some arbitrary Enso code, to a given
/// node in the program.
#[MethodInput=AttachVisualisationInput,rpc_name="executionContext/attachVisualisation"]
#[MethodInput=AttachVisualisationInput, rpc_name="executionContext/attachVisualisation"]
fn attach_visualisation
( &self
, visualisation_id : Uuid
@ -142,17 +142,17 @@ trait API {
, visualisation_config : VisualisationConfiguration) -> ();
/// Detach a visualisation from the executing code.
#[MethodInput=DetachVisualisationInput,rpc_name="executionContext/detachVisualisation"]
#[MethodInput=DetachVisualisationInput, rpc_name="executionContext/detachVisualisation"]
fn detach_visualisation
(&self, context_id:Uuid, visualisation_id:Uuid, expression_id:Uuid) -> ();
(&self, context_id: Uuid, visualisation_id: Uuid, expression_id: Uuid) -> ();
/// Modify the configuration for an existing visualisation.
#[MethodInput=ModifyVisualisationInput,rpc_name="executionContext/modifyVisualisation"]
#[MethodInput=ModifyVisualisationInput, rpc_name="executionContext/modifyVisualisation"]
fn modify_visualisation
(&self, visualisation_id:Uuid, visualisation_config:VisualisationConfiguration) -> ();
(&self, visualisation_id: Uuid, visualisation_config: VisualisationConfiguration) -> ();
/// Obtain the full suggestions database.
#[MethodInput=GetSuggestionsDatabaseInput,rpc_name="search/getSuggestionsDatabase"]
#[MethodInput=GetSuggestionsDatabaseInput, rpc_name="search/getSuggestionsDatabase"]
fn get_suggestions_database(&self) -> response::GetSuggestionDatabase;
/// Receive the current version of the suggestions database.
@ -170,6 +170,10 @@ trait API {
, return_type : Option<String>
, tags : Option<Vec<SuggestionEntryType>>
) -> response::Completion;
/// Get the list of component groups available in runtime.
#[MethodInput=GetComponentGroups, rpc_name="executionContext/getComponentGroups"]
fn get_component_groups(&self, context_id: ContextId) -> response::GetComponentGroups;
}}

View File

@ -1,8 +1,12 @@
//! Helper structures wrapping RPC method result types.
use super::*;
use crate::language_server::types::*;
use crate::prelude::*;
use crate::language_server::SuggestionsDatabaseEntry;
use crate::types::Sha3_224;
use serde::Deserialize;
use serde::Serialize;
@ -94,3 +98,11 @@ pub struct Completion {
pub results: Vec<SuggestionId>,
pub current_version: SuggestionsDatabaseVersion,
}
/// Response of `get_component_groups` method.
#[derive(Hash, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(missing_docs)]
pub struct GetComponentGroups {
pub component_groups: Vec<LibraryComponentGroup>,
}

View File

@ -1025,6 +1025,43 @@ pub struct SuggestionDatabaseUpdatesEvent {
pub current_version: SuggestionsDatabaseVersion,
}
// =============================
// === LibraryComponentGroup ===
// =============================
/// A single component of a [`LibraryComponentGroup`].
#[derive(Hash, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(missing_docs)]
pub struct LibraryComponent {
name: String,
shortcut: Option<String>,
}
/// The component group provided by a library.
#[derive(Hash, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(missing_docs)]
pub struct LibraryComponentGroup {
/// The fully qualified module name. A string consisting of a namespace and a library name
/// separated by the dot <namespace>.<library name>, i.e. `Standard.Base`
library: String,
/// The group name without the library name prefix. E.g. given the `Standard.Base.Group 1`
/// group reference, the `group` field contains `Group 1`.
group: String,
color: Option<String>,
icon: Option<String>,
/// The list of components provided by this component group.
exports: Vec<LibraryComponent>,
}
// ======================
// === Test Utilities ===
// ======================
/// Utilities for testing code using the LS types.
pub mod test {
use super::*;

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
approx = "0.5.1"
engine-protocol = { path = "../app/gui/controller/engine-protocol" }
ensogl = { path = "../lib/rust/ensogl" }
enso-frp = { path = "../lib/rust/frp" }
enso-prelude = { path = "../lib/rust/prelude" }

View File

@ -0,0 +1,70 @@
//! The test suite of IDE-engine communication. The view is not instantiated, and controllers
//! may be used for convenience.
use enso_gui::integration_test::prelude::*;
use engine_protocol::language_server::ExplicitCall;
use engine_protocol::language_server::MethodPointer;
use engine_protocol::language_server::StackItem;
use enso_gui::controller::project::MAIN_DEFINITION_NAME;
use enso_gui::executor::web::EventLoopExecutor;
use enso_gui::initializer::setup_global_executor;
use enso_web::sleep;
use std::time::Duration;
use wasm_bindgen_test::wasm_bindgen_test;
// =======================================
// === TestOnNewProjectControllersOnly ===
// =======================================
struct TestOnNewProjectControllersOnly {
_ide: controller::Ide,
project: model::Project,
_executor: EventLoopExecutor,
}
impl TestOnNewProjectControllersOnly {
async fn set_up() -> Self {
let executor = setup_global_executor();
let logger = Logger::new("Test");
let config = enso_gui::config::Startup::default();
info!(logger, "Setting up the project.");
let initializer = enso_gui::Initializer::new(config);
let error_msg = "Couldn't open project.";
let ide = initializer.initialize_ide_controller().await.expect(error_msg);
ide.manage_projects().unwrap().create_new_project(None).await.unwrap();
let project = ide.current_project().unwrap();
Self { _ide: ide, project, _executor: executor }
}
}
// =============
// === Tests ===
// =============
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
// This test requires 2022.1.1-nightly.2022-04-26 or later version of Engine.
#[wasm_bindgen_test]
async fn getting_component_groups() {
let test = TestOnNewProjectControllersOnly::set_up().await;
let ls_json_connection = test.project.json_rpc();
let main_module = test.project.main_module().to_string();
let execution_ctx = ls_json_connection.create_execution_context().await.unwrap();
let frame = StackItem::ExplicitCall(ExplicitCall {
method_pointer: MethodPointer {
module: main_module.clone(),
defined_on_type: main_module,
name: MAIN_DEFINITION_NAME.to_owned(),
},
this_argument_expression: None,
positional_arguments_expressions: vec![],
});
ls_json_connection.push_to_execution_context(&execution_ctx.context_id, &frame).await.unwrap();
sleep(Duration::from_secs(15)).await;
let groups = ls_json_connection.get_component_groups(&execution_ctx.context_id).await.unwrap();
DEBUG!("{groups:?}");
}