Skip to content

Commit

Permalink
Add Multiple Y Field Selection to Plot Wizard (#4787)
Browse files Browse the repository at this point in the history
  • Loading branch information
julieg18 authored Oct 11, 2023
1 parent 2d408ac commit f05ffa0
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 57 deletions.
20 changes: 10 additions & 10 deletions extension/src/fileSystem/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,8 @@ describe('addPlotToDvcYamlFile', () => {
addPlotToDvcYamlFile('/', {
template: 'simple',
title: 'Simple Plot',
x: { file: 'data.json', key: 'epochs' },
y: { file: 'data.json', key: 'accuracy' }
x: { 'data.json': 'epochs' },
y: { 'data.json': 'accuracy' }
})

expect(mockedWriteFileSync).toHaveBeenCalledWith(
Expand Down Expand Up @@ -654,8 +654,8 @@ describe('addPlotToDvcYamlFile', () => {
addPlotToDvcYamlFile('/', {
template: 'simple',
title: 'simple_plot',
x: { file: 'data.json', key: 'epochs' },
y: { file: 'acc.json', key: 'accuracy' }
x: { 'data.json': 'epochs' },
y: { 'acc.json': 'accuracy' }
})

expect(mockedWriteFileSync).toHaveBeenCalledWith(
Expand All @@ -673,8 +673,8 @@ describe('addPlotToDvcYamlFile', () => {
addPlotToDvcYamlFile('/', {
template: 'simple',
title: 'Simple Plot',
x: { file: 'data.json', key: 'epochs' },
y: { file: 'data.json', key: 'accuracy' }
x: { 'data.json': 'epochs' },
y: { 'data.json': 'accuracy' }
})

mockDvcYamlContent.splice(7, 0, ...mockPlotYamlContent)
Expand All @@ -696,8 +696,8 @@ describe('addPlotToDvcYamlFile', () => {
addPlotToDvcYamlFile('/', {
template: 'simple',
title: 'Simple Plot',
x: { file: 'data.json', key: 'epochs' },
y: { file: 'data.json', key: 'accuracy' }
x: { 'data.json': 'epochs' },
y: { 'data.json': 'accuracy' }
})

expect(mockedWriteFileSync).toHaveBeenCalledWith(
Expand Down Expand Up @@ -734,8 +734,8 @@ describe('addPlotToDvcYamlFile', () => {
addPlotToDvcYamlFile('/', {
template: 'simple',
title: 'simple_plot',
x: { file: 'data.json', key: 'epochs' },
y: { file: 'data.json', key: 'accuracy' }
x: { 'data.json': 'epochs' },
y: { 'data.json': 'accuracy' }
})

expect(mockedWriteFileSync).toHaveBeenCalledWith(
Expand Down
9 changes: 7 additions & 2 deletions extension/src/fileSystem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,16 @@ const loadYamlAsDoc = (

const getPlotYamlObj = (plot: PlotConfigData) => {
const { x, y, template, title } = plot

const yFiles = Object.keys(y)
const [xFile, xKey] = Object.entries(x)[0]
const oneFileUsed = yFiles.length === 1 && yFiles[0] === xFile

return {
[title]: {
template,
x: x.file === y.file ? x.key : { [x.file]: x.key },
y: { [y.file]: y.key }
x: oneFileUsed ? xKey : x,
y
}
}
}
Expand Down
144 changes: 117 additions & 27 deletions extension/src/pipeline/quickPick.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { QuickPickItemKind } from 'vscode'
import { pickPlotConfiguration } from './quickPick'
import { getInput } from '../vscode/inputBox'
import { pickFiles } from '../vscode/resourcePicker'
import { quickPickOne, quickPickValue } from '../vscode/quickPick'
import {
quickPickOne,
quickPickValue,
quickPickManyValues
} from '../vscode/quickPick'
import { getFileExtension, loadDataFiles } from '../fileSystem'
import { Title } from '../vscode/title'
import { Toast } from '../vscode/toast'
Expand All @@ -13,6 +17,7 @@ const mockedGetFileExt = jest.mocked(getFileExtension)
const mockedGetInput = jest.mocked(getInput)
const mockedQuickPickOne = jest.mocked(quickPickOne)
const mockedQuickPickValue = jest.mocked(quickPickValue)
const mockedQuickPickValues = jest.mocked(quickPickManyValues)
const mockedToast = jest.mocked(Toast)
const mockedShowError = jest.fn()
mockedToast.showError = mockedShowError
Expand Down Expand Up @@ -259,9 +264,13 @@ describe('pickPlotConfiguration', () => {
{ data: mockValidData, file: '/file.json' }
])
mockedQuickPickOne.mockResolvedValueOnce('simple')
mockedQuickPickValue
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
.mockResolvedValueOnce({ file: 'file.json', key: 'prob' })
mockedQuickPickValue.mockResolvedValueOnce({
file: 'file.json',
key: 'actual'
})
mockedQuickPickValues.mockResolvedValueOnce([
{ file: 'file.json', key: 'prob' }
])
mockedGetInput.mockResolvedValueOnce('Simple Plot')

const result = await pickPlotConfiguration('/')
Expand All @@ -281,8 +290,7 @@ describe('pickPlotConfiguration', () => {
],
'Pick a Plot Template'
)
expect(mockedQuickPickValue).toHaveBeenNthCalledWith(
1,
expect(mockedQuickPickValue).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
Expand All @@ -294,8 +302,7 @@ describe('pickPlotConfiguration', () => {
],
{ title: Title.SELECT_PLOT_X_METRIC }
)
expect(mockedQuickPickValue).toHaveBeenNthCalledWith(
2,
expect(mockedQuickPickValues).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
Expand All @@ -315,27 +322,33 @@ describe('pickPlotConfiguration', () => {
expect(result).toStrictEqual({
template: 'simple',
title: 'Simple Plot',
x: { file: 'file.json', key: 'actual' },
y: { file: 'file.json', key: 'prob' }
x: { 'file.json': 'actual' },
y: { 'file.json': 'prob' }
})
})

it('should let the user pick a x field and y field from multiple files', async () => {
mockedPickFiles.mockResolvedValueOnce(['/file.json', '/file2.json'])
mockedLoadDataFiles.mockResolvedValueOnce([
{ data: mockValidData, file: '/file.json' },
{ data: mockValidData, file: '/file2.json' }
{
data: mockValidData,
file: '/file2.json'
}
])
mockedQuickPickOne.mockResolvedValueOnce('simple')
mockedGetInput.mockResolvedValueOnce('simple_plot')
mockedQuickPickValue
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
.mockResolvedValueOnce({ file: 'file2.json', key: 'prob' })
mockedQuickPickValue.mockResolvedValueOnce({
file: 'file.json',
key: 'actual'
})
mockedQuickPickValues.mockResolvedValueOnce([
{ file: 'file2.json', key: 'prob' }
])

const result = await pickPlotConfiguration('/')

expect(mockedQuickPickValue).toHaveBeenNthCalledWith(
1,
expect(mockedQuickPickValue).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
Expand All @@ -354,8 +367,7 @@ describe('pickPlotConfiguration', () => {
],
{ title: Title.SELECT_PLOT_X_METRIC }
)
expect(mockedQuickPickValue).toHaveBeenNthCalledWith(
2,
expect(mockedQuickPickValues).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
Expand All @@ -378,8 +390,80 @@ describe('pickPlotConfiguration', () => {
expect(result).toStrictEqual({
template: 'simple',
title: 'simple_plot',
x: { file: 'file.json', key: 'actual' },
y: { file: 'file2.json', key: 'prob' }
x: { 'file.json': 'actual' },
y: { 'file2.json': 'prob' }
})
})

it('should let the user pick multiple y fields', async () => {
mockedPickFiles.mockResolvedValueOnce(['/file.json', '/file2.json'])
mockedLoadDataFiles.mockResolvedValueOnce([
{ data: mockValidData, file: '/file.json' },
{
data: mockValidData.map((value, ind) => ({ ...value, step: ind })),
file: '/file2.json'
}
])
mockedQuickPickOne.mockResolvedValueOnce('simple')
mockedGetInput.mockResolvedValueOnce('simple_plot')
mockedQuickPickValue.mockResolvedValueOnce({
file: 'file.json',
key: 'actual'
})
mockedQuickPickValues.mockResolvedValueOnce([
{ file: 'file2.json', key: 'prob' },
{ file: 'file2.json', key: 'actual' },
{ file: 'file2.json', key: 'step' }
])

const result = await pickPlotConfiguration('/')

expect(mockedQuickPickValue).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
label: 'file.json',
value: undefined
},
{ label: 'actual', value: { file: 'file.json', key: 'actual' } },
{ label: 'prob', value: { file: 'file.json', key: 'prob' } },
{
kind: QuickPickItemKind.Separator,
label: 'file2.json',
value: undefined
},
{ label: 'actual', value: { file: 'file2.json', key: 'actual' } },
{ label: 'prob', value: { file: 'file2.json', key: 'prob' } },
{ label: 'step', value: { file: 'file2.json', key: 'step' } }
],
{ title: Title.SELECT_PLOT_X_METRIC }
)
expect(mockedQuickPickValues).toHaveBeenCalledWith(
[
{
kind: QuickPickItemKind.Separator,
label: 'file.json',
value: undefined
},
{ label: 'prob', value: { file: 'file.json', key: 'prob' } },
{
kind: QuickPickItemKind.Separator,
label: 'file2.json',
value: undefined
},
{ label: 'actual', value: { file: 'file2.json', key: 'actual' } },
{ label: 'prob', value: { file: 'file2.json', key: 'prob' } },
{ label: 'step', value: { file: 'file2.json', key: 'step' } }
],
{
title: Title.SELECT_PLOT_Y_METRIC
}
)
expect(result).toStrictEqual({
template: 'simple',
title: 'simple_plot',
x: { 'file.json': 'actual' },
y: { 'file2.json': ['prob', 'actual', 'step'] }
})
})

Expand Down Expand Up @@ -419,13 +503,12 @@ describe('pickPlotConfiguration', () => {
])
mockedQuickPickOne.mockResolvedValueOnce('simple')
mockedGetInput.mockResolvedValueOnce('simple_plot')
mockedQuickPickValue
.mockResolvedValueOnce('actual')
.mockResolvedValueOnce(undefined)
mockedQuickPickValue.mockResolvedValueOnce('actual')
mockedQuickPickValues.mockResolvedValueOnce(undefined)

const result = await pickPlotConfiguration('/')

expect(mockedQuickPickValue).toHaveBeenCalledTimes(2)
expect(mockedQuickPickValues).toHaveBeenCalledTimes(1)
expect(result).toStrictEqual(undefined)
})

Expand All @@ -435,9 +518,16 @@ describe('pickPlotConfiguration', () => {
{ data: mockValidData, file: 'file.json' }
])
mockedQuickPickOne.mockResolvedValueOnce('linear')
mockedQuickPickValue
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
.mockResolvedValueOnce({ file: 'file.json', key: 'prob' })
mockedQuickPickValue.mockResolvedValueOnce({
file: 'file.json',
key: 'actual'
})
mockedQuickPickValues.mockResolvedValueOnce([
{
file: 'file.json',
key: 'prob'
}
])
mockedGetInput.mockResolvedValueOnce(undefined)

const result = await pickPlotConfiguration('/')
Expand Down
Loading

0 comments on commit f05ffa0

Please sign in to comment.