import { screen , waitFor , within } from '@testing-library/react' ; import userEvent from '@testing-library/user-event' ; import { renderApp , selectExplorerNode } from '../test-utils' ; test ( 'show slider with two thumbs' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const thumbs = await screen . findAllByRole ( 'slider' ) ; expect ( thumbs ) . toHaveLength ( 2 ) ; expect ( thumbs [ 0 ] ) . toHaveAttribute ( 'aria-valuenow' , '20' ) ; expect ( thumbs [ 1 ] ) . toHaveAttribute ( 'aria-valuenow' , '81' ) ; } ) ; test ( 'show tooltip on hover' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; const tooltip = screen . getByRole ( 'dialog' , { hidden : true } ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-expanded' , 'false' ) ; expect ( tooltip ) . not . toBeVisible ( ) ; userEvent . hover ( editBtn ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-expanded' , 'true' ) ; expect ( tooltip ) . toBeVisible ( ) ; userEvent . unhover ( editBtn ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-expanded' , 'false' ) ; expect ( tooltip ) . not . toBeVisible ( ) ; userEvent . hover ( editBtn ) ; userEvent . keyboard ( '{Escape}' ) ; expect ( tooltip ) . not . toBeVisible ( ) ; } ) ; test ( 'show min/max and data range in tooltip' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; userEvent . hover ( editBtn ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; expect ( minInput ) . toHaveValue ( '−9.5e+1' ) ; expect ( maxInput ) . toHaveValue ( '4e+2' ) ; expect ( minInput ) . toHaveAttribute ( 'title' , '-95' ) ; expect ( maxInput ) . toHaveAttribute ( 'title' , '400' ) ; const range = screen . getByText ( /Data range/ ) ; expect ( range ) . toBeVisible ( ) ; expect ( within ( range ) . getByTitle ( '-95' ) ) . toHaveTextContent ( '−9.5e+1' ) ; expect ( within ( range ) . getByTitle ( '400' ) ) . toHaveTextContent ( '4e+2' ) ; } ) ; test ( 'update domain when moving thumbs (with keyboard)' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const minThumb = await screen . findByRole ( 'slider' , { name : /min/ } ) ; userEvent . hover ( minThumb ) ; const visArea = await screen . findByRole ( 'figure' ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; minThumb . focus ( ) ; userEvent . keyboard ( '{ArrowLeft}' ) ; expect ( minInput ) . toHaveValue ( '−1.04671e+2' ) ; expect ( within ( visArea ) . getByText ( '−1.047e+2' ) ) . toBeInTheDocument ( ) ; userEvent . keyboard ( '{ArrowLeft>5/}' ) ; expect ( minInput ) . toHaveValue ( '−2.30818e+2' ) ; expect ( within ( visArea ) . getByText ( '−2.308e+2' ) ) . toBeInTheDocument ( ) ; expect ( minThumb ) . toHaveAttribute ( 'aria-valuenow' , '20' ) ; expect ( maxInput ) . toHaveValue ( '4e+2' ) ; const maxThumb = await screen . findByRole ( 'slider' , { name : /max/ } ) ; maxThumb . focus ( ) ; userEvent . keyboard ( '{PageDown}' ) ; expect ( maxInput ) . toHaveValue ( '5.72182e+1' ) ; expect ( within ( visArea ) . getByText ( '5.722e+1' ) ) . toBeInTheDocument ( ) ; userEvent . keyboard ( '{PageUp}' ) ; expect ( maxInput ) . toHaveValue ( '2.52142e+2' ) ; expect ( within ( visArea ) . getByText ( '2.521e+2' ) ) . toBeInTheDocument ( ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '81' ) ; expect ( minInput ) . toHaveValue ( '−2.30818e+2' ) ; maxThumb . blur ( ) ; } ) ; test ( 'allow editing bounds manually' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-pressed' , 'false' ) ; userEvent . click ( editBtn ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-expanded' , 'true' ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; const applyBtn = screen . getByRole ( 'button' , { name : 'Apply min' } ) ; const cancelBtn = screen . getByRole ( 'button' , { name : 'Cancel min' } ) ; expect ( applyBtn ) . toBeEnabled ( ) ; expect ( cancelBtn ) . toBeEnabled ( ) ; await waitFor ( ( ) => expect ( minInput ) . toHaveFocus ( ) ) ; userEvent . type ( minInput , '1' ) ; expect ( minInput ) . toHaveValue ( '−9.5e+11' ) ; const visArea = await screen . findByRole ( 'figure' ) ; expect ( within ( visArea ) . getByText ( '−9.5e+1' ) ) . toBeInTheDocument ( ) ; userEvent . click ( cancelBtn ) ; expect ( minInput ) . toHaveValue ( '−9.5e+1' ) ; expect ( applyBtn ) . toBeDisabled ( ) ; expect ( cancelBtn ) . toBeDisabled ( ) ; userEvent . type ( minInput , '1' ) ; userEvent . click ( applyBtn ) ; expect ( within ( visArea ) . getByText ( '−9.5e+11' ) ) . toBeInTheDocument ( ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; userEvent . clear ( maxInput ) ; userEvent . type ( maxInput , '100000{enter}' ) ; expect ( maxInput ) . toHaveValue ( '1e+5' ) ; expect ( within ( visArea ) . getByText ( '1e+5' ) ) . toBeInTheDocument ( ) ; expect ( editBtn ) . toHaveAttribute ( 'aria-pressed' , 'false' ) ; } ) ; test ( 'clamp domain in symlog scale' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; userEvent . click ( editBtn ) ; const minThumb = screen . getByRole ( 'slider' , { name : /min/ } ) ; const maxThumb = screen . getByRole ( 'slider' , { name : /max/ } ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; userEvent . clear ( minInput ) ; userEvent . type ( minInput , '-1e+1000{enter}' ) ; expect ( minInput ) . toHaveValue ( '−8.98847e+307' ) ; expect ( minThumb ) . toHaveAttribute ( 'aria-valuenow' , '1' ) ; userEvent . clear ( maxInput ) ; userEvent . type ( maxInput , '1e+1000{enter}' ) ; expect ( maxInput ) . toHaveValue ( '8.98847e+307' ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '100' ) ; maxThumb . focus ( ) ; userEvent . keyboard ( '{ArrowLeft}' ) ; expect ( maxInput ) . toHaveValue ( '5.40006e+301' ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '99' ) ; maxThumb . blur ( ) ; } ) ; test ( 'show min/max autoscale toggles in tooltip (pressed by default)' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; userEvent . hover ( editBtn ) ; expect ( screen . getByText ( 'Autoscale' ) ) . toBeVisible ( ) ; const minBtn = screen . getByRole ( 'button' , { name : 'Min' } ) ; const maxBtn = screen . getByRole ( 'button' , { name : 'Max' } ) ; expect ( minBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; expect ( maxBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; } ) ; test ( 'control min/max autoscale behaviour' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const minThumb = await screen . findByRole ( 'slider' , { name : /min/ } ) ; userEvent . hover ( minThumb ) ; const minBtn = screen . getByRole ( 'button' , { name : 'Min' } ) ; const maxBtn = screen . getByRole ( 'button' , { name : 'Max' } ) ; const maxInput = screen . getByLabelText ( 'max' ) ; minThumb . focus ( ) ; userEvent . keyboard ( '{ArrowRight}' ) ; expect ( minBtn ) . toHaveAttribute ( 'aria-pressed' , 'false' ) ; expect ( maxBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; userEvent . type ( maxInput , '0{enter}' ) ; expect ( maxInput ) . toHaveValue ( '4e+20' ) ; expect ( maxBtn ) . toHaveAttribute ( 'aria-pressed' , 'false' ) ; userEvent . click ( maxBtn ) ; expect ( maxBtn ) . toHaveAttribute ( 'aria-pressed' , 'true' ) ; expect ( minBtn ) . toHaveAttribute ( 'aria-pressed' , 'false' ) ; await waitFor ( ( ) => expect ( maxInput ) . toHaveValue ( '4e+2' ) ) ; } ) ; test ( 'handle empty domain' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; userEvent . click ( editBtn ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; const minThumb = screen . getByRole ( 'slider' , { name : /min/ } ) ; const maxThumb = screen . getByRole ( 'slider' , { name : /max/ } ) ; userEvent . clear ( minInput ) ; userEvent . type ( minInput , '400{enter}' ) ; expect ( minThumb ) . toHaveAttribute ( 'aria-valuenow' , '58' ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '58' ) ; const visArea = await screen . findByRole ( 'figure' ) ; expect ( within ( visArea ) . getByText ( '−∞' ) ) . toBeInTheDocument ( ) ; expect ( within ( visArea ) . getByText ( '+∞' ) ) . toBeInTheDocument ( ) ; maxThumb . focus ( ) ; userEvent . keyboard ( '{ArrowLeft}' ) ; expect ( minInput ) . toHaveValue ( '3.97453e+2' ) ; expect ( maxInput ) . toHaveValue ( '3.97453e+2' ) ; expect ( minThumb ) . toHaveAttribute ( 'aria-valuenow' , '58' ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '58' ) ; userEvent . keyboard ( '{ArrowRight}' ) ; expect ( maxInput ) . toHaveValue ( '3.99891e+2' ) ; expect ( minThumb ) . toHaveAttribute ( 'aria-valuenow' , '20' ) ; expect ( maxThumb ) . toHaveAttribute ( 'aria-valuenow' , '81' ) ; maxThumb . blur ( ) ; } ) ; test ( 'handle min > max' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/nx_process/nx_data' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; userEvent . click ( editBtn ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; userEvent . clear ( minInput ) ; userEvent . type ( minInput , '500{enter}' ) ; expect ( minInput ) . toHaveValue ( '5e+2' ) ; expect ( maxInput ) . toHaveValue ( '4e+2' ) ; expect ( screen . getByText ( /Min greater than max/ ) ) . toHaveTextContent ( /falling back to data range/ ) ; const visArea = await screen . findByRole ( 'figure' ) ; expect ( within ( visArea ) . getByText ( '−9.5e+1' ) ) . toBeInTheDocument ( ) ; expect ( within ( visArea ) . getByText ( '4e+2' ) ) . toBeInTheDocument ( ) ; const minBtn = screen . getByRole ( 'button' , { name : 'Min' } ) ; userEvent . click ( minBtn ) ; expect ( screen . queryByText ( /Min greater than max/ ) ) . not . toBeInTheDocument ( ) ; } ) ; test ( 'handle min or max <= 0 in log scale' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/image' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; await expect ( screen . findByRole ( 'button' , { name : 'Log' } ) ) . resolves . toBeVisible ( ) ; userEvent . click ( editBtn ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; userEvent . clear ( minInput ) ; userEvent . type ( minInput , '-5{enter}' ) ; expect ( minInput ) . toHaveValue ( '−5e+0' ) ; expect ( screen . getByText ( /Custom min invalid/ ) ) . toHaveTextContent ( /falling back to data min/ ) ; const visArea = await screen . findByRole ( 'figure' ) ; expect ( within ( visArea ) . getByText ( '9.996e-1' ) ) . toBeInTheDocument ( ) ; userEvent . clear ( maxInput ) ; userEvent . type ( maxInput , '-10{enter}' ) ; expect ( screen . queryByText ( /Custom min invalid/ ) ) . not . toBeInTheDocument ( ) ; expect ( screen . queryByText ( /Custom max invalid/ ) ) . not . toBeInTheDocument ( ) ; expect ( screen . getByText ( /Min greater than max/ ) ) . toHaveTextContent ( /falling back to data range/ ) ; } ) ; test ( 'handle min <= 0 with custom max fallback in log scale' , async ( ) => { await renderApp ( ) ; await selectExplorerNode ( 'nexus_entry/image' ) ; const editBtn = await screen . findByRole ( 'button' , { name : 'Edit domain' } ) ; await expect ( screen . findByRole ( 'button' , { name : 'Log' } ) ) . resolves . toBeVisible ( ) ; userEvent . click ( editBtn ) ; const minInput = screen . getByLabelText ( 'min' ) ; const maxInput = screen . getByLabelText ( 'max' ) ; userEvent . clear ( minInput ) ; userEvent . type ( minInput , '-5{enter}' ) ; userEvent . clear ( maxInput ) ; userEvent . type ( maxInput , '1e-4{enter}' ) ; expect ( screen . getByText ( /Custom min invalid/ ) ) . toHaveTextContent ( /falling back to custom max/ ) ; const visArea = await screen . findByRole ( 'figure' ) ; expect ( within ( visArea ) . getByText ( '−∞' ) ) . toBeInTheDocument ( ) ; expect ( within ( visArea ) . getByText ( '+∞' ) ) . toBeInTheDocument ( ) ; } ) ;