1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
'use strict';
const { nextTick } = require( 'vue' );
const { mount, flushPromises } = require( '@vue/test-utils' );
const { getSpecialBlock, mockMwApiGet, mockMwConfigGet } = require( './SpecialBlock.setup.js' );
const { createTestingPinia } = require( '@pinia/testing' );
const UserLookup = require( '../../../resources/src/mediawiki.special.block/components/UserLookup.vue' );
const useBlockStore = require( '../../../resources/src/mediawiki.special.block/stores/block.js' );
describe( 'UserLookup', () => {
const getWrapper = ( propsData, apiMocks = [] ) => {
mockMwApiGet( apiMocks );
return mount( UserLookup, {
props: propsData,
global: {
plugins: [ createTestingPinia( { stubActions: false } ) ]
},
attachTo: document.body
} );
};
it( 'should update menu items based on the API response', async () => {
const wrapper = getWrapper( { modelValue: 'ExampleUser' } );
// Ensure that the initial search string matches the initial prop value.
const input = wrapper.find( '.cdx-text-input__input' );
expect( input.element.value ).toBe( 'ExampleUser' );
// "No results"
const listBox = wrapper.find( '.cdx-menu__listbox' );
expect( listBox.element.children ).toHaveLength( 1 );
await input.trigger( 'input' );
// Ensure that the Lookup menu is populated with API response data
// We need to use "flushPromises" from Vue test utils
// to ensure the fake API request can complete
await flushPromises();
expect( listBox.element.children ).toHaveLength( 2 );
expect( listBox.element.children[ 0 ].textContent ).toBe( 'ExampleUser' );
expect( listBox.element.children[ 1 ].textContent ).toBe( 'ExampleUser2' );
} );
it( 'should show an error if the pre-supplied target is missing', async () => {
const wrapper = getSpecialBlock( {
blockTargetUser: 'NonexistentUser',
blockTargetExists: false
} );
await flushPromises();
expect( wrapper.find( '.cdx-message__content' ).text() ).toBe( 'nosuchusershort' );
} );
it( 'should show an error if the target is changed to a missing user', async () => {
const wrapper = getWrapper( { modelValue: '' } );
await wrapper.find( '.cdx-text-input__input' ).setValue( 'NonexistentUser' );
await flushPromises();
expect( wrapper.find( '.cdx-message__content' ).text() ).toBe( 'nosuchusershort' );
} );
it( 'should not show an error when selecting a target from the menu items', async () => {
mockMwConfigGet( { blockTargetUser: 'ExampleUser', blockTargetExists: true } );
const wrapper = getWrapper(
{ modelValue: 'ExampleUser' },
[ {
params: {
list: 'allusers',
auprefix: 'Example'
},
response: {
query: {
allusers: [
{ name: 'ExampleUser' },
{ name: 'ExampleUser2' }
]
}
}
} ]
);
await wrapper.find( '.cdx-text-input__input' ).setValue( 'Example' );
await flushPromises();
const listBox = wrapper.find( '.cdx-menu__listbox' );
expect( listBox.element.children ).toHaveLength( 2 );
await listBox.element.children[ 0 ].click();
expect( wrapper.vm.messages ).toStrictEqual( {} );
expect( wrapper.find( '.cdx-message__content' ).exists() ).toBeFalsy();
} );
it( 'should reset the form when the clear button is clicked', async () => {
mockMwConfigGet( {
blockTargetUser: 'NonexistentUser',
blockTargetExists: false
} );
const wrapper = getWrapper( { modelValue: 'NonexistentUser' } );
const store = useBlockStore();
await flushPromises();
expect( wrapper.vm.messages ).toStrictEqual( { error: 'nosuchusershort' } );
await wrapper.find( '.cdx-text-input__clear-icon' ).trigger( 'click' );
await nextTick();
expect( wrapper.vm.messages ).toStrictEqual( {} );
expect( store.targetExists ).toBeFalsy();
expect( document.activeElement.name ).toStrictEqual( 'wpTarget' );
} );
} );
|