7512 lines · 280.1 KB · Rust
RawDownload
use std::collections::HashMap;use std::sync::Arc;use std::time::Duration; use chrono::{DateTime, Utc};use cloud_object_client::MockObjectClient;use cloud_object_models::JsonSerializer;use futures_lite::future;use settings::{RespectUserSyncSetting, SyncToCloud};use warp_core::features::FeatureFlag;use warp_graphql::object_permissions::AccessLevel;use warp_graphql::scalars::time::ServerTimestamp;use warpui::{App, ModelHandle, SingletonEntity}; use super::{GetCloudObjectResponse, InitialLoadResponse, UpdateManager};use crate::ASSETS;use crate::ai::cloud_environments::{    AmbientAgentEnvironment, CloudAmbientAgentEnvironment, CloudAmbientAgentEnvironmentModel,};use crate::auth::UserUid;use crate::auth::user::TEST_USER_UID;use crate::cloud_object::model::actions::{    ObjectAction, ObjectActionHistory, ObjectActionSubtype, ObjectActionType, ObjectActions,};use crate::cloud_object::model::generic_string_model::GenericStringObjectId;use crate::cloud_object::model::persistence::{CloudModel, CloudModelEvent, UpdateSource};use crate::cloud_object::{    BulkCreateCloudObjectResult, CloudModelType, CloudObjectEventEntrypoint, CloudObjectGuest,    CloudObjectLocation, ConflictStatus, CreateCloudObjectResult, CreatedCloudObject,    GenericCloudObject, GenericStringObjectFormat, JsonObjectType, ObjectDeleteResult,    ObjectIdType, ObjectMetadataUpdateResult, ObjectPermissionsUpdateData, ObjectType, Owner,    Revision, RevisionAndLastEditor, ServerCloudObject, ServerFolder, ServerGuestSubject,    ServerNotebook, ServerObject, ServerObjectGuest, ServerPreference, ServerWorkflow,    ServerWorkflowEnum, Space, UpdateCloudObjectResult,};use crate::drive::CloudObjectTypeAndId;use crate::drive::folders::{CloudFolder, CloudFolderModel, FolderId};use crate::drive::sharing::{SharingAccessLevel, Subject, UserKind};use crate::notebooks::{CloudNotebook, CloudNotebookModel, NotebookId};use crate::persistence::ModelEvent;use crate::server::cloud_objects::listener::ObjectUpdateMessage;use crate::server::cloud_objects::test_utils::{    UpdateManagerStruct, create_update_manager_struct, initialize_app, mock_server_api,};use crate::server::cloud_objects::update_manager::{    FetchSingleObjectOption, GenericStringObjectInput, InitiatedBy, ServerMetadata,    ServerPermissions, get_duplicate_object_name,};use crate::server::ids::{    ClientId, HashableId, ObjectUid, ServerId, ServerIdAndType, SyncId, ToServerId,};use crate::server::sync_queue::SyncQueue;use crate::settings::{CloudPreferenceModel, Preference};use crate::workflows::workflow::{Argument, ArgumentType, Workflow};use crate::workflows::workflow_enum::{    CloudWorkflowEnum, CloudWorkflowEnumModel, EnumVariants, WorkflowEnum,};use crate::workflows::{CloudWorkflow, CloudWorkflowModel, WorkflowId};use crate::workspaces::user_profiles::{UserProfileWithUID, UserProfiles}; fn create_object<K, M>(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    client_id: ClientId,    model: M,) -> GenericCloudObject<K, M>where    K: HashableId        + ToServerId        + std::fmt::Debug        + Into<String>        + Clone        + Copy        + Send        + Sync        + 'static,    M: CloudModelType<IdType = K, CloudObjectType = GenericCloudObject<K, M>> + 'static,{    update_manager.update(app, |update_manager, ctx| {        update_manager.create_object(            model,            Owner::mock_current_user(),            client_id,            CloudObjectEventEntrypoint::Unknown,            true,            None,            InitiatedBy::User,            ctx,        );    });    CloudModel::handle(app).read(app, |cloud_model, _ctx| {        cloud_model            .get_object_of_type::<K, M>(&SyncId::ClientId(client_id))            .expect("object should exist")            .clone()    })} fn create_object_result<K: HashableId + ToServerId>(    client_id: ClientId,    object_id: K,    object_id_type: ObjectIdType,) -> CreateCloudObjectResult {    CreateCloudObjectResult::Success {        created_cloud_object: CreatedCloudObject {            client_id,            revision_and_editor: RevisionAndLastEditor {                revision: Revision::now(),                last_editor_uid: Some("34jkaosdfj".to_string()),            },            metadata_ts: DateTime::<Utc>::default().into(),            creator_uid: None,            server_id_and_type: ServerIdAndType {                id: object_id.to_server_id(),                id_type: object_id_type,            },            permissions: ServerPermissions::mock_personal(),        },    }} fn create_notebook(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    client_id: ClientId,) {    update_manager.update(app, |update_manager, ctx| {        update_manager.create_notebook(            client_id,            Owner::mock_current_user(),            None,            Default::default(),            CloudObjectEventEntrypoint::Unknown,            true,            ctx,        );    });} fn receive_object_update_from_rtc(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    item: ObjectUpdateMessage,) {    update_manager.update(app, move |update_manager, ctx| {        update_manager.received_message_from_server(item, ctx);    })} fn receive_initial_load_or_polling_update(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    force_refresh: bool,    mocked_response: InitialLoadResponse,) {    update_manager.update(app, move |update_manager, ctx| {        update_manager.on_changed_objects_fetched(mocked_response, force_refresh, ctx);    })} fn mock_server_permissions(owner: Owner) -> ServerPermissions {    ServerPermissions {        space: owner,        guests: Vec::new(),        anyone_link_sharing: None,        permissions_last_updated_ts: Utc::now().into(),    }} fn create_workflow(    client_id: ClientId,    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,) {    create_workflow_internal(        app,        update_manager,        client_id,        "client_workflow".to_string(),        "echo client".to_string(),        Owner::mock_current_user(),        None,    )} fn create_workflow_internal(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    client_id: ClientId,    workflow_name: String,    workflow_command: String,    owner: Owner,    initial_folder_id: Option<SyncId>,) {    update_manager.update(app, |update_manager, ctx| {        update_manager.create_workflow(            Workflow::new(workflow_name, workflow_command),            owner,            initial_folder_id,            client_id,            CloudObjectEventEntrypoint::Unknown,            true,            ctx,        );    });} fn get_workflow(app: &App, sync_id: SyncId) -> CloudWorkflow {    CloudModel::handle(app).read(app, |cloud_model, _ctx| {        cloud_model            .get_workflow(&sync_id)            .expect("workflow should exist")            .clone()    })} fn create_workflow_enum(    client_id: ClientId,    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,) {    create_workflow_enum_internal(        app,        update_manager,        client_id,        "workflow_enum".to_string(),        vec!["variant 1".to_string(), "variant 2".to_string()],        Owner::mock_current_user(),    )} fn create_workflow_enum_internal(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    client_id: ClientId,    enum_name: String,    enum_variants: Vec<String>,    owner: Owner,) {    update_manager.update(app, |update_manager, ctx| {        update_manager.create_workflow_enum(            WorkflowEnum {                name: enum_name,                variants: EnumVariants::Static(enum_variants),                is_shared: false,            },            owner,            client_id,            CloudObjectEventEntrypoint::Unknown,            true,            ctx,        );    });} fn mock_server_workflow(id: WorkflowId, owner: Owner, metadata: ServerMetadata) -> ServerWorkflow {    ServerWorkflow::new(        SyncId::ServerId(id.into()),        CloudWorkflowModel::new(Workflow::new(format!("w{id}"), format!("c{id}"))),        metadata,        mock_server_permissions(owner),    )} fn mock_server_workflow_with_enum(    id: WorkflowId,    enum_id: GenericStringObjectId,    owner: Owner,    metadata: ServerMetadata,) -> (ServerWorkflow, ServerWorkflowEnum) {    let workflow = ServerWorkflow::new(        SyncId::ServerId(id.into()),        CloudWorkflowModel::new(            Workflow::new(format!("w{id}"), format!("c{id}")).with_arguments(vec![Argument {                name: format!("e{enum_id}"),                default_value: None,                description: None,                arg_type: ArgumentType::Enum {                    enum_id: SyncId::ServerId(enum_id.into()),                },            }]),        ),        metadata.clone(),        mock_server_permissions(owner),    );     let workflow_enum = ServerWorkflowEnum::new(        SyncId::ServerId(enum_id.into()),        CloudWorkflowEnumModel::new(WorkflowEnum {            name: format!("e{id}"),            is_shared: false,            variants: EnumVariants::Static(vec!["v1".to_string(), "v2".to_string()]),        }),        metadata,        mock_server_permissions(owner),    );     (workflow, workflow_enum)} fn mock_server_notebook(id: NotebookId, owner: Owner, metadata: ServerMetadata) -> ServerNotebook {    ServerNotebook::new(        SyncId::ServerId(id.into()),        CloudNotebookModel {            title: format!("n{id}"),            data: format!("n{id}"),            ai_document_id: None,            conversation_id: None,        },        metadata,        mock_server_permissions(owner),    )} fn mock_server_folder(id: FolderId, owner: Owner, metadata: ServerMetadata) -> ServerFolder {    ServerFolder::new(        SyncId::ServerId(id.into()),        CloudFolderModel {            name: format!("f{id}"),            is_open: false,            is_warp_pack: false,        },        metadata,        mock_server_permissions(owner),    )} fn update_notebook(    app: &mut App,    update_manager: &ModelHandle<UpdateManager>,    client_id: ClientId,    title: String,) {    update_manager.update(app, |update_manager, ctx| {        update_manager.update_notebook_title(Arc::new(title), SyncId::ClientId(client_id), ctx);    });} fn update_workflow(app: &mut App, update_manager: &ModelHandle<UpdateManager>, sync_id: SyncId) {    update_manager.update(app, |update_manager, ctx| {        update_manager.update_workflow(            Workflow::new("client workflow 2", "echo client 2"),            sync_id,            None,            ctx,        )    });} #[track_caller]fn assert_pending_online_only_change_for_object(app: &mut App, uid: &ObjectUid, status: bool) {    CloudModel::handle(app).update(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_mut_by_uid(uid) {            assert_eq!(                object.metadata().has_pending_online_only_change(),                status,                "Expected has_pending_online_only_change for {uid} to be {status}"            );        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_pending_status_for_object(app: &mut App, uid: &ObjectUid, status: bool) {    CloudModel::handle(app).update(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_mut_by_uid(uid) {            assert_eq!(                object.metadata().has_pending_content_changes(),                status,                "Expected has_pending_content_changes for {uid} to be {status}"            );        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_errored_status_for_object(app: &mut App, uid: &ObjectUid, is_errored: bool) {    CloudModel::handle(app).update(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_mut_by_uid(uid) {            assert_eq!(                object.metadata().is_errored(),                is_errored,                "Expected error status for {uid} to be {is_errored}"            );        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_trashed_status_for_object(app: &mut App, uid: &ObjectUid, is_trashed: bool) {    CloudModel::handle(app).update(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_mut_by_uid(uid) {            assert_eq!(                object.metadata().trashed_ts.is_some(),                is_trashed,                "Expected trashed status for {uid} to be {is_trashed}"            );        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_conflict_status_for_object(app: &mut App, uid: &ObjectUid, has_conflicts: bool) {    CloudModel::handle(app).read(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_by_uid(uid) {            assert_eq!(                object.has_conflicting_changes(),                has_conflicts,                "Expected conflict status for {uid} to be {has_conflicts}"            );        } else {            panic!("object {uid} should have been in cloud model, but wasn't");        }    })} fn assert_root_level_for_object(app: &mut App, uid: &ObjectUid, is_root_level: bool) {    CloudModel::handle(app).update(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_mut_by_uid(uid) {            assert_eq!(object.metadata().folder_id.is_none(), is_root_level);        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_folder_for_object(app: &App, uid: &ObjectUid, folder_id: Option<SyncId>) {    CloudModel::handle(app).read(app, |cloud_model, _| {        if let Some(object) = cloud_model.get_by_uid(uid) {            assert_eq!(object.metadata().folder_id, folder_id);        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} fn assert_space_for_object(app: &App, uid: &ObjectUid, space: Space) {    CloudModel::handle(app).read(app, |cloud_model, ctx| {        if let Some(object) = cloud_model.get_by_uid(uid) {            assert_eq!(object.space(ctx), space);        } else {            panic!("object should have been in cloud model, but wasn't");        }    });} /// Asserts that the current editor email address of the object matches the expected value.fn assert_current_editor_for_object(app: &mut App, uid: &ObjectUid, current_editor: Option<&str>) {    app.read(|ctx| {        if let Some(object) = CloudModel::as_ref(ctx).get_by_uid(uid) {            assert_eq!(                object.metadata().current_editor_uid.as_deref(),                current_editor            );        } else {            panic!("object {uid} should have been in cloud model, but wasn't");        }    });} /// Asserts that the `metadata_last_updated_ts` timestamp for an object has the expected value.fn assert_metadata_ts_for_object(app: &mut App, uid: &ObjectUid, metadata_ts: ServerTimestamp) {    app.read(|ctx| {        if let Some(object) = CloudModel::as_ref(ctx).get_by_uid(uid) {            assert_eq!(                object.metadata().metadata_last_updated_ts,                Some(metadata_ts)            );        } else {            panic!("object {uid} should have been in cloud model, but wasn't");        }    });} /// Asserts that the `revision` timestamp for an object has the expected value.fn assert_revision_for_object(app: &App, uid: &ObjectUid, revision: impl Into<Revision>) {    let revision = revision.into();    app.read(|ctx| {        if let Some(object) = CloudModel::as_ref(ctx).get_by_uid(uid) {            assert_eq!(object.metadata().revision, Some(revision));        } else {            panic!("object {uid} should have been in cloud model, but wasn't");        }    });} fn assert_workflow_name(app: &mut App, sync_id: SyncId, expected_name: &str) {    let workflow = get_workflow(app, sync_id);    assert_eq!(workflow.model().data.name(), expected_name);} fn assert_notebook_data(app: &App, sync_id: SyncId, expected_data: &str) {    CloudModel::handle(app).read(app, |cloud_model, _| {        match cloud_model.get_notebook(&sync_id) {            Some(notebook) => assert_eq!(&notebook.model().data, expected_data),            None => panic!("notebook {sync_id:?} should have been in cloud model, but wasn't"),

Lines 1–500 of 7512.