disma 0.16.4

Discord server management has never been easier!
Documentation
use crate::{
    channel::{AwaitingChannel, ExistingChannel},
    core::diffs::{Diff, Differ},
    utils::misc::IfThen,
};

impl Differ<AwaitingChannel> for ExistingChannel {
    fn diffs_with(&self, awaiting: &AwaitingChannel) -> Vec<Diff> {
        let mut all_diffs = vec![];

        self.topic.diffs_with(&awaiting.topic).if_then(
            |diffs| !diffs.is_empty(),
            |diffs| all_diffs.push(Diff::Update("topic".into(), diffs)),
        );

        self.channel_type
            .diffs_with(&awaiting.channel_type)
            .if_then(
                |diffs| !diffs.is_empty(),
                |diffs| all_diffs.push(Diff::Update("channel_type".into(), diffs)),
            );

        self.category_name()
            .diffs_with(&awaiting.category_name())
            .if_then(
                |diffs| !diffs.is_empty(),
                |diffs| all_diffs.push(Diff::Update("category".into(), diffs)),
            );

        self.overwrites.diffs_with(&awaiting.overwrites).if_then(
            |diffs| !diffs.is_empty(),
            |diffs| all_diffs.push(Diff::Update("overwrites".into(), diffs)),
        );

        all_diffs
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;

    use crate::{
        category::{AwaitingCategory, ExistingCategory},
        channel::{AwaitingChannel, ChannelType, ExistingChannel, KeepExtraChannels},
        core::diffs::{Diff, Differ},
        permission::{
            Permission, PermissionsList, PermissionsOverwrite, PermissionsOverwritesList,
        },
        role::{AwaitingRole, ExistingRole},
    };

    fn given_existing_role_with(name: String) -> ExistingRole {
        ExistingRole {
            id: "something".to_string(),
            name,
            permissions: PermissionsList::from(vec![Permission::SEND_MESSAGES]),
            color: Some("a3bb30".to_string()),
            is_mentionable: true,
            show_in_sidebar: true,
        }
    }

    fn given_awaiting_role_with(name: String) -> AwaitingRole {
        AwaitingRole {
            name,
            permissions: PermissionsList::from(vec![Permission::ADMINISTRATOR]),
            color: None,
            is_mentionable: false,
            show_in_sidebar: false,
        }
    }

    fn given_existing_category_with_name(name: String) -> ExistingCategory {
        ExistingCategory {
            id: "something".to_string(),
            name,
            overwrites: PermissionsOverwritesList::from(vec![]),
        }
    }

    fn given_awaiting_category_with_name(name: String) -> AwaitingCategory {
        AwaitingCategory {
            name,
            overwrites: PermissionsOverwritesList::new(),
            extra_channels_strategy: Arc::from(KeepExtraChannels {}),
        }
    }

    #[test]
    fn can_diff_topic_update() {
        let name = "channel_a".to_string();
        let channel_type = ChannelType::TEXT;

        let origin = ExistingChannel {
            id: "something".to_string(),
            name: name.clone(),
            topic: Some("bang bang!".to_string()),
            channel_type: channel_type.clone(),
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let target = AwaitingChannel {
            name,
            topic: Some("Not here".to_string()),
            channel_type,
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let diffs = origin.diffs_with(&target);

        let expected_diffs = vec![Diff::Update(
            "topic".to_string(),
            vec![
                Diff::Remove("bang bang!".to_string()),
                Diff::Add("Not here".to_string()),
            ],
        )];
        assert_eq!(diffs, expected_diffs);
    }

    #[test]
    fn can_diff_channel_type_update() {
        let name = "channel_a".to_string();
        let topic = Some("Not here!".to_string());

        let origin = ExistingChannel {
            id: "something".to_string(),
            name: name.clone(),
            topic: topic.clone(),
            channel_type: ChannelType::TEXT,
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let target = AwaitingChannel {
            name,
            topic,
            channel_type: ChannelType::VOICE,
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let diffs = origin.diffs_with(&target);

        let expected_diffs = vec![Diff::Update(
            "channel_type".to_string(),
            vec![
                Diff::Remove(ChannelType::TEXT.to_string()),
                Diff::Add(ChannelType::VOICE.to_string()),
            ],
        )];
        assert_eq!(diffs, expected_diffs);
    }

    #[test]
    fn can_diff_category_update() {
        let name = "channel_a".to_string();
        let topic = Some("Not here!".to_string());
        let channel_type = ChannelType::TEXT;

        let origin = ExistingChannel {
            id: "something".to_string(),
            name: name.clone(),
            topic: topic.clone(),
            channel_type: channel_type.clone(),
            category: Some(given_existing_category_with_name("category_a".to_string())),
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let target = AwaitingChannel {
            name,
            topic,
            channel_type,
            category: Some(given_awaiting_category_with_name("category_b".to_string())),
            overwrites: PermissionsOverwritesList::from(vec![]),
        };

        let diffs = origin.diffs_with(&target);

        let expected_diffs = vec![Diff::Update(
            "category".to_string(),
            vec![
                Diff::Remove("category_a".to_string()),
                Diff::Add("category_b".to_string()),
            ],
        )];
        assert_eq!(diffs, expected_diffs);
    }

    #[test]
    fn can_diff_overwrites_update() {
        let name = "channel_a".to_string();
        let topic = Some("Not here!".to_string());
        let channel_type = ChannelType::TEXT;
        let role_name = "role_a".to_string();

        let origin = ExistingChannel {
            id: "something".to_string(),
            name: name.clone(),
            topic: topic.clone(),
            channel_type: channel_type.clone(),
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![PermissionsOverwrite {
                role: given_existing_role_with(role_name.clone()),
                allow: PermissionsList::from(vec![Permission::READ_MESSAGE_HISTORY]),
                deny: PermissionsList::from(vec![Permission::SEND_MESSAGES]),
            }]),
        };

        let target = AwaitingChannel {
            name,
            topic,
            channel_type,
            category: None,
            overwrites: PermissionsOverwritesList::from(vec![PermissionsOverwrite {
                role: given_awaiting_role_with(role_name.clone()),
                allow: PermissionsList::from(vec![Permission::SEND_MESSAGES]),
                deny: PermissionsList::from(vec![Permission::READ_MESSAGE_HISTORY]),
            }]),
        };

        let diffs = origin.diffs_with(&target);

        let expected_diffs = vec![Diff::Update(
            "overwrites".to_string(),
            vec![Diff::Update(
                role_name,
                vec![
                    Diff::Update(
                        "allow".to_string(),
                        vec![
                            Diff::Remove(Permission::READ_MESSAGE_HISTORY.to_string()),
                            Diff::Add(Permission::SEND_MESSAGES.to_string()),
                        ],
                    ),
                    Diff::Update(
                        "deny".to_string(),
                        vec![
                            Diff::Remove(Permission::SEND_MESSAGES.to_string()),
                            Diff::Add(Permission::READ_MESSAGE_HISTORY.to_string()),
                        ],
                    ),
                ],
            )],
        )];
        assert_eq!(diffs, expected_diffs);
    }
}