Skip to content

Commit

Permalink
fix type errors and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
koji committed Mar 14, 2024
1 parent e3ae47a commit b6444d4
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 233 deletions.
14 changes: 7 additions & 7 deletions app/src/assets/localization/en/protocol_details.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"connection_status": "connection status",
"creation_method": "creation method",
"deck_view": "Deck View",
"default_value":"Default Value",
"default_value": "Default Value",
"delete_protocol_perm": "{{name}} and its run history will be permanently deleted.",
"delete_protocol": "Delete Protocol",
"delete_this_protocol": "Delete this protocol?",
Expand All @@ -26,17 +26,17 @@
"liquid_name": "liquid name",
"liquids_not_in_protocol": "no liquids are specified for this protocol",
"liquids": "liquids",
"listed_values_are_view_only":"Listed values are view-only",
"listed_values_are_view_only": "Listed values are view-only",
"location": "location",
"modules": "modules",
"name":"Name",
"name": "Name",
"no_available_robots_found": "No available robots found",
"no_parameters":"No parameters specified in this protocol",
"no_parameters": "No parameters specified in this protocol",
"no_summary": "no summary specified for this protocol.",
"not_connected": "not connected",
"not_in_protocol": "no {{section}} is specified for this protocol",
"org_or_author": "org/author",
"parameters":"Parameters",
"parameters": "Parameters",
"pipette_aspirate_count_description": "individual aspirate commands per pipette.",
"pipette_aspirate_count": "{{pipette}} aspirate count",
"pipette_dispense_count_description": "individual dispense commands per pipette.",
Expand All @@ -49,7 +49,7 @@
"protocol_outdated_app_analysis": "This protocol's analysis is out of date. It may produce different results if you run it now.",
"python_api_version": "Python API {{version}}",
"quantity": "Quantity",
"range":"Range",
"range": "Range",
"read_less": "read less",
"read_more": "read more",
"right_mount": "right mount",
Expand All @@ -62,7 +62,7 @@
"sending": "Sending",
"show_in_folder": "Show in folder",
"slot": "Slot {{slotName}}",
"start_setup_customize_values":"Start setup to customize values",
"start_setup_customize_values": "Start setup to customize values",
"start_setup": "Start setup",
"successfully_sent": "Successfully sent",
"total_volume": "total volume",
Expand Down
2 changes: 1 addition & 1 deletion app/src/atoms/InlineNotification/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export function InlineNotification(
>
{fullHeading}
</span>
{message !=null && fullmessage}
{message != null && fullmessage}
</StyledText>
</Flex>
{onCloseClick && (
Expand Down
139 changes: 63 additions & 76 deletions app/src/organisms/ProtocolDetails/ProtocolParameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,17 @@ import {
import { StyledText } from '../../atoms/text'
import { Banner } from '../../atoms/Banner'

import type { ProtocolAnalysisOutput } from '@opentrons/shared-data'

// Note (03/13/2024: kk) this will be replaced with custom hooks return
import exampleRunTimeParameters from './exampleRunTimeParameters.json'

// Note (03/13/2024: kk) probably the following if/type will be moved more better place later
interface Choice {
displayName: string
value: string
}

type DefaultValueType = string | number | boolean

interface RunTimeParameter {
displayName: string
variableName: string
description: string
suffix: string | null
min?: number
max?: number
choices?: Choice[]
default: DefaultValueType
}
import type { RunTimeParameter } from '@opentrons/shared-data'

interface ProtocolParametersProps {
analysis: ProtocolAnalysisOutput | null
runTimeParameters: RunTimeParameter[]
}

export function ProtocolParameters({
analysis,
runTimeParameters,
}: ProtocolParametersProps): JSX.Element {
const { t } = useTranslation('protocol_details')

// ToDo (03/13/2024:kk) the sample data will be replaces analysis data
const isUsingSampleData = true
const { runTimeParameters } = isUsingSampleData
? exampleRunTimeParameters
: { runTimeParameters: [] }

return (
<Flex>
{runTimeParameters.length > 0 ? (
Expand Down Expand Up @@ -90,40 +62,49 @@ function ProtocolParameterItems({
}: ProtocolParameterItemsProps): JSX.Element {
const { t } = useTranslation('protocol_details')

const formattedValue = (parameter: RunTimeParameter): string => {
if (typeof parameter.default === 'boolean') {
return parameter.default ? 'On' : 'Off'
}

if (typeof parameter.default === 'number') {
return parameter.default.toString()
}

if (parameter.choices != null) {
const choice = parameter.choices.find(
choice => choice.value === parameter.default
)
if (choice != null) {
return choice.displayName
}
const formattedValue = (runTimeParameter: RunTimeParameter): string => {
const { type, default: defaultValue } = runTimeParameter
switch (type) {
case 'int':
case 'float':
return defaultValue.toString()
case 'boolean':
return Boolean(defaultValue) ? 'On' : 'Off'
case 'str':
if ('choices' in runTimeParameter && runTimeParameter.choices != null) {
const choice = runTimeParameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}

const formatRange = (obj: RunTimeParameter): string => {
if (
Object.prototype.hasOwnProperty.call(obj, 'min') &&
Object.prototype.hasOwnProperty.call(obj, 'max')
) {
return `${obj.min}-${obj.max}`
const formatRange = (
runTimeParameter: RunTimeParameter,
minMax: string
): string => {
const { type, default: defaultValue } = runTimeParameter

switch (type) {
case 'int':
case 'float':
return minMax
case 'boolean':
return 'On, off'
case 'str':
if (defaultValue === 'left' || defaultValue === 'right') {
return 'Left, right'
} else {
return 'Multi'
}
default:
return ''
}
if (typeof obj.default === 'boolean') {
return 'On, off'
}
if (Object.prototype.hasOwnProperty.call(obj, 'choices')) {
return 'Multi'
}
return ''
}

return (
Expand All @@ -134,22 +115,28 @@ function ProtocolParameterItems({
<StyledTableHeader>{t('range')}</StyledTableHeader>
</thead>
<tbody>
{runTimeParameters.map((parameter: RunTimeParameter, index: number) => (
<StyledTableRow
isLast={index === runTimeParameters.length - 1}
key={`runTimeParameter-${index}`}
>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{parameter.displayName}</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{formattedValue(parameter)}</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{formatRange(parameter)}</StyledText>
</StyledTableCell>
</StyledTableRow>
))}
{runTimeParameters.map((parameter: RunTimeParameter, index: number) => {
const min = 'min' in parameter ? parameter.min : 0
const max = 'max' in parameter ? parameter.max : 0
return (
<StyledTableRow
isLast={index === runTimeParameters.length - 1}
key={`runTimeParameter-${index}`}
>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{parameter.displayName}</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{formattedValue(parameter)}</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">
{formatRange(parameter, `${min}-${max}`)}
</StyledText>
</StyledTableCell>
</StyledTableRow>
)
})}
</tbody>
</StyledTable>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,125 @@ import { screen } from '@testing-library/react'

import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { storedProtocolData } from '../../../redux/protocol-storage/__fixtures__'
import { ProtocolParameters } from '../ProtocolParameters'

import type { ProtocolAnalysisOutput } from '@opentrons/shared-data'
import type { RunTimeParameter } from '@opentrons/shared-data'

const mockRunTimeParameter: RunTimeParameter[] = [
{
displayName: 'Trash Tips',
variableName: 'TIP_TRASH',
description:
'to throw tip into the trash or to not throw tip into the trash',
type: 'boolean',
default: true,
},
{
displayName: 'EtoH Volume',
variableName: 'ETOH_VOLUME',
description: '70% ethanol volume',
type: 'float',
suffix: 'mL',
min: 1.5,
max: 10.0,
default: 6.5,
},
{
displayName: 'Default Module Offsets',
variableName: 'DEFAULT_OFFSETS',
description: 'default module offsets for temp, H-S, and none',
type: 'str',
choices: [
{
displayName: 'No offsets',
value: 'none',
},
{
displayName: 'temp offset',
value: '1',
},
{
displayName: 'heater-shaker offset',
value: '2',
},
],
default: 'none',
},
{
displayName: 'pipette mount',
variableName: 'mont',
description: 'pipette mount',
type: 'str',
choices: [
{
displayName: 'Left',
value: 'left',
},
{
displayName: 'Right',
value: 'right',
},
],
default: 'left',
},
]

const render = (props: React.ComponentProps<typeof ProtocolParameters>) => {
return renderWithProviders(<ProtocolParameters {...props} />, {
i18nInstance: i18n,
})
}

const mockMostRecentAnalysis: ProtocolAnalysisOutput = storedProtocolData.mostRecentAnalysis as ProtocolAnalysisOutput

describe('ProtocolParameters', () => {
let props: React.ComponentProps<typeof ProtocolParameters>

beforeEach(() => {
props = {
analysis: mockMostRecentAnalysis,
runTimeParameters: mockRunTimeParameter,
}
})

it('should render banner', () => {
afterEach(() => {
vi.clearAllMocks()
})

it('should render banner when RunTimeParameters are existing', () => {
render(props)
screen.getByText('Listed values are view-only')
screen.getByText('Start setup to customize values')
})

it('should render table header', () => {})
it('should render table header', () => {
render(props)
screen.getByText('Name')
screen.getByText('Default Value')
screen.getByText('Range')
})

it('should render parameters default information', () => {
render(props)
screen.getByText('Trash Tips')
screen.getByText('On')
screen.getByText('On, off')

it('should render parameters default information', () => {})
screen.getByText('EtoH Volume')
screen.getByText('6.5')
screen.getByText('1.5-10')

it('should render empty display when protocol does not have any parameter', () => {})
screen.getByText('Default Module Offsets')
screen.getByText('No offsets')
screen.getByText('Multi')

screen.getByText('pipette mount')
screen.getByText('Left')
screen.getByText('Left, right')
})

it('should render empty display when protocol does not have any parameter', () => {
props = {
runTimeParameters: [],
}
render(props)
screen.getByText('No parameters specified in this protocol')
})
})
Loading

0 comments on commit b6444d4

Please sign in to comment.