import React from 'react'
import { syncFetch } from 'test-helpers/syncFetch'
import globPath from 'test-helpers/globPath'
import { mountWithProviders } from 'test-helpers/mountWithTheme'
import { CREATE_ENDPOINT as JSON_CREATE_ENDPOINT } from 'api/proxy/v2/specs'
import { ENDPOINT as TOML_CREATE_ENDPOINT } from 'api/proxy/v2/ocrSpecs'
import { JobSpecFormats } from './utils'
import { Route } from 'react-router-dom'
import * as storage from 'utils/local-storage'
import New, { validate, SELECTED_FORMAT, PERSIST_SPEC } from './New'
import { ReactWrapper } from 'enzyme'
import { act } from 'react-dom/test-utils'
const switchTo = (component: ReactWrapper, format: JobSpecFormats) => {
component.find(`input[value="${format}"]`).simulate('change', {
target: { value: format },
})
}
const fillTextarea = (component: ReactWrapper, jobSpec: string) => {
return component.find(`textarea[name="jobSpec"]`).simulate('change', {
target: { value: jobSpec, name: 'jobSpec' },
})
}
describe('pages/Jobs/New', () => {
beforeEach(() => {
storage.remove(`${PERSIST_SPEC}${JobSpecFormats.JSON}`)
storage.remove(`${PERSIST_SPEC}${JobSpecFormats.TOML}`)
storage.remove(SELECTED_FORMAT)
})
it('submits JSON job spec form', async () => {
const expectedSubmit = '{"foo":"bar"}'
const submit = global.fetch.postOnce(globPath(JSON_CREATE_ENDPOINT), {})
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
fillTextarea(wrapper, expectedSubmit)
wrapper
.find('[data-testid="new-job-spec-submit"]')
.first()
.simulate('submit')
await syncFetch(wrapper)
expect(submit.lastCall()[1].body).toEqual(expectedSubmit)
})
it('submits TOML job spec form', async () => {
const expectedSubmit = 'foo="bar"'
const submit = global.fetch.postOnce(globPath(TOML_CREATE_ENDPOINT), {})
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new?format=${JobSpecFormats.TOML}`],
},
)
fillTextarea(wrapper, expectedSubmit)
wrapper
.find('[data-testid="new-job-spec-submit"]')
.first()
.simulate('submit')
await syncFetch(wrapper)
expect(submit.lastCall()[1].body).toEqual(
JSON.stringify({ toml: expectedSubmit }),
)
})
it('loads and indents JSON spec definition from search param', () => {
const expected = { foo: 'bar' }
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new?definition=${JSON.stringify(expected)}`],
},
)
expect(wrapper.text()).toContain('"foo":"bar"')
expect(wrapper.text()).toContain(`${JobSpecFormats.JSON} blob`)
expect(wrapper.text()).toContain(JSON.stringify(expected))
})
it('loads TOML spec definition from search param', () => {
const expected = '"foo"="bar"'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new?definition=${expected}`],
},
)
expect(wrapper.text()).toContain('"foo"="bar"')
expect(wrapper.text()).toContain(`${JobSpecFormats.TOML} blob`)
})
it('saves spec definition in storage', () => {
const expected = '"foo"="bar"'
const wrapper = mountWithProviders(
,
{
initialEntries: ['/jobs/new'],
},
)
fillTextarea(wrapper, expected)
expect(storage.get(`${PERSIST_SPEC}${JobSpecFormats.JSON}`)).toContain(
expected,
)
})
it('persists spec definitions when switch the format', () => {
const expectedJson = '{"foo":"bar"}'
const expectedToml = '"foo":"bar"'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
const textArea = fillTextarea(wrapper, expectedJson)
switchTo(wrapper, JobSpecFormats.TOML)
expect(textArea.text()).not.toContain(expectedJson)
textArea.simulate('change', {
target: { value: expectedToml, name: 'jobSpec' },
})
expect(textArea.text()).toContain(expectedToml)
switchTo(wrapper, JobSpecFormats.JSON)
expect(textArea.text()).toContain(expectedJson)
})
it('saves last selected spec format in a storage', () => {
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new?format=${JobSpecFormats.JSON}`],
},
)
expect(wrapper.text()).toContain(`${JobSpecFormats.JSON} blob`)
switchTo(wrapper, JobSpecFormats.TOML)
expect(wrapper.text()).toContain(`${JobSpecFormats.TOML} blob`)
expect(storage.get(SELECTED_FORMAT)).toEqual(JobSpecFormats.TOML)
switchTo(wrapper, JobSpecFormats.JSON)
expect(wrapper.text()).toContain(`${JobSpecFormats.JSON} blob`)
expect(storage.get(SELECTED_FORMAT)).toEqual(JobSpecFormats.JSON)
})
describe('validate', () => {
it('string', () => {
expect(
validate({
format: JobSpecFormats.JSON,
value: ' ',
}),
).toEqual(false)
expect(
validate({
format: JobSpecFormats.JSON,
value: '',
}),
).toEqual(false)
})
it('JSON format', () => {
expect(
validate({
format: JobSpecFormats.JSON,
value: '{"foo":"bar"}',
}),
).toEqual(true)
expect(
validate({
format: JobSpecFormats.JSON,
value: '{"foo":"bar"',
}),
).toEqual(false)
})
it('TOML format', () => {
expect(
validate({
format: JobSpecFormats.TOML,
value: '"foo"="bar"',
}),
).toEqual(true)
expect(
validate({
format: JobSpecFormats.TOML,
value: '"foo""bar"',
}),
).toEqual(false)
})
})
it('updates json preview task list', () => {
const jobSpec1 = '{"tasks":[{ "type": "Httpget"}, { "type": "Jsonparse"}]}'
const jobSpec2 =
'{"tasks":[{ "type": "Multiply"}, { "type": "Jsonparse"}, { "type": "Httpget"}]}'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
jest.useFakeTimers()
fillTextarea(wrapper, jobSpec1)
act(() => {
jest.runAllTimers()
})
wrapper.update()
const taskList = wrapper.find('[data-testid="task-list-item"]')
expect(taskList.map((task: ReactWrapper) => task.text())).toEqual([
'Httpget',
'Jsonparse',
])
jest.runAllTimers()
fillTextarea(wrapper, jobSpec2)
act(() => {
jest.runAllTimers()
})
wrapper.update()
const taskList2 = wrapper.find('[data-testid="task-list-item"]')
expect(taskList2.map((task: ReactWrapper) => task.text())).toEqual([
'Multiply',
'Jsonparse',
'Httpget',
])
})
it('updates toml preview task list', () => {
const jobSpec1 =
'observationSource = """ ds [type=ds]; ds_parse [type=ds_parse]; """'
const jobSpec2 =
'observationSource = """ ds [type=ds]; ds_parse [type=ds_parse]; ds_multiply [type=ds_multiply]; """'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
jest.useFakeTimers()
fillTextarea(wrapper, jobSpec1)
act(() => {
jest.runAllTimers()
})
wrapper.update()
const taskList = wrapper.find('[data-testid^="task-list-id-"]')
expect(
taskList.map((task: ReactWrapper) => task.prop('data-testid')),
).toEqual(['task-list-id-ds_parse', 'task-list-id-ds'])
fillTextarea(wrapper, jobSpec2)
act(() => {
jest.runAllTimers()
})
wrapper.update()
const taskList2 = wrapper.find('[data-testid^="task-list-id-"]')
expect(
taskList2.map((task: ReactWrapper) => task.prop('data-testid')),
).toEqual([
'task-list-id-ds_multiply',
'task-list-id-ds_parse',
'task-list-id-ds',
])
})
it('shows "Tasks not found" on job spec errors', () => {
const jsonSpec = '{"tasks":[{ "type": Httpget}, { "type": "Jsonparse"}]}'
const tomlSpec =
'observationSource = "" ds [type=ds]; ds_parse [type=ds_parse]; """'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
jest.useFakeTimers()
fillTextarea(wrapper, jsonSpec)
act(() => {
jest.runAllTimers()
})
wrapper.update()
expect(wrapper.text()).toContain('Tasks not found')
fillTextarea(wrapper, tomlSpec)
act(() => {
jest.runAllTimers()
})
wrapper.update()
expect(wrapper.text()).toContain('Tasks not found')
})
it('shows "Tasks not found" on empty job spec', () => {
const jsonSpec = '{"tasks":[]}'
const tomlSpec = 'observationSource = "" """'
const wrapper = mountWithProviders(
,
{
initialEntries: [`/jobs/new`],
},
)
fillTextarea(wrapper, jsonSpec)
expect(wrapper.text()).toContain('Tasks not found')
fillTextarea(wrapper, tomlSpec)
expect(wrapper.text()).toContain('Tasks not found')
})
})