Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6ea433b
Fix nonstandard type tooltips and refactor
rogermparent Jul 5, 2022
a99bcc6
Merge branch 'main' of github.com:iterative/vscode-dvc into minor-cel…
rogermparent Jul 6, 2022
fae24b4
Refactor stopPropagation event on tooltips
rogermparent Jul 6, 2022
714880b
Add generic tooltip test builder and use it for multiple data types
rogermparent Jul 6, 2022
4bfbbd3
Use more static values in tests
rogermparent Jul 6, 2022
a71be71
Add data types fixture
rogermparent Jul 6, 2022
30706ef
Add failing tests using new fixture
rogermparent Jul 6, 2022
c22f486
Rename columns and fix tooltip tests
rogermparent Jul 8, 2022
124217b
Fix grammar of rows tests
rogermparent Jul 8, 2022
efee628
Make text of columns tests similar to rows tests
rogermparent Jul 8, 2022
168376c
Merge branch 'main' into minor-cell-fix
rogermparent Jul 8, 2022
570038f
Move expectTooltipValue in only function it's used, remove module-wid…
rogermparent Jul 8, 2022
a7c944c
fix typo
rogermparent Jul 8, 2022
489eac4
Remove unnecessary abstraction
rogermparent Jul 8, 2022
74bc55c
Add interactive cell tooltip test
rogermparent Jul 8, 2022
d942f62
Change test wording
rogermparent Jul 8, 2022
b575781
Use @storybook/testing-library for Storybook play functions
rogermparent Jul 8, 2022
22b2546
Stop using screen
rogermparent Jul 8, 2022
46cbf45
Merge branch 'storybook-testing-library' into minor-cell-fix
rogermparent Jul 8, 2022
c74e3b1
Add .play to show bool tooltip on data types Storybook
rogermparent Jul 8, 2022
c638db3
Increase chromatic delay for multiview zoomed plot
rogermparent Jul 8, 2022
8112478
Further increase chromatic delay
rogermparent Jul 8, 2022
2292037
Remove chromatic delay on MultiView Zoomed plot
rogermparent Jul 12, 2022
b20d192
Remove chromatic delays
rogermparent Jul 12, 2022
db47df5
Await multiview plot
rogermparent Jul 12, 2022
31838ba
Merge branch 'main' into storybook-testing-library
rogermparent Jul 12, 2022
7ee1d49
Merge branch 'storybook-testing-library' of github.com:iterative/vsco…
rogermparent Jul 12, 2022
359008a
Merge branch 'main' into minor-cell-fix
rogermparent Jul 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions extension/src/cli/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,8 @@ export type StatusesOrAlwaysChanged = StageOrFileStatuses | 'always changed'

export type StatusOutput = Record<string, StatusesOrAlwaysChanged[]>

export type Value =
| string
| number
| boolean
| null
| number[]
| string[]
| boolean[]
type SingleValue = string | number | boolean | null
export type Value = SingleValue | SingleValue[]
Comment on lines -52 to +53
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows the Value type to hold mixed but not nested lists.


export interface ValueTreeOrError {
data?: ValueTree
Expand Down
15 changes: 13 additions & 2 deletions extension/src/experiments/columns/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,32 @@ import {
deeplyNestedOutput,
columns as deeplyNestedColumns
} from '../../test/fixtures/expShow/deeplyNested'
import {
dataTypesOutput,
columns as dataTypesColumns
} from '../../test/fixtures/expShow/dataTypes'

describe('ColumnsModel', () => {
const exampleDvcRoot = 'test'

it('should return columns that equal the columns fixture when given the output fixture', async () => {
it('should return the expected columns when given the default output fixture', async () => {
const model = new ColumnsModel('', buildMockMemento())
await model.transformAndSet(outputFixture)
expect(model.getSelected()).toStrictEqual(columnsFixture)
})

it('should return data that equal the deeply nested output fixture', async () => {
it('should return the expected columns when given the deeply nested output fixture', async () => {
const model = new ColumnsModel('', buildMockMemento())
await model.transformAndSet(deeplyNestedOutput)
expect(model.getSelected()).toStrictEqual(deeplyNestedColumns)
})

it('should return the expected columns when given the data types output fixture', async () => {
const model = new ColumnsModel('', buildMockMemento())
await model.transformAndSet(dataTypesOutput)
expect(model.getSelected()).toStrictEqual(dataTypesColumns)
})

describe('persistence', () => {
const paramsDotYamlPath = buildMetricOrParamPath(
ColumnType.PARAMS,
Expand Down
14 changes: 12 additions & 2 deletions extension/src/experiments/model/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { buildMockMemento } from '../../test/util'
import { buildMetricOrParamPath } from '../columns/paths'
import { Experiment, ColumnType } from '../webview/contract'
import { definedAndNonEmpty } from '../../util/array'
import {
dataTypesOutput,
rows as dataTypesRows
} from '../../test/fixtures/expShow/dataTypes'

jest.mock('vscode')

Expand Down Expand Up @@ -64,18 +68,24 @@ describe('ExperimentsModel', () => {
return { data }
}

it('should return rows that equal the rows fixture when given the output fixture', () => {
it('should return the expected rows when given the output fixture', () => {
const model = new ExperimentsModel('', buildMockMemento())
model.transformAndSet(outputFixture)
expect(model.getRowData()).toStrictEqual(rowsFixture)
})

it('should return data that equal the deeply nested output fixture', () => {
it('should return the expected rows when given the deeply nested output fixture', () => {
const model = new ExperimentsModel('', buildMockMemento())
model.transformAndSet(deeplyNestedOutput)
expect(model.getRowData()).toStrictEqual(deeplyNestedRows)
})

it('should return the expected rows when given the data types output fixture', () => {
const model = new ExperimentsModel('', buildMockMemento())
model.transformAndSet(dataTypesOutput)
expect(model.getRowData()).toStrictEqual(dataTypesRows)
})

it('should continue to apply filters to new data if selection mode is set to use filters', () => {
const testPath = buildMetricOrParamPath(
ColumnType.PARAMS,
Expand Down
193 changes: 193 additions & 0 deletions extension/src/test/fixtures/expShow/dataTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import { ExperimentsOutput } from '../../../cli/reader'
import {
Column,
ColumnType,
Row,
TableData
} from '../../../experiments/webview/contract'

export const dataTypesOutput: ExperimentsOutput = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll probably add more types here, I just included what has been asked for and we can work from there- I haven't tried nested lists or objects, and null breaks the table when given but it doesn't occur in JSON.

workspace: {
baseline: {
data: {
timestamp: null,
params: {
'params.yaml': {
data: {
bool1: true,
bool2: false,
zero: 0,
negative: -123,
float: 1.9293040037155151,
string: 'string',
emptyString: '',
array: [true, false, 'string', 2]
}
}
},
queued: false,
running: false,
executor: null
}
}
},
'53c3851f46955fa3e2b8f6e1c52999acc8c9ea77': {
baseline: {
data: {
timestamp: '2020-11-21T19:58:22',
queued: false,
running: false,
executor: null,
name: 'main'
}
}
}
}

export const columns: Column[] = [
{
hasChildren: true,
label: 'params.yaml',
parentPath: ColumnType.PARAMS,
path: 'params:params.yaml',
type: ColumnType.PARAMS
},
{
hasChildren: false,
label: 'bool1',
maxStringLength: 4,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:bool1',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'bool1'],
type: ColumnType.PARAMS,
types: ['boolean']
},
{
hasChildren: false,
label: 'bool2',
maxStringLength: 5,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:bool2',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'bool2'],
type: ColumnType.PARAMS,
types: ['boolean']
},
{
hasChildren: false,
label: 'zero',
maxNumber: 0,
maxStringLength: 1,
minNumber: 0,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:zero',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'zero'],
type: ColumnType.PARAMS,
types: ['number']
},
{
hasChildren: false,
label: 'negative',
maxNumber: -123,
maxStringLength: 4,
minNumber: -123,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:negative',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'negative'],
type: ColumnType.PARAMS,
types: ['number']
},
{
hasChildren: false,
label: 'float',
maxNumber: 1.9293040037155151,
maxStringLength: 18,
minNumber: 1.9293040037155151,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:float',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'float'],
type: ColumnType.PARAMS,
types: ['number']
},
{
hasChildren: false,
label: 'string',
maxStringLength: 6,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:string',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'string'],
type: ColumnType.PARAMS,
types: ['string']
},
{
hasChildren: false,
label: 'emptyString',
maxStringLength: 0,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:emptyString',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'emptyString'],
type: ColumnType.PARAMS,
types: ['string']
},
{
hasChildren: false,
label: 'array',
maxStringLength: 19,
parentPath: 'params:params.yaml',
path: 'params:params.yaml:array',
pathArray: [ColumnType.PARAMS, 'params.yaml', 'array'],
type: ColumnType.PARAMS,
types: ['array']
}
]
export const rows: Row[] = [
{
displayColor: '#945dd6',
executor: null,
id: 'workspace',
label: 'workspace',
params: {
'params.yaml': {
array: [true, false, 'string', 2],
emptyString: '',
bool2: false,
float: 1.9293040037155151,
negative: -123,
string: 'string',
bool1: true,
zero: 0
}
},
queued: false,
running: false,
selected: true,
timestamp: null
},
{
displayColor: '#13adc7',
executor: null,
id: 'main',
label: 'main',
name: 'main',
queued: false,
running: false,
selected: true,
sha: '53c3851f46955fa3e2b8f6e1c52999acc8c9ea77',
timestamp: '2020-11-21T19:58:22'
}
]

export const dataTypesTableData: TableData = {
changes: [],
columnOrder: [],
columnWidths: {},
filteredCounts: { experiments: 0, checkpoints: 0 },
filters: [],
hasCheckpoints: false,
hasRunningExperiment: false,
sorts: [],
columns,
hasColumns: true,
rows
}

export default dataTypesTableData
70 changes: 60 additions & 10 deletions webview/src/experiments/components/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
TableData
} from 'dvc/src/experiments/webview/contract'
import { buildMetricOrParamPath } from 'dvc/src/experiments/columns/paths'
import { dataTypesTableData } from 'dvc/src/test/fixtures/expShow/dataTypes'
import { App } from './App'
import { useIsFullyContained } from './overflowHoverTooltip/useIsFullyContained'
import styles from './table/styles.module.scss'
Expand Down Expand Up @@ -613,9 +614,6 @@ describe('App', () => {
})

it('should show and hide a tooltip on mouseEnter and mouseLeave of a cell', () => {
jest
.spyOn(window, 'requestAnimationFrame')
.mockImplementation(cb => window.setTimeout(cb, 1))
render(<App />)
fireEvent(
window,
Expand All @@ -641,13 +639,11 @@ describe('App', () => {

fireEvent.mouseLeave(testParamCell, { bubbles: true })

jest.advanceTimersByTime(1)
jest.advanceTimersByTime(CELL_TOOLTIP_DELAY)
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()

jest.mocked(window.requestAnimationFrame).mockRestore()
})

it('should show a tooltip with the full number on number cells', () => {
it('should persist a cell tooltip when it is moused into', () => {
render(<App />)
fireEvent(
window,
Expand All @@ -659,13 +655,67 @@ describe('App', () => {
})
)

const testMetricCell = screen.getByText('1.9293')
fireEvent.mouseEnter(testMetricCell, { bubbles: true })
const testParamCell = screen.getByText(testParamStringValue)
fireEvent.mouseEnter(testParamCell, { bubbles: true })

jest.advanceTimersByTime(CELL_TOOLTIP_DELAY)
const tooltip = screen.getByRole('tooltip')
expect(tooltip).toBeInTheDocument()
expect(tooltip).toHaveTextContent(String(testMetricNumberValue))

fireEvent.mouseLeave(testParamCell, { bubbles: true })
fireEvent.mouseEnter(tooltip, { bubbles: true })

jest.advanceTimersByTime(CELL_TOOLTIP_DELAY)
expect(tooltip).toBeInTheDocument()
})

it('should show the expected tooltip for all data types', () => {
const expectTooltipValue: (args: {
cellLabel: string
expectedTooltipResult: string
}) => void = ({ cellLabel, expectedTooltipResult }) => {
const testParamCell = screen.getByText(cellLabel)
expect(testParamCell).toBeInTheDocument()

fireEvent.mouseEnter(testParamCell, { bubbles: true })

jest.advanceTimersByTime(CELL_TOOLTIP_DELAY)
const tooltip = screen.queryByRole('tooltip')
expect(tooltip).toHaveTextContent(expectedTooltipResult)

fireEvent.mouseLeave(testParamCell, { bubbles: true })

jest.advanceTimersByTime(CELL_TOOLTIP_DELAY)
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
}

render(<App />)
fireEvent(
window,
new MessageEvent('message', {
data: {
data: dataTypesTableData,
type: MessageToWebviewType.SET_DATA
}
})
)

expectTooltipValue({
cellLabel: '1.9293',
expectedTooltipResult: '1.9293040037155151'
})
expectTooltipValue({
cellLabel: 'true',
expectedTooltipResult: 'true'
})
expectTooltipValue({
cellLabel: 'false',
expectedTooltipResult: 'false'
})
expectTooltipValue({
cellLabel: '[true, false, string, 2]',
expectedTooltipResult: '[true, false, string, 2]'
})
})
})

Expand Down
4 changes: 4 additions & 0 deletions webview/src/experiments/components/table/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,7 @@ $badge-size: 0.85rem;
vertical-align: middle;
font-size: 0.5rem;
}

.cellTooltip {
padding: 2px 6px;
}
Loading