material-ui-rs 0.5.3

A Material3 inspired theme for `iced`
Documentation
use super::*;

#[test]
fn state_toggles_open_closed() {
    let mut state = State::new();

    assert!(!state.is_open());

    state.toggle();
    assert!(state.is_open());

    state.close();
    assert!(!state.is_open());
}

#[test]
fn state_toggle_animates_picker_panel_reveal() {
    let start = Instant::now();
    let mut state = State::new();

    assert_eq!(state.reveal(), 0.0);
    state.toggle_at(start);

    assert!(state.is_open());
    assert!(state.is_animating());
    assert_eq!(state.reveal(), 0.0);

    assert!(state.advance(start + duration_ms(PICKER_PANEL_TRANSITION_DURATION_MS / 2)));
    assert!(state.reveal() > 0.0);

    state.close_at(start + duration_ms(PICKER_PANEL_TRANSITION_DURATION_MS));
    assert!(!state.is_open());
    assert!(state.is_animating());
}

#[test]
fn bottom_margin_accounts_for_adaptive_navigation_clearance() {
    assert_eq!(
        bottom_margin(navigation::AdaptiveLayout::NavigationBar),
        FLOATING_MARGIN + tokens::component::navigation_bar::CONTAINER_HEIGHT
    );
    assert_eq!(
        bottom_margin(navigation::AdaptiveLayout::NavigationRail),
        FLOATING_MARGIN
    );
    assert_eq!(
        bottom_margin_for(
            navigation::AdaptiveLayout::NavigationBar,
            navigation::CompactNavigation::ModalDrawer,
        ),
        FLOATING_MARGIN
    );
}

#[test]
fn floating_clearance_tracks_the_revealed_picker_panel() {
    let start = Instant::now();
    let mut state = State::new();

    assert_eq!(state.floating_clearance(), PALETTE_BUTTON_SIZE);

    state.open_at(start);
    let _ = state.advance(start + duration_ms(PICKER_PANEL_TRANSITION_DURATION_MS));

    assert_eq!(
        state.floating_clearance(),
        PALETTE_BUTTON_SIZE + picker_panel_slot_height()
    );
}

#[test]
fn floating_panel_padding_keeps_reveal_above_independent_fab() {
    let padding = floating_padding(FLOATING_MARGIN, FLOATING_MARGIN + PALETTE_BUTTON_SIZE);

    assert_eq!(padding.right, FLOATING_MARGIN);
    assert_eq!(padding.bottom, FLOATING_MARGIN + PALETTE_BUTTON_SIZE);
}

#[test]
fn controller_toggle_picker_starts_panel_animation() {
    let mut controller = ThemeController::new(MaterialColor::Purple, true);

    controller.update(
        ThemeAction::TogglePicker,
        Size::new(1080.0, 980.0),
        FLOATING_MARGIN,
        Instant::now(),
    );

    assert!(controller.is_picker_open());
    assert!(controller.is_animating());
}

#[test]
fn controller_selects_color_and_closes_picker_from_action() {
    let mut controller = ThemeController::new(MaterialColor::Purple, true);
    let viewport = Size::new(1080.0, 980.0);
    let bottom_margin = FLOATING_MARGIN;
    let now = Instant::now();

    controller.update(ThemeAction::TogglePicker, viewport, bottom_margin, now);
    assert!(controller.is_picker_open());

    controller.update(
        ThemeAction::SelectColor(MaterialColor::Blue),
        viewport,
        bottom_margin,
        now,
    );

    let transition = controller
        .transition()
        .expect("selecting a different color should animate");

    assert_eq!(controller.selected_color(), MaterialColor::Blue);
    assert!(!controller.is_picker_open());
    assert_eq!(
        transition.origin(),
        swatch_center(viewport, bottom_margin, MaterialColor::Blue)
    );
}

#[test]
fn controller_dark_mode_action_uses_supplied_origin() {
    let mut controller = ThemeController::new(MaterialColor::Purple, true);
    let origin = Point::new(64.0, 512.0);
    let now = Instant::now();

    controller.update(
        ThemeAction::SetDarkMode {
            dark_mode: false,
            origin,
        },
        Size::new(1080.0, 980.0),
        FLOATING_MARGIN,
        now,
    );

    let transition = controller
        .transition()
        .expect("changing dark mode should animate");

    assert!(!controller.dark_mode());
    assert_eq!(transition.origin(), origin);
}

#[test]
fn material_colors_generate_distinct_primary_roles() {
    assert_eq!(MaterialColor::ALL.len(), 8);
    assert_eq!(
        MaterialColor::Purple.color_scheme(false).primary,
        Theme::Light.colors().primary
    );
    assert_ne!(
        MaterialColor::Blue.color_scheme(false).primary,
        Theme::Light.colors().primary
    );
    assert_ne!(
        MaterialColor::Green.color_scheme(true).primary,
        Theme::Dark.colors().primary
    );
    assert_ne!(
        MaterialColor::Blue
            .color_scheme(false)
            .surface
            .container
            .base,
        Theme::Light.colors().surface.container.base
    );
    assert_ne!(
        MaterialColor::Blue.color_scheme(false).secondary.container,
        Theme::Light.colors().secondary.container
    );
}

#[test]
fn material_colors_tint_menu_backgrounds() {
    let baseline = crate::style::menu::default(&Theme::Light);
    let blue = Theme::new("Blue", MaterialColor::Blue.color_scheme(false));
    let tinted = crate::style::menu::default(&blue);

    assert_ne!(tinted.background, baseline.background);
    assert_ne!(tinted.selected_background, baseline.selected_background);
}

#[test]
fn selected_swatch_uses_stronger_outline() {
    let theme = Theme::Light;
    let selected = swatch_style(&theme, Status::Active, MaterialColor::Blue, true);
    let unselected = swatch_style(&theme, Status::Active, MaterialColor::Blue, false);

    assert_eq!(selected.border.width, SELECTED_SWATCH_OUTLINE_WIDTH);
    assert_eq!(unselected.border.width, SWATCH_OUTLINE_WIDTH);
}

#[test]
fn swatch_centers_track_picker_layout() {
    let viewport = Size::new(1080.0, 980.0);
    let bottom_margin = FLOATING_MARGIN;
    let purple = swatch_center(viewport, bottom_margin, MaterialColor::Purple);
    let blue = swatch_center(viewport, bottom_margin, MaterialColor::Blue);
    let yellow = swatch_center(viewport, bottom_margin, MaterialColor::Yellow);

    assert_eq!(blue.x - purple.x, SWATCH_TARGET_SIZE + PICKER_PANEL_SPACING);
    assert_eq!(
        yellow.y - purple.y,
        SWATCH_TARGET_SIZE + PICKER_PANEL_SPACING
    );
    assert!(purple.x < palette_center(viewport, bottom_margin).x);
}

#[test]
fn picker_panel_reveal_height_clamps_to_slot_height() {
    assert_eq!(picker_panel_reveal_height(-1.0), 0.0);
    assert_eq!(picker_panel_reveal_height(0.0), 0.0);
    assert_eq!(
        picker_panel_reveal_height(1.0),
        picker_panel_height() + PICKER_PANEL_SPACING
    );
    assert_eq!(
        picker_panel_reveal_height(2.0),
        picker_panel_height() + PICKER_PANEL_SPACING
    );
}

#[test]
fn reveal_overlay_uses_android_style_thresholds() {
    assert_eq!(percent_past_threshold(0.5, 0.5), 0.0);
    assert_eq!(percent_past_threshold(1.0, 0.5), 1.0);
    assert_eq!(reveal_gradient_end_alpha(1.0), 0.0);
    assert_eq!(
        reveal_gradient_end_alpha(THEME_REVEAL_EDGE_FADE_THRESHOLD),
        1.0
    );
    assert!(reveal_gradient_end_alpha(0.80) > reveal_gradient_end_alpha(0.95));
    assert_eq!(reveal_start_fill_alpha(1.0), 0.0);
    assert!(reveal_start_fill_alpha(0.40) > reveal_start_fill_alpha(0.80));
}

#[test]
fn reveal_blur_is_strongest_mid_transition() {
    assert!(reveal_blur_ratio(0.5) > reveal_blur_ratio(0.1));
    assert!(reveal_blur_ratio(0.5) > reveal_blur_ratio(0.9));
    assert!(reveal_blur_width(1000.0, 0.5) > reveal_blur_width(1000.0, 0.0));
}