fxa_client/state_machine/internal_machines/
disconnected.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use super::{invalid_transition, Event, InternalStateMachine, State};
6use crate::{Error, FxaEvent, FxaState, Result};
7
8pub struct DisconnectedStateMachine;
9
10// Save some typing
11use Event::*;
12use State::*;
13
14impl InternalStateMachine for DisconnectedStateMachine {
15    fn initial_state(&self, event: FxaEvent) -> Result<State> {
16        match event {
17            FxaEvent::BeginOAuthFlow { scopes, entrypoint } => {
18                Ok(State::BeginOAuthFlow { scopes, entrypoint })
19            }
20            FxaEvent::BeginPairingFlow {
21                pairing_url,
22                scopes,
23                entrypoint,
24            } => Ok(State::BeginPairingFlow {
25                pairing_url,
26                scopes,
27                entrypoint,
28            }),
29            e => Err(Error::InvalidStateTransition(format!(
30                "Disconnected -> {e}"
31            ))),
32        }
33    }
34
35    fn next_state(&self, state: State, event: Event) -> Result<State> {
36        Ok(match (state, event) {
37            (BeginOAuthFlow { .. }, BeginOAuthFlowSuccess { oauth_url }) => {
38                Complete(FxaState::Authenticating { oauth_url })
39            }
40            (BeginPairingFlow { .. }, BeginPairingFlowSuccess { oauth_url }) => {
41                Complete(FxaState::Authenticating { oauth_url })
42            }
43            (BeginOAuthFlow { .. }, CallError) => Cancel,
44            (BeginPairingFlow { .. }, CallError) => Cancel,
45            (state, event) => return invalid_transition(state, event),
46        })
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use super::super::StateMachineTester;
53    use super::*;
54
55    #[test]
56    fn test_oauth_flow() {
57        let tester = StateMachineTester::new(
58            DisconnectedStateMachine,
59            FxaEvent::BeginOAuthFlow {
60                scopes: vec!["profile".to_owned()],
61                entrypoint: "test-entrypoint".to_owned(),
62            },
63        );
64        assert_eq!(
65            tester.state,
66            BeginOAuthFlow {
67                scopes: vec!["profile".to_owned()],
68                entrypoint: "test-entrypoint".to_owned(),
69            }
70        );
71        assert_eq!(tester.peek_next_state(CallError), Cancel);
72        assert_eq!(
73            tester.peek_next_state(BeginOAuthFlowSuccess {
74                oauth_url: "http://example.com/oauth-start".to_owned(),
75            }),
76            Complete(FxaState::Authenticating {
77                oauth_url: "http://example.com/oauth-start".to_owned(),
78            })
79        );
80    }
81
82    #[test]
83    fn test_pairing_flow() {
84        let tester = StateMachineTester::new(
85            DisconnectedStateMachine,
86            FxaEvent::BeginPairingFlow {
87                pairing_url: "https://example.com/pairing-url".to_owned(),
88                scopes: vec!["profile".to_owned()],
89                entrypoint: "test-entrypoint".to_owned(),
90            },
91        );
92        assert_eq!(
93            tester.state,
94            BeginPairingFlow {
95                pairing_url: "https://example.com/pairing-url".to_owned(),
96                scopes: vec!["profile".to_owned()],
97                entrypoint: "test-entrypoint".to_owned(),
98            }
99        );
100        assert_eq!(tester.peek_next_state(CallError), Cancel);
101        assert_eq!(
102            tester.peek_next_state(BeginPairingFlowSuccess {
103                oauth_url: "http://example.com/oauth-start".to_owned(),
104            }),
105            Complete(FxaState::Authenticating {
106                oauth_url: "http://example.com/oauth-start".to_owned(),
107            })
108        );
109    }
110}