//! Context preservation.
//!
//! The source library invokes `fn` with the `this` of the call site. Rust has
//! no `this`. The equivalent is a closure that captures the state it should
//! operate on. These tests prove the wrapped function mutates the right state in
//! both trailing and leading modes, which is what the context tests assert.

mod common;

use std::convert::Infallible;
use std::sync::atomic::{AtomicI32, Ordering};
use std::sync::Arc;

use debounce_promise::Debounce;

use common::sleep;

#[tokio::test]
async fn maintains_the_context_of_the_function() {
    let foo = Arc::new(AtomicI32::new(1));
    let captured = Arc::clone(&foo);
    let debounced = Debounce::latest(move |_: ()| {
        let captured = Arc::clone(&captured);
        async move {
            captured.fetch_add(1, Ordering::SeqCst);
            Ok::<_, Infallible>(())
        }
    })
    .wait_ms(10)
    .build();

    let call = debounced.call(());
    sleep(20).await;
    assert_eq!(foo.load(Ordering::SeqCst), 2);
    drop(call);
}

#[tokio::test]
async fn maintains_the_context_when_leading() {
    let foo = Arc::new(AtomicI32::new(1));
    let captured = Arc::clone(&foo);
    let debounced = Debounce::latest(move |_: ()| {
        let captured = Arc::clone(&captured);
        async move {
            captured.fetch_add(1, Ordering::SeqCst);
            Ok::<_, Infallible>(())
        }
    })
    .wait_ms(10)
    .leading(true)
    .build();

    let _ = debounced.call(()).await;
    assert_eq!(foo.load(Ordering::SeqCst), 2);
}
