fxa_client/state_machine/internal_machines/
connected.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};
7use error_support::report_error;
8
9pub struct ConnectedStateMachine;
10
11// Save some typing
12use Event::*;
13use State::*;
14
15impl InternalStateMachine for ConnectedStateMachine {
16    fn initial_state(&self, event: FxaEvent) -> Result<State> {
17        match event {
18            FxaEvent::Disconnect => Ok(Disconnect),
19            FxaEvent::CheckAuthorizationStatus => Ok(CheckAuthorizationStatus),
20            FxaEvent::CallGetProfile => Ok(GetProfile),
21            e => Err(Error::InvalidStateTransition(format!("Connected -> {e}"))),
22        }
23    }
24
25    fn next_state(&self, state: State, event: Event) -> Result<State> {
26        Ok(match (state, event) {
27            (Disconnect, DisconnectSuccess) => Complete(FxaState::Disconnected),
28            (Disconnect, CallError) => {
29                // disconnect() is currently infallible, but let's handle errors anyway in case we
30                // refactor it in the future.
31                report_error!("fxa-state-machine-error", "saw CallError after Disconnect");
32                Complete(FxaState::Disconnected)
33            }
34            (CheckAuthorizationStatus, CheckAuthorizationStatusSuccess { active }) => {
35                if active {
36                    Complete(FxaState::Connected)
37                } else {
38                    Complete(FxaState::AuthIssues)
39                }
40            }
41            (GetProfile, GetProfileSuccess) => Complete(FxaState::Connected),
42            (GetProfile, CallError) => Complete(FxaState::AuthIssues),
43            (CheckAuthorizationStatus, CallError) => Complete(FxaState::AuthIssues),
44            (state, event) => return invalid_transition(state, event),
45        })
46    }
47}
48
49#[cfg(test)]
50mod test {
51    use super::super::StateMachineTester;
52    use super::*;
53
54    #[test]
55    fn test_disconnect() {
56        let tester = StateMachineTester::new(ConnectedStateMachine, FxaEvent::Disconnect);
57        assert_eq!(tester.state, Disconnect);
58        assert_eq!(
59            tester.peek_next_state(CallError),
60            Complete(FxaState::Disconnected)
61        );
62        assert_eq!(
63            tester.peek_next_state(DisconnectSuccess),
64            Complete(FxaState::Disconnected)
65        );
66    }
67
68    #[test]
69    fn test_check_authorization() {
70        let tester =
71            StateMachineTester::new(ConnectedStateMachine, FxaEvent::CheckAuthorizationStatus);
72        assert_eq!(tester.state, CheckAuthorizationStatus);
73        assert_eq!(
74            tester.peek_next_state(CallError),
75            Complete(FxaState::AuthIssues)
76        );
77        assert_eq!(
78            tester.peek_next_state(CheckAuthorizationStatusSuccess { active: true }),
79            Complete(FxaState::Connected),
80        );
81        assert_eq!(
82            tester.peek_next_state(CheckAuthorizationStatusSuccess { active: false }),
83            Complete(FxaState::AuthIssues)
84        );
85    }
86}