1
use crate::tests::{TestServiceSetup, gnome_prompter_test, plasma_prompter_test};
2

            
3
gnome_prompter_test!(prompt_called_twice_error_gnome, prompt_called_twice_error);
4
plasma_prompter_test!(prompt_called_twice_error_plasma, prompt_called_twice_error);
5

            
6
14
async fn prompt_called_twice_error() -> Result<(), Box<dyn std::error::Error>> {
7
6
    let setup = TestServiceSetup::plain_session(true).await?;
8

            
9
    // Lock the collection to create a prompt scenario
10
8
    let collection = setup
11
        .server
12
4
        .collection_from_path(setup.collections[0].inner().path())
13
6
        .await
14
        .expect("Collection should exist");
15
8
    collection
16
4
        .set_locked(true, setup.keyring_secret.clone())
17
6
        .await?;
18

            
19
    // Get a prompt path by calling unlock (which creates a prompt but doesn't
20
    // auto-trigger it)
21
8
    let (_unlocked, prompt_path) = setup
22
        .server
23
2
        .unlock(vec![setup.collections[0].inner().path().to_owned().into()])
24
6
        .await?;
25

            
26
    // Verify we got a prompt path
27
    assert!(!prompt_path.is_empty(), "Should have a prompt path");
28

            
29
    // Create a Prompt proxy manually
30
12
    let prompt = oo7::dbus::api::Prompt::new(&setup.client_conn, prompt_path.clone())
31
6
        .await?
32
        .unwrap();
33

            
34
    // First call to prompt() should succeed
35
6
    prompt.prompt(None).await?;
36

            
37
    // Give the prompt a moment to register the callback
38
4
    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
39

            
40
    // Second call to prompt() should fail with "callback is ongoing already" error
41
    assert!(
42
        prompt.prompt(None).await.is_err(),
43
        "Second call to prompt() should fail"
44
    );
45
2
    Ok(())
46
}
47

            
48
#[cfg(any(feature = "gnome_native_crypto", feature = "gnome_openssl_crypto"))]
49
#[tokio::test]
50
async fn prompt_not_found_error() -> Result<(), Box<dyn std::error::Error>> {
51
    let setup = TestServiceSetup::plain_session(true).await?;
52

            
53
    // Lock the collection to create a prompt scenario
54
    let collection = setup
55
        .server
56
        .collection_from_path(setup.collections[0].inner().path())
57
        .await
58
        .expect("Collection should exist");
59
    collection
60
        .set_locked(true, setup.keyring_secret.clone())
61
        .await?;
62

            
63
    // Create a prompt using server API
64
    let (_unlocked, prompt_path) = setup
65
        .server
66
        .unlock(vec![setup.collections[0].inner().path().to_owned().into()])
67
        .await?;
68

            
69
    assert!(!prompt_path.is_empty(), "Should have a prompt path");
70

            
71
    // Remove the prompt from the service before MockPrompter tries to process it
72
    setup.server.remove_prompt(&prompt_path).await;
73

            
74
    // Manually serve a callback to trigger the error path
75
    let callback = crate::gnome::prompter::PrompterCallback::new(
76
        None,
77
        setup.server.clone(),
78
        prompt_path.clone(),
79
    )
80
    .await?;
81

            
82
    let callback_path = super::OwnedObjectPath::from(callback.path().clone());
83
    setup
84
        .server
85
        .object_server()
86
        .at(&callback_path, callback.clone())
87
        .await?;
88

            
89
    // Now call prompt_ready which should fail because the prompt doesn't exist
90
    let result = callback
91
        .prompt_ready(
92
            zbus::zvariant::Optional::from(None),
93
            crate::gnome::prompter::Properties::default(),
94
            "",
95
        )
96
        .await;
97

            
98
    assert!(result.is_err(), "Should fail when prompt doesn't exist");
99

            
100
    // Verify it's the specific error we expect
101
    assert!(
102
        matches!(result, Err(oo7::dbus::ServiceError::NoSuchObject(_))),
103
        "Should be NoSuchObject error"
104
    );
105

            
106
    Ok(())
107
}
108

            
109
#[tokio::test]
110
async fn dismiss_prompt_cleanup() -> Result<(), Box<dyn std::error::Error>> {
111
    let setup = TestServiceSetup::plain_session(true).await?;
112

            
113
    // Lock the collection to create a prompt scenario
114
    let collection = setup
115
        .server
116
        .collection_from_path(setup.collections[0].inner().path())
117
        .await
118
        .expect("Collection should exist");
119
    collection
120
        .set_locked(true, setup.keyring_secret.clone())
121
        .await?;
122

            
123
    // Get a prompt path by calling unlock
124
    let (_unlocked, prompt_path) = setup
125
        .server
126
        .unlock(vec![setup.collections[0].inner().path().to_owned().into()])
127
        .await?;
128

            
129
    assert!(!prompt_path.is_empty(), "Should have a prompt path");
130

            
131
    // Verify prompt exists in service before dismissal
132
    let prompt_exists_before = setup.server.prompt(&prompt_path).await;
133
    assert!(
134
        prompt_exists_before.is_some(),
135
        "Prompt should exist in service before dismissal"
136
    );
137

            
138
    // Verify prompt is accessible via D-Bus
139
    let prompt = oo7::dbus::api::Prompt::new(&setup.client_conn, prompt_path.clone()).await?;
140
    assert!(
141
        prompt.is_some(),
142
        "Prompt should be accessible via D-Bus before dismissal"
143
    );
144

            
145
    // Dismiss the prompt
146
    prompt.unwrap().dismiss().await?;
147

            
148
    // Give it a moment to process the dismissal
149
    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
150

            
151
    // Verify prompt is removed from service
152
    let prompt_exists_after = setup.server.prompt(&prompt_path).await;
153
    assert!(
154
        prompt_exists_after.is_none(),
155
        "Prompt should be removed from service after dismissal"
156
    );
157

            
158
    Ok(())
159
}