Skip to content

Commit 9133cff

Browse files
committed
Adds web forms test coverage
1 parent 5f39d71 commit 9133cff

File tree

3 files changed

+121
-2
lines changed

3 files changed

+121
-2
lines changed

packages/web-forms/src/components/controls/RankControl.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,16 @@ const swapItems = (index: number, newPosition: number) => {
8686
<ControlText :question="question" />
8787

8888
<VueDraggable
89-
v-model="options"
9089
:id="question.nodeId"
90+
v-model="options"
9191
:delay="HOLD_DELAY"
9292
:disabled="question.currentState.readonly"
9393
ghost-class="fade-moving"
9494
class="rank-control"
9595
@update="setValues">
9696
<div
9797
v-for="(option, index) in options"
98+
:id="option.value"
9899
:key="option.value"
99100
class="rank-option"
100101
:class="{ 'moving': highlight.index.value === index }"

packages/web-forms/tests/components/FormQuestion.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import InputControl from '@/components/controls/Input/InputControl.vue';
22
import SelectControl from '@/components/controls/SelectControl.vue';
3+
import RankControl from '@/components/controls/RankControl.vue';
34
import UnsupportedControl from '@/components/controls/UnsupportedControl.vue';
45
import type { SelectNode } from '@getodk/xforms-engine';
56
import { mount } from '@vue/test-utils';
67
import { describe, expect, it } from 'vitest';
7-
import FormQuestion from '../../src/components/FormQuestion.vue';
8+
import FormQuestion from '@/components/FormQuestion.vue';
89
import { fakeUnsupportedControlNode, getReactiveForm, globalMountOptions } from '../helpers';
910

1011
const mountComponent = async (formPath: string, questionNumber: number) => {
@@ -39,6 +40,20 @@ describe('FormQuestion', () => {
3940
expect(component.find('label').text()).toEqual('1. Select a fruit');
4041
});
4142

43+
it('shows Rank control for rank nodes', async () => {
44+
const component = await mountComponent('1-rank.xml', 0);
45+
46+
const rankControl = component.findComponent(RankControl);
47+
48+
expect(rankControl.exists()).toBe(true);
49+
50+
expect(component.find('label').text()).toEqual('What values guide your decision-making?');
51+
expect(component.find('#creativity_and_innovation .rank-label').text()).toEqual(
52+
'Creativity and Innovation'
53+
);
54+
expect(component.find('#family_and_friends .rank-label').text()).toEqual('Family and Friends');
55+
});
56+
4257
it('shows UnsupportedControl for unsupported / unimplemented question type', () => {
4358
const component = mount(FormQuestion, {
4459
props: {
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { DOMWrapper, mount, VueWrapper } from '@vue/test-utils';
3+
import { getReactiveForm, globalMountOptions } from '../helpers';
4+
import FormQuestion from '@/components/FormQuestion.vue';
5+
import RankControl from '@/components/controls/RankControl.vue';
6+
import { RankNode } from '@getodk/xforms-engine';
7+
8+
describe('RankControl', () => {
9+
const getAllOptions = (rankControl: VueWrapper): string[] => {
10+
return rankControl.findAll('.rank-label').map((element) => element.text());
11+
};
12+
13+
const getRankControl = async () => {
14+
const xform = await getReactiveForm('1-rank.xml');
15+
16+
const component = mount(FormQuestion, {
17+
props: {
18+
question: xform.currentState.children[0] as RankNode,
19+
},
20+
global: globalMountOptions,
21+
});
22+
23+
return component.findComponent(RankControl);
24+
};
25+
26+
const swapItems = (options: string[], indexA: number, indexB: number) => {
27+
const temp = options[indexA];
28+
options[indexA] = options[indexB];
29+
options[indexB] = temp;
30+
};
31+
32+
const moveOptionUp = async (rankControl: VueWrapper, optionIndex: number) => {
33+
const buttonMoveUp: DOMWrapper<HTMLElement> = rankControl.find(
34+
`.rank-option:nth-child(${optionIndex}) button:first-child`
35+
);
36+
expect(buttonMoveUp.exists()).toBe(true);
37+
await buttonMoveUp.trigger('click');
38+
};
39+
40+
const moveOptionDown = async (rankControl: VueWrapper, optionIndex: number) => {
41+
const buttonMoveUp: DOMWrapper<HTMLElement> = rankControl.find(
42+
`.rank-option:nth-child(${optionIndex}) button:nth-child(2)`
43+
);
44+
expect(buttonMoveUp.exists()).toBe(true);
45+
await buttonMoveUp.trigger('click');
46+
};
47+
48+
it('should render all options', async () => {
49+
const expectedOptions = [
50+
'Career Growth and Learning Opportunities',
51+
'Building a Supportive Community',
52+
'Financial Stability',
53+
'Pursuit of Hobbies and Passions',
54+
'Health',
55+
'Family and Friends',
56+
'Personal Development and Mindfulness',
57+
'Environmental Sustainability',
58+
'Creativity and Innovation',
59+
'Time Management and Work-Life Balance',
60+
];
61+
62+
const rankControl = (await getRankControl()) as VueWrapper;
63+
expect(rankControl.exists()).toBe(true);
64+
65+
const allOptions = getAllOptions(rankControl);
66+
expect(allOptions.length).toEqual(10);
67+
68+
const allOptionsExist = expectedOptions.every((option) => allOptions.includes(option));
69+
expect(allOptionsExist).toBe(true);
70+
});
71+
72+
it('should rank options using buttons', async () => {
73+
const rankControl = (await getRankControl()) as VueWrapper;
74+
expect(rankControl.exists()).toBe(true);
75+
76+
const expectedOptions = getAllOptions(rankControl);
77+
swapItems(expectedOptions, 4, 3);
78+
swapItems(expectedOptions, 6, 7);
79+
80+
await moveOptionUp(rankControl, 5);
81+
await moveOptionDown(rankControl, 7);
82+
83+
const allRankedOptions = getAllOptions(rankControl);
84+
const sameOrder = expectedOptions.every((value, index) => value === allRankedOptions[index]);
85+
expect(sameOrder).toBe(true);
86+
});
87+
88+
it('should not move options if they are the first or last one', async () => {
89+
const rankControl = (await getRankControl()) as VueWrapper;
90+
expect(rankControl.exists()).toBe(true);
91+
92+
const expectedOptions = getAllOptions(rankControl);
93+
swapItems(expectedOptions, 3, 2);
94+
95+
await moveOptionUp(rankControl, 1);
96+
await moveOptionUp(rankControl, 4);
97+
await moveOptionDown(rankControl, 10);
98+
99+
const allRankedOptions = getAllOptions(rankControl);
100+
const sameOrder = expectedOptions.every((value, index) => value === allRankedOptions[index]);
101+
expect(sameOrder).toBe(true);
102+
});
103+
});

0 commit comments

Comments
 (0)