// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/

//! Tests for searching `Frame` functionality.

#![cfg_attr(rustfmt, rustfmt_skip)]

// -------------------------------------------------------------------------------------------------

extern crate cognitive_qualia as qualia;
extern crate cognitive_frames as frames;

mod common;

use qualia::{Direction, Position, Size, SurfaceId};
use frames::Frame;
use frames::Geometry::{Horizontal, Stacked, Vertical};
use frames::Searching;
use common::{assertions, layouts};

// -------------------------------------------------------------------------------------------------

/// Test finding buildable frame.
///
///  - Buildable for leaf should be its parent.
///  - Buildable for container should be itself.
#[test]
fn test_find_buildable() {
    let mut r = Frame::new_root();
    let mut c = Frame::new_container(Vertical);
    let mut l = Frame::new_leaf(SurfaceId::new(1), Stacked);

    r.append(&mut c);
    c.append(&mut l);

    assertions::assert_frame_equal_exact(&l.find_buildable().unwrap(), &c);
    assertions::assert_frame_equal_exact(&c.find_buildable().unwrap(), &c);
}

// -------------------------------------------------------------------------------------------------

/// Test finding top frame.
///
///  - Top for any normal frame should be first parent with mode not `Leaf` and not `Container`.
///  - Top for any special frame should be itself.
#[test]
fn test_find_top() {
    let mut r = Frame::new_root();
    let mut s1 = Frame::new_workspace("".to_string(), Stacked, true);
    let mut s2 = Frame::new_workspace("".to_string(), Stacked, true);
    let mut c1 = Frame::new_container(Horizontal);
    let mut c2 = Frame::new_container(Vertical);
    let mut l = Frame::new_leaf(SurfaceId::new(1), Stacked);

    r.append(&mut s1);
    s1.append(&mut s2);
    s2.append(&mut c1);
    c1.append(&mut c2);
    c2.append(&mut l);

    assertions::assert_frame_equal_exact(&r.find_top().unwrap(), &r);
    assertions::assert_frame_equal_exact(&s1.find_top().unwrap(), &s1);
    assertions::assert_frame_equal_exact(&s2.find_top().unwrap(), &s2);
    assertions::assert_frame_equal_exact(&c1.find_top().unwrap(), &s2);
    assertions::assert_frame_equal_exact(&c2.find_top().unwrap(), &s2);
    assertions::assert_frame_equal_exact(&l.find_top().unwrap(), &s2);
}

// -------------------------------------------------------------------------------------------------

/// Check finding frame with sid.
#[test]
fn test_find_with_sid() {
    let (r, _, _, s, v1, v2, v3, h1, h2, h3, s1, s2, s3) = layouts::make_simple_frames_appending();

    assert!(&r.find_with_sid(SurfaceId::new(666)).is_none());

    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(11)).unwrap(), &v1);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(12)).unwrap(), &v2);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(13)).unwrap(), &v3);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(21)).unwrap(), &h1);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(22)).unwrap(), &h2);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(23)).unwrap(), &h3);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(31)).unwrap(), &s1);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(32)).unwrap(), &s2);
    assertions::assert_frame_equal_exact(&r.find_with_sid(SurfaceId::new(33)).unwrap(), &s3);

    assert!(&s.find_with_sid(SurfaceId::new(11)).is_none());
    assert!(&s.find_with_sid(SurfaceId::new(12)).is_none());
    assert!(&s.find_with_sid(SurfaceId::new(22)).is_none());

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find contiguous frame on the same level.
///
///  - 0*South from A should be A.
///  - 1*South from A should be B.
///  - 1*North from B should be A.
///  - 1*South from B should be None.
///
///     ┌─────┐
///     │  A  │
///     ├─────┤
///     │  B  │
///     └─────┘
///
#[test]
fn test_find_contiguous_on_the_same_level_one_further() {
    let mut r = Frame::new_root();
    let mut v = Frame::new_container(Vertical);
    let mut a = Frame::new_leaf(SurfaceId::new(1), Stacked);
    let mut b = Frame::new_leaf(SurfaceId::new(2), Stacked);
    r.append(&mut v);
    v.append(&mut a);
    v.append(&mut b);

    // 0*South from A should be A
    let p = a.find_contiguous(Direction::South, 0);
    assertions::assert_frame_equal_exact(&p.unwrap(), &a);

    // 1*South from A should be B
    let p = a.find_contiguous(Direction::South, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &b);

    // 1*North from B should be A
    let p = b.find_contiguous(Direction::North, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &a);

    // 1*South from B should be None;
    let p = b.find_contiguous(Direction::South, 1);
    assert!(p.is_none());

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find contiguous frame on the same level.
///
/// - 3*East from B should be E.
/// - 5*West from F should be A.
///
///     ┌─────┬─────┬─────┬─────┬─────┬─────┐
///     │  A  │  B  │  C  │  D  │  E  │  F  │
///     └─────┴─────┴─────┴─────┴─────┴─────┘
///
#[test]
fn test_find_contiguous_on_the_same_level_many_further() {
    let mut r = Frame::new_root();
    let mut h = Frame::new_container(Horizontal);
    let mut a = Frame::new_leaf(SurfaceId::new(1), Stacked);
    let mut b = Frame::new_leaf(SurfaceId::new(2), Stacked);
    let mut c = Frame::new_leaf(SurfaceId::new(3), Stacked);
    let mut d = Frame::new_leaf(SurfaceId::new(4), Stacked);
    let mut e = Frame::new_leaf(SurfaceId::new(5), Stacked);
    let mut f = Frame::new_leaf(SurfaceId::new(6), Stacked);
    r.append(&mut h);
    h.append(&mut a);
    h.append(&mut b);
    h.append(&mut c);
    h.append(&mut d);
    h.append(&mut e);
    h.append(&mut f);

    // 3*West from B should be E
    let p = b.find_contiguous(Direction::East, 3);
    assertions::assert_frame_equal_exact(&p.unwrap(), &e);

    // 5*East from F should be A
    let p = f.find_contiguous(Direction::West, 5);
    assertions::assert_frame_equal_exact(&p.unwrap(), &a);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find contiguous frame on the second level and going from vertical to horizontal.
///
///  - 1*East from B should be D.
///  - 1*East from A should be BC.
///  - 1*West from C should be A.
///  - 2*East from A should be D
///  - 1*Trunk from C should be BC.
///
///
///     ┌───────┬───────┬───────┐
///     │       │┌─────┐│       │
///     │       ││  B  ││       │
///     │   A   │├─────┤│   D   │
///     │       ││  C  ││       │
///     │       │└─────┘│       │
///     └───────┴───────┴───────┘
///
#[test]
fn test_find_contiguous_on_the_second_level_across() {
    let mut r    = Frame::new_root();
    let mut abcd = Frame::new_container(Horizontal);
    let mut bc   = Frame::new_container(Vertical);
    let mut a    = Frame::new_leaf(SurfaceId::new(1), Stacked);
    let mut b    = Frame::new_leaf(SurfaceId::new(2), Stacked);
    let mut c    = Frame::new_leaf(SurfaceId::new(3), Stacked);
    let mut d    = Frame::new_leaf(SurfaceId::new(4), Stacked);
    r.append(&mut abcd);
    bc.append(&mut b);
    bc.append(&mut c);
    abcd.append(&mut a);
    abcd.append(&mut bc);
    abcd.append(&mut d);

    // 1*East from B should be D
    let p = b.find_contiguous(Direction::East, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &d);

    // 1*West from A should be BC
    let p = a.find_contiguous(Direction::East, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &bc);

    // 1*East from C should be A
    let p = c.find_contiguous(Direction::West, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &a);

    // 2*West from A should be D
    let p = a.find_contiguous(Direction::East, 2);
    assertions::assert_frame_equal_exact(&p.unwrap(), &d);

    // 1*Trunk from C should be BC
    let p = c.find_contiguous(Direction::Up, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &bc);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find contiguous frame on the third level and going from horizontal to horizontal
///
///  - 1*East from C should be D.
///
///
///     ┌─────────────────────┬─────┐
///     │┌─────┬─────────────┐│     │
///     ││     │┌─────┬─────┐││     │
///     ││  A  ││  B  │  C  │││  D  │
///     ││     │└─────┴─────┘││     │
///     │└─────┴─────────────┘│     │
///     └─────────────────────┴─────┘
///
#[test]
fn test_find_contiguous_on_the_third_level_along() {
    let mut r    = Frame::new_root();
    let mut abcd = Frame::new_container(Horizontal);
    let mut abc  = Frame::new_container(Horizontal);
    let mut bc   = Frame::new_container(Horizontal);
    let mut a    = Frame::new_leaf(SurfaceId::new(1), Stacked);
    let mut b    = Frame::new_leaf(SurfaceId::new(2), Stacked);
    let mut c    = Frame::new_leaf(SurfaceId::new(3), Stacked);
    let mut d    = Frame::new_leaf(SurfaceId::new(4), Stacked);
    r.append(&mut abcd);
    abcd.append(&mut abc);
    abcd.append(&mut d);
    abc.append(&mut a);
    abc.append(&mut bc);
    bc.append(&mut b);
    bc.append(&mut c);

    // 1*East from C should be D
    let p = c.find_contiguous(Direction::East, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &d);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find contiguous when searching in direction perpendicular to screen.
///
///
///     ┏━━━━━━━━━━━━━━━━━━━━━━━┓
///     ┃┌───────┬─────────────┐┃
///     ┃│┌─────┐│┌─────┬─────┐│┃
///     ┃││ ABC │││  D  │  E  ││┃
///     ┃│└─────┘│└─────┴─────┘│┃
///     ┃└───────┴─────────────┘┃
///     ┠───────────────────────┨
///     ┃┌─────────────────┐    ┃
///     ┃│         F       │    ┃
///     ┃└─────────────────┘    ┃
///     ┗━━━━━━━━━━━━━━━━━━━━━━━┛
///
#[test]
fn test_find_contiguous_in_perpendicular_direction() {
    let (r, _, _, _, a, b, c, _, _, _) = layouts::make_positioned_for_searching();

    // 1*End from A should be B
    let p = a.find_contiguous(Direction::End, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &b);

    // 2*End from A should be C
    let p = a.find_contiguous(Direction::End, 2);
    assertions::assert_frame_equal_exact(&p.unwrap(), &c);

    // 1*Begin from C should be B
    let p = c.find_contiguous(Direction::Begin, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &b);

    // 2*Begin from C should be A
    let p = c.find_contiguous(Direction::Begin, 2);
    assertions::assert_frame_equal_exact(&p.unwrap(), &a);

    // 3*End from A should be None
    let p = a.find_contiguous(Direction::End, 3);
    assert!(p.is_none());

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDEF and point is inside ABC and ABC is stacked, with A as most top
/// frame, A should be found.
///
///
///     ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
///     ┃┌──────────┬─────────────┐┃
///     ┃│ ▛▀▀▀▀▀▀▜ │┌─────┬─────┐│┃
///     ┃│ ▌ ABC ×▐ ││  D  │  E  ││┃
///     ┃│ ▙▄▄▄▄▄▄▟ │└─────┴─────┘│┃
///     ┃└──────────┴─────────────┘┃
///     ┠──────────────────────────┨
///     ┃┌─────────────────┐       ┃
///     ┃│         F       │       ┃
///     ┃└─────────────────┘       ┃
///     ┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛
///
#[test]
fn test_find_stacked_pointed_inside() {
    let (r, _, _, _, a, _, _, _, _, _) = layouts::make_positioned_for_searching();

    let point = Position::new(10, 10);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &a);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDEF and point is inside D and D is inside flat frame, D should be
/// found.
///
///
///     ┏━━━━━━━━━━━━━━━━━━━━━━━━┓     ┏━━━━━━━━━━━━━━━━━━━━━━━━┓
///     ┃┌───────┬──────────────┐┃     ┃┌───────┬──────────────┐┃
///     ┃│┌─────┐│ ▛▀▀▀▀▀▜─────┐│┃     ┃│┌─────┐│ ┌─────▛▀▀▀▀▀▜│┃
///     ┃││ ABC ││ ▌  D ×▐  E  ││┃     ┃││ ABC ││ │  D  ▌  E ×▐│┃
///     ┃│└─────┘│ ▙▄▄▄▄▄▟─────┘│┃     ┃│└─────┘│ └─────▙▄▄▄▄▄▟│┃
///     ┃└───────┴──────────────┘┃     ┃└───────┴──────────────┘┃
///     ┠────────────────────────┨     ┠────────────────────────┨
///     ┃┌────────────────┐      ┃     ┃┌────────────────┐      ┃
///     ┃│        F       │      ┃     ┃│        F       │      ┃
///     ┃└────────────────┘      ┃     ┃└────────────────┘      ┃
///     ┗━━━━━━━━━━━━━━━━━━━━━━━━┛     ┗━━━━━━━━━━━━━━━━━━━━━━━━┛
///
#[test]
fn test_find_flat_pointed_inside() {
    let (r, _, _, _, _, _, _, d, e, _) = layouts::make_positioned_for_searching();

    let point = Position::new(50, 10);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &d);

    let point = Position::new(80, 10);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &e);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDEF and point is outside ABCDEF and directly above
/// ABC and ABC is stacked, with A as most top frame, A should be found.
///
///
///           ×
///     ┏━━━━━━━━━━━━━━━━━━━━━━━━━┓
///     ┃┌─────────┬─────────────┐┃
///     ┃│ ▛▀▀▀▀▀▜ │┌─────┬─────┐│┃
///     ┃│ ▌ ABC ▐ ││  D  │  E  ││┃
///     ┃│ ▙▄▄▄▄▄▟ │└─────┴─────┘│┃
///     ┃└─────────┴─────────────┘┃
///     ┠─────────────────────────┨
///     ┃┌────────────────┐       ┃
///     ┃│        F       │       ┃
///     ┃└────────────────┘       ┃
///     ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛
///
#[test]
fn test_find_stacked_pointed_ouside() {
    let (r, _, _, _, a, _, _, _, _, _) = layouts::make_positioned_for_searching();

    let point = Position::new(20, -10);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &a);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDEF and point is outside ABCDEF and directly above
/// D and D is inside flat frame, D should be found.
///
///
///                   ×
///     ┏━━━━━━━━━━━━━━━━━━━━━━━━┓
///     ┃┌───────┬──────────────┐┃
///     ┃│┌─────┐│ ▛▀▀▀▀▀▜─────┐│┃
///     ┃││ ABC ││ ▌  D  ▐  E  ││┃
///     ┃│└─────┘│ ▙▄▄▄▄▄▟─────┘│┃
///     ┃└───────┴──────────────┘┃
///     ┠────────────────────────┨
///     ┃┌────────────────┐      ┃
///     ┃│        F       │      ┃
///     ┃└────────────────┘      ┃
///     ┗━━━━━━━━━━━━━━━━━━━━━━━━┛
///
#[test]
fn test_find_flat_pointed_outside() {
    let (r, _, _, _, _, _, _, d, _, _) = layouts::make_positioned_for_searching();

    let point = Position::new(60, -10);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &d);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDE and point is outside ABCDE and below D, but
/// inside another frame not contained in ABCDE, D should be found.
///
///
///     ┌────────────────────────┐
///     │┏━━━━━━━┯━━━━━━━━━━━━━━┓│
///     │┃┌─────┐│ ▛▀▀▀▀▀▜─────┐┃│
///     │┃│ ABC ││ ▌  D  ▐  E  │┃│
///     │┃└─────┘│ ▙▄▄▄▄▄▟─────┘┃│
///     │┗━━━━━━━┷━━━━━━━━━━━━━━┛│
///     ├────────────────────────┤
///     │┌────────────────┐      │
///     ││        F   ×   │      │
///     │└────────────────┘      │
///     └────────────────────────┘
///
#[test]
fn test_find_frame_over_another() {
    let (r, abcde, _, _, _, _, _, d, _, _) = layouts::make_positioned_for_searching();

    let point = Position::new(50, 70);
    let p = abcde.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &d);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// When searching inside ABCDEF and point is outside of any frame contained in
/// ABCDEF, ABCDEF should be found.
///
///
///     ▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌
///     ▐ ┌───────┬─────────────┐ ▌
///     ▐ │┌─────┐│┌─────┬─────┐│ ▌
///     ▐ ││ ABC │││  D  │  E  ││ ▌
///     ▐ │└─────┘│└─────┴─────┘│ ▌
///     ▐ └───────┴─────────────┘ ▌
///     ▐─────────────────────────▌
///     ▐ ┌────────────────┐      ▌
///     ▐ │        F       │  ×   ▌
///     ▐ └────────────────┘      ▌
///     ▐▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▌
///
#[test]
fn test_find_empty_space() {
    let (r, _, _, _, _, _, _, _, _, _) = layouts::make_positioned_for_searching();

    let point = Position::new(80, 80);
    let p = r.find_pointed(point);
    assertions::assert_frame_equal_exact(&p, &r);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find adjacent frames.
///
/// - 1*South from A should be C
/// - 1*South from C should be E
/// - 2*South from A should be F
/// - 1*South from CD should be F
/// - 1*North from AB should be None
///
///
///     ┌─────────────────────┐
///     │┌─────────────┬─────┐│
///     ││      A      │  B  ││
///     │└─────────────┴─────┘│
///     ├─────────────────────┤
///     │┌─────────┬─────────┐│
///     ││    C    │    D    ││
///     │└─────────┴─────────┘│
///     ├─────────────────────┤
///     │┌─────┬─────────────┐│
///     ││  E  │      F      ││
///     │└─────┴─────────────┘│
///     └─────────────────────┘
///
#[test]
fn test_find_adjacent_frames() {
    let mut r  = Frame::new_root();
    let mut v  = Frame::new_container(Vertical);
    let mut ab = Frame::new_container(Horizontal);
    let mut cd = Frame::new_container(Horizontal);
    let mut ef = Frame::new_container(Horizontal);
    let mut a  = Frame::new_leaf(SurfaceId::new(1), Stacked);
    let mut b  = Frame::new_leaf(SurfaceId::new(2), Stacked);
    let mut c  = Frame::new_leaf(SurfaceId::new(3), Stacked);
    let mut d  = Frame::new_leaf(SurfaceId::new(4), Stacked);
    let mut e  = Frame::new_leaf(SurfaceId::new(5), Stacked);
    let mut f  = Frame::new_leaf(SurfaceId::new(6), Stacked);
    r.append(&mut v);
    v.append(&mut ab);
    v.append(&mut cd);
    v.append(&mut ef);
    ab.append(&mut a);
    ab.append(&mut b);
    cd.append(&mut c);
    cd.append(&mut d);
    ef.append(&mut e);
    ef.append(&mut f);
    r. set_plumbing_position_and_size(Position::new( 0,  0), Size::new(100, 10));
    v. set_plumbing_position_and_size(Position::new( 0,  0), Size::new(100, 10));
    ab.set_plumbing_position_and_size(Position::new( 0,  0), Size::new(100, 10));
    cd.set_plumbing_position_and_size(Position::new( 0, 10), Size::new(100, 10));
    ef.set_plumbing_position_and_size(Position::new( 0, 20), Size::new(100, 10));
    a. set_plumbing_position_and_size(Position::new( 0,  0), Size::new( 70, 10));
    b. set_plumbing_position_and_size(Position::new(70,  0), Size::new( 30, 10));
    c. set_plumbing_position_and_size(Position::new( 0,  0), Size::new( 50, 10));
    d. set_plumbing_position_and_size(Position::new(50,  0), Size::new( 50, 10));
    e. set_plumbing_position_and_size(Position::new( 0,  0), Size::new( 30, 10));
    f. set_plumbing_position_and_size(Position::new(30,  0), Size::new( 70, 10));

    // 1*South from A should be C
    let p = a.find_adjacent(Direction::South, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &c);

    // 1*South from C should be E
    let p = c.find_adjacent(Direction::South, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &e);

    // 2*South from A should be F
    let p = a.find_adjacent(Direction::South, 2);
    assertions::assert_frame_equal_exact(&p.unwrap(), &f);

    // 1*South from CD should be F
    let p = cd.find_adjacent(Direction::South, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &f);

    // 1*North from AB should be None
    let p = ab.find_adjacent(Direction::North, 1);
    assert!(p.is_none());

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Find adjacent frames in direction perpendicular to screen.
///
/// - 1*End from A should be B
/// - 2*End from A should be C
///
///
///     ┌───────────────────────┐
///     │┌───────┬─────────────┐│
///     ││┌─────┐│┌─────┬─────┐││
///     │││ ABC │││  D  │  E  │││
///     ││└─────┘│└─────┴─────┘││
///     │└───────┴─────────────┘│
///     ├───────────────────────┤
///     │┌────────────────┐     │
///     ││        F       │     │
///     │└────────────────┘     │
///     └───────────────────────┘
///
#[test]
fn test_find_adjacent_stacked_frames() {
    let (r, _, _, _, a, b, c, _, _, _) = layouts::make_positioned_for_searching();

    // 1*End from A should be B
    let p = a.find_adjacent(Direction::End, 1);
    assertions::assert_frame_equal_exact(&p.unwrap(), &b);

    // 2*End from A should be C
    let p = a.find_adjacent(Direction::End, 2);
    assertions::assert_frame_equal_exact(&p.unwrap(), &c);

    r.destroy();
}

// -------------------------------------------------------------------------------------------------

/// Tests finding workspace.
#[test]
fn test_finding_workspace() {
    let (r, _, _, _, _, _, _, w22, _) = layouts::make_simple_with_workspaces();

    let matcher = |frame: &Frame| { frame.get_mode().is_workspace() && frame.get_title() == "22" };
    let found = r.find(&matcher).unwrap();
    assert!(found.equals_exact(&w22));

    r.destroy();
}

// -------------------------------------------------------------------------------------------------