You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
5.6 KiB
106 lines
5.6 KiB
import Wizard from '@/views/survey/components/SurveyCreateWizard.vue'
|
|
import SurveyList from '@/views/survey/index.vue'
|
|
import { surveyCopyDraft } from '@/utils/surveyCopy'
|
|
import { show, save } from '@/api/survey/evaluations'
|
|
import { index as questionIndex } from '@/api/survey/index'
|
|
|
|
jest.mock('@/api/survey/evaluations', () => ({ show: jest.fn(), save: jest.fn(), index: jest.fn(), destroy: jest.fn(), qrCode: jest.fn() }))
|
|
jest.mock('@/api/survey/index', () => ({ index: jest.fn(), save: jest.fn(), destroy: jest.fn(), reorder: jest.fn() }))
|
|
|
|
const source = {
|
|
id: 10, title: '培训问卷', desc: '<p>说明</p>', course_id: '11', type_id: '3', audience_course_ids: [11, 12],
|
|
start_time: '2026-12-01 00:00:00', end_time: '2026-12-31 23:59:59', status: 1,
|
|
course_content_evaluation_forms_count: 20, qrCodeData: 'source-qr'
|
|
}
|
|
const questions = [
|
|
{ id: 20, course_content_evaluation_id: 10, field: 'attend', name: '是否参加', edit_input: 'radio', sort: 1, select_item: [{ key: 'yes', value: '是' }] },
|
|
{ id: 21, field: 'group', name: '组合题', edit_input: 'multi_dimension', sort: 2, dimensions: [{ field: 'count', edit_input: 'number', config: { min: 0 } }], config: { visible_when: { field: 'attend', values: ['yes'], required_values: ['yes'] } } }
|
|
]
|
|
function wizard() {
|
|
return {
|
|
...Wizard.data(), ...Wizard.methods,
|
|
base: { requestToForm: (data, form) => Object.fromEntries(Object.keys(form).map(key => [key, data[key] === undefined ? form[key] : data[key]])) },
|
|
compareTime: () => false,
|
|
$emit: jest.fn(), $message: jest.fn(), $refs: { dialog: { reset: jest.fn() } }, $nextTick: callback => callback()
|
|
}
|
|
}
|
|
describe('Copy a questionnaire into the new-survey dialog', () => {
|
|
beforeEach(() => jest.resetAllMocks())
|
|
|
|
it('opens an independent draft with all editable basics and deep-copied question settings, without saving', async() => {
|
|
show.mockResolvedValue(source)
|
|
questionIndex.mockResolvedValue({ data: questions })
|
|
const state = wizard()
|
|
await state.openCopy(10, [{ id: 11, is_arrange: 0 }])
|
|
expect(state.isShow).toBe(true)
|
|
expect(state.type).toBe('add')
|
|
expect(state.id).toBe('')
|
|
expect(state.form.id).toBeUndefined()
|
|
expect(state.form.title).toBe('培训问卷(副本)')
|
|
expect(state.form.status).toBe(0)
|
|
expect(state.form.desc).toBe(source.desc)
|
|
expect(state.form.audience_course_ids).toEqual([11, 12])
|
|
expect(state.form.start_time).toBe(source.start_time)
|
|
expect(state.form.qrCodeData).toBeUndefined()
|
|
expect(state.form.course_content_evaluation_forms_count).toBeUndefined()
|
|
expect(state.questionList[0].id).not.toBe(20)
|
|
state.questionList[1].dimensions[0].config.min = 5
|
|
state.questionList[1].config.visible_when.values.push('no')
|
|
expect(questions[1].dimensions[0].config.min).toBe(0)
|
|
expect(questions[1].config.visible_when.values).toEqual(['yes'])
|
|
expect(save).not.toHaveBeenCalled()
|
|
Wizard.watch.isShow.call(state, false)
|
|
expect(state.copyFromId).toBe('')
|
|
expect(state.questionList).toEqual([])
|
|
})
|
|
|
|
it('creates the copy only on save, reloads new question IDs and updates that same new survey on subsequent saves', async() => {
|
|
show.mockResolvedValue(source)
|
|
questionIndex.mockResolvedValueOnce({ data: questions }).mockResolvedValueOnce({ data: questions.map(question => ({ ...question, id: question.id + 100, course_content_evaluation_id: 100 })) })
|
|
const state = wizard()
|
|
await state.openCopy(10, [{ id: 11, is_arrange: 0 }])
|
|
save.mockResolvedValue({ ...source, id: 100, status: 0 })
|
|
await state.submit()
|
|
expect(save.mock.calls[0][0].copy_from_id).toBe(10)
|
|
expect(save.mock.calls[0][0].id).toBeUndefined()
|
|
expect(state.id).toBe(100)
|
|
expect(state.questionLinkIds.course_content_evaluation_id).toBe(100)
|
|
expect(state.questionList[0].id).toBe(120)
|
|
state.form.title = '修改新问卷标题'
|
|
await state.submit()
|
|
expect(save.mock.calls[1][0].id).toBe(100)
|
|
expect(save.mock.calls[1][0].copy_from_id).toBeUndefined()
|
|
expect(questionIndex).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('restores selected schedules without retaining the original questionnaire link', async() => {
|
|
show.mockResolvedValue({ ...source, course_content_id: '8,9' })
|
|
questionIndex.mockResolvedValue({ data: questions })
|
|
const state = wizard()
|
|
state.filterSurveys = async() => { state.courseContentList = [{ id: 8 }, { id: 9 }, { id: 10 }] }
|
|
await state.openCopy(10, [{ id: 11, is_arrange: 1 }])
|
|
expect(state.courseContentList.map(item => !!item.checked)).toEqual([true, true, false])
|
|
expect(state.selectedCourseSchedules.map(item => item.id)).toEqual([8, 9])
|
|
expect(state.questionLinkIds.course_content_evaluation_id).toBe('')
|
|
})
|
|
|
|
it('does not open or create a copy when loading fails and unlocks the list copy menu for retry', async() => {
|
|
const state = wizard()
|
|
show.mockRejectedValue(new Error('missing source'))
|
|
questionIndex.mockResolvedValue({ data: [] })
|
|
await expect(state.openCopy(10, [])).rejects.toThrow('missing source')
|
|
expect(state.isShow).toBe(false)
|
|
expect(save).not.toHaveBeenCalled()
|
|
const list = { copyingSurveyId: null, courseList: [], $refs: { SurveyCreateWizard: state }, $message: { error: jest.fn() } }
|
|
await SurveyList.methods.duplicateSurvey.call(list, 10)
|
|
expect(list.copyingSurveyId).toBeNull()
|
|
expect(list.$message.error).toHaveBeenCalled()
|
|
})
|
|
|
|
it('preserves selected schedule links and keeps the draft name within the existing title limit', () => {
|
|
const draft = surveyCopyDraft({ ...source, title: '题'.repeat(255), course_content_id: '8,9' }, questions)
|
|
expect(draft.form.course_content_id).toBe('8,9')
|
|
expect(draft.form.title.length).toBeLessThanOrEqual(255)
|
|
})
|
|
})
|