import { render , screen , waitFor } from '@testing-library/react' ; import userEvent from '@testing-library/user-event' ; import SchemaDefinition from './SchemaDefinition' ; const getProps = ( fixtureId ) : any => { return require ( `./__fixtures__/SchemaDefinition/${ fixtureId }.json` ) as any ; } ; const onActivePathChangeMock = jest . fn ( ) ; const setValueMock = jest . fn ( ) ; const scrollIntoViewMock = jest . fn ( ) ; window . HTMLElement . prototype . scrollIntoView = scrollIntoViewMock ; const defaultProps = { isRequired : false , isExpanded : true , path : 'currentPath' , onActivePathChange : onActivePathChangeMock , setValue : setValueMock , } ; describe ( 'SchemaDefinition' , ( ) => { afterEach ( ( ) => { jest . resetAllMocks ( ) ; } ) ; it ( 'creates snapshot' , ( ) => { const { asFragment } = render ( < SchemaDefinition { ... getProps ( '1' ) } { ... defaultProps } / > ) ; expect ( asFragment ( ) ) . toMatchSnapshot ( ) ; } ) ; describe ( 'Render' , ( ) => { it ( 'renders component - type: string' , ( ) => { const props = getProps ( '2' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'Copy path to clipboard' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Phone' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Default' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'value' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Type' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'string' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Annotations' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'this is a description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Format' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Pattern' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Min length' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '7' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Max length' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '12' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Enum' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders component - type: integer' , ( ) => { const props = getProps ( '3' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'Sample' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Default' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '2' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Type' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'integer' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Annotations' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'this is a description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Min' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '0' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Max' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '100' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Exclusive min' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Exclusive max' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'true' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Enum' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders component - type: object' , ( ) => { const props = getProps ( '4' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'Scanner configuration' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Type' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'object' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Annotations' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'this is a description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Properties' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByRole ( 'listitem' ) ) . toHaveLength ( 3 ) ; expect ( screen . getByText ( 'Enum' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders component - type: array' , ( ) => { const props = getProps ( '5' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'title' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Type' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'array' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByText ( 'Default' ) ) . toHaveLength ( 2 ) ; expect ( screen . getByText ( '(please expand for more details)' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Annotations' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'this is a description' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Items' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByText ( '[string]' ) ) . toHaveLength ( 2 ) ; expect ( screen . getAllByText ( '(unique)' ) ) . toHaveLength ( 2 ) ; expect ( screen . getByText ( 'Min items' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '2' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Max items' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '6' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Enum' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'calls setActivePathMock' , ( ) => { const props = getProps ( '6' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } isExpanded = { false } / > ) ; expect ( screen . queryByText ( 'Annotations' ) ) . toBeNull ( ) ; expect ( screen . queryByText ( 'Constraints' ) ) . toBeNull ( ) ; const btn = screen . getByRole ( 'button' , { name : /Show detail/ } ) ; userEvent . click ( btn ) ; expect ( onActivePathChangeMock ) . toHaveBeenCalledTimes ( 1 ) ; expect ( onActivePathChangeMock ) . toHaveBeenCalledWith ( 'currentPath' ) ; } ) ; it ( 'renders ENUM' , ( ) => { const props = getProps ( '7' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'Enum' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByRole ( 'listitem' ) ) . toHaveLength ( 7 ) ; expect ( screen . getByText ( 'trace' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'debug' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'info' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'warn' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'error' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'fatal' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'panic' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders REQUIRED label' , ( ) => { const props = getProps ( '8' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } isRequired / > ) ; expect ( screen . getByText ( 'Required' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Required' ) ) . toHaveClass ( 'bg-success' ) ; } ) ; it ( 'renders value with different options' , ( ) => { const props = getProps ( '9' ) ; const { rerender } = render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; const select = screen . getByDisplayValue ( 'Option 1' ) ; expect ( select ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'object' ) ) . toBeInTheDocument ( ) ; userEvent . selectOptions ( select , '2' ) ; expect ( setValueMock ) . toHaveBeenCalledTimes ( 1 ) ; expect ( setValueMock ) . toHaveBeenCalledWith ( { active : 2 , combinationType : 'anyOf' , error : false , options : [ { additionalProperties : false , type : 'object' } , { additionalProperties : false , properties : { agentGroupId : { description : 'Agent group ID from Management Console (hover over an agent group to see its ID)' , type : 'number' , } , agentNamePrefix : { description : "Prefix for each auto-registered agent's name" , type : 'string' } , cloudUrl : { description : 'Base URL of the Jitterbit Harmony Cloud' , type : 'string' } , deregisterAgentOnDrainstop : { description : 'Performs agent deregistration on drainstop/JVM shutdown (defaults to false)' , type : 'boolean' , } , password : { description : 'Encrypted password of the Agent Installer user (encrypted using JitterbitUtils)' , type : 'string' , } , retryCount : { description : 'Number of retries if agent is having issues making the call to Harmony cloud for registration (defaults to 10, valid range is 0-300)' , maximum : 300 , minimum : 0 , type : 'integer' , } , retryIntervalSeconds : { description : 'Number of seconds the agent will wait before retrying. This number doubles every retry to a maximum of 600 seconds (10 minutes). Defaults to 5, valid range 5-600.' , maximum : 600 , minimum : 5 , type : 'integer' , } , username : { description : 'Encrypted username of the Agent Installer user (encrypted using JitterbitUtils)' , type : 'string' , } , } , required : [ 'cloudUrl' , 'username' , 'password' , 'agentGroupId' ] , type : 'object' , } , { type : 'null' } , ] , } ) ; rerender ( < SchemaDefinition { ... props } { ... defaultProps } def = { { ... props . def , active : 2 } } isRequired / > ) ; expect ( screen . getByText ( 'null' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders 2 different types' , ( ) => { const props = getProps ( '10' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; const select = screen . getByRole ( 'combobox' , { name : 'Type selection' } ) ; expect ( select ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; userEvent . selectOptions ( select , 'null' ) ; expect ( screen . queryByText ( 'Constraints' ) ) . toBeNull ( ) ; } ) ; it ( 'renders link in description' , ( ) => { const props = getProps ( '11' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; const link = screen . getByText ( 'https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#resourcerequirements-v1-core' ) ; expect ( link ) . toBeInTheDocument ( ) ; expect ( link ) . toHaveClass ( 'd-inline text-secondary' ) ; expect ( link ) . toHaveAttribute ( 'rel' , 'noopener noreferrer' ) ; expect ( link ) . toHaveAttribute ( 'target' , '_blank' ) ; expect ( link ) . toHaveAttribute ( 'href' , 'https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#resourcerequirements-v1-core' ) ; } ) ; it ( 'updates combinationType' , async ( ) => { const props = getProps ( '12a' ) ; const { rerender } = render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'Raw' ) ) . toBeInTheDocument ( ) ; const updatedProps = getProps ( '12b' ) ; rerender ( < SchemaDefinition { ... updatedProps } { ... defaultProps } / > ) ; await waitFor ( ( ) => { expect ( screen . queryByText ( 'Raw' ) ) . toBeNull ( ) ; } ) ; } ) ; it ( 'renders value as null' , ( ) => { const props = getProps ( '13' ) ; render ( < SchemaDefinition { ... props } { ... defaultProps } / > ) ; expect ( screen . getByText ( 'array' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Annotations' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'List of additional environment variables that may be specified in the container' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Constraints' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( '0' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByText ( '-' ) ) . toHaveLength ( 3 ) ; } ) ; } ) ; } ) ;