Skip to content

Commit 736c4cb

Browse files
committed
SVY-20341 Native Select does not work properly in multiselect mode
[SERVOY] Refactor tests to use Cypress and remove deprecated Jasmine specs
1 parent 7bbfb52 commit 736c4cb

2 files changed

Lines changed: 216 additions & 89 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/* eslint-disable @typescript-eslint/no-unused-expressions */
2+
import { Component, ViewChild } from '@angular/core';
3+
import { Format, ServoyApi, ServoyApiTesting, ServoyPublicTestingModule, IValuelist } from '@servoy/public';
4+
import { ServoyBootstrapSelect } from './select';
5+
import { MountConfig } from 'cypress/angular';
6+
import { FormsModule } from '@angular/forms';
7+
import { ShowDisplayValuePipe } from '../lib/showDisplayValue.pipe';
8+
9+
@Component({
10+
template: `<bootstrapcomponents-select
11+
[servoyApi]="servoyApi"
12+
[onActionMethodID]="onActionMethodID"
13+
[onDataChangeMethodID]="onDataChangeMethodID"
14+
[onFocusGainedMethodID]="onFocusGainedMethodID"
15+
[onFocusLostMethodID]="onFocusLostMethodID"
16+
[dataProviderID]="dataProviderID"
17+
(dataProviderIDChange)="dataProviderIDChange($event)"
18+
[enabled]="enabled"
19+
[multiselect]="multiselect"
20+
[placeholderText]="placeholderText"
21+
[selectSize]="selectSize"
22+
[styleClass]="styleClass"
23+
[tabSeq]="tabSeq"
24+
[toolTipText]="toolTipText"
25+
[valuelistID]="valuelistID"
26+
#element>
27+
</bootstrapcomponents-select>`,
28+
standalone: false
29+
})
30+
class WrapperComponent {
31+
servoyApi: ServoyApi;
32+
33+
onActionMethodID: (e: Event, data?: unknown) => void;
34+
onDataChangeMethodID: (e: Event, data?: unknown) => void;
35+
onFocusGainedMethodID: (e: Event, data?: unknown) => void;
36+
onFocusLostMethodID: (e: Event, data?: unknown) => void;
37+
38+
dataProviderID: unknown;
39+
dataProviderIDChange = (newData: unknown) => {};
40+
41+
enabled = true;
42+
multiselect: boolean;
43+
placeholderText: string;
44+
selectSize: number;
45+
styleClass: string;
46+
tabSeq: number;
47+
toolTipText: string;
48+
valuelistID: IValuelist;
49+
50+
@ViewChild('element') element: ServoyBootstrapSelect;
51+
}
52+
53+
describe('ServoyBootstrapSelect', () => {
54+
let servoyApiSpy;
55+
let mockData;
56+
57+
const config: MountConfig<WrapperComponent>= {
58+
declarations: [ServoyBootstrapSelect, ShowDisplayValuePipe],
59+
imports: [ ServoyPublicTestingModule, FormsModule]
60+
}
61+
62+
beforeEach(() => {
63+
servoyApiSpy = new ServoyApiTesting();
64+
65+
mockData = [{
66+
"displayValue": "one",
67+
"realValue": 1
68+
},
69+
{
70+
"displayValue": "two",
71+
"realValue": 2
72+
},
73+
{
74+
"displayValue": "three",
75+
"realValue": 3
76+
},
77+
{
78+
"displayValue": "four",
79+
"realValue": 4
80+
}] as IValuelist;
81+
config.componentProperties = {
82+
servoyApi: servoyApiSpy,
83+
enabled: true,
84+
dataProviderID: '1',
85+
multiselect: false,
86+
valuelistID: mockData
87+
}
88+
});
89+
90+
it('should mount and register the component', () => {
91+
const registerComponent = cy.stub(servoyApiSpy, 'registerComponent');
92+
cy.mount(WrapperComponent, config).then(() => {
93+
cy.get('select').should('exist').then(() => {
94+
cy.wrap(registerComponent).should('be.called');
95+
});
96+
});
97+
});
98+
99+
it('should set the placeholder text', () => {
100+
config.componentProperties.placeholderText = 'Enter your name';
101+
cy.mount(WrapperComponent, config).then(() => {
102+
cy.get('select').should('have.attr', 'placeholder', 'Enter your name');
103+
});
104+
});
105+
106+
it('show a style class', () => {
107+
cy.mount(WrapperComponent, config).then(wrapper => {
108+
cy.get('select').should('not.have.class', 'mystyleclass').then(() => {
109+
wrapper.component.styleClass = 'mystyleclass';
110+
wrapper.fixture.detectChanges();
111+
cy.get('select').should('have.class', 'mystyleclass')
112+
});
113+
});
114+
});
115+
116+
it('show more then 1 style class', () => {
117+
config.componentProperties.styleClass = 'mystyleclass';
118+
cy.mount(WrapperComponent, config).then(wrapper => {
119+
cy.get('select').should('have.class', 'mystyleclass').then(() => {
120+
wrapper.component.styleClass = 'classA classB';
121+
wrapper.fixture.detectChanges();
122+
cy.get('select').should('have.class', 'classA').should('have.class', 'classB');
123+
});
124+
});
125+
});
126+
127+
it('should not allow multiselect', () => {
128+
cy.mount(WrapperComponent, config).then(() => {
129+
cy.get('select').should('not.have.attr', 'multiple');
130+
});
131+
});
132+
133+
it('should allow multiselect', () => {
134+
config.componentProperties.multiselect = true;
135+
cy.mount(WrapperComponent, config).then(() => {
136+
cy.get('select').should('have.attr', 'multiple');
137+
cy.get('select').invoke('val').should('deep.equal', ["0: '1'"]).then(() => {
138+
cy.get('select').select(["0: '1'", "1: '2'"]).then(() => {
139+
cy.get('select').invoke('val').should('deep.equal', ["0: '1'", "1: '2'"]);
140+
});
141+
});
142+
});
143+
});
144+
145+
it('should handle enabled state', () => {
146+
cy.mount(WrapperComponent, config).then(wrapper => {
147+
cy.get('select').should('not.have.attr', 'disabled').then(() => {
148+
wrapper.component.enabled = false;
149+
wrapper.fixture.detectChanges();
150+
cy.get('select').should('have.attr', 'disabled');
151+
});
152+
});
153+
});
154+
155+
it('should handle onaction event', () => {
156+
const onActionMethodID = cy.stub();
157+
config.componentProperties.onActionMethodID = onActionMethodID;
158+
cy.mount(WrapperComponent, config).then(() => {
159+
cy.wrap(onActionMethodID).should('be.not.called');
160+
cy.get('select').should('have.value', '1').select('2').then(() => {
161+
cy.wrap(onActionMethodID).should('be.called');
162+
});
163+
});
164+
});
165+
166+
it('should handle focus gained event', () => {
167+
const onFocusGainedMethodID = cy.stub();
168+
config.componentProperties.onFocusGainedMethodID = onFocusGainedMethodID;
169+
cy.mount(WrapperComponent, config).then(() => {
170+
cy.get('select').should('have.value', '1').focus().then(() => {
171+
cy.wrap(onFocusGainedMethodID).should('be.called');
172+
});
173+
});
174+
});
175+
176+
it('should handle focus lost event', () => {
177+
const onFocusLostMethodID = cy.stub();
178+
config.componentProperties.onFocusLostMethodID = onFocusLostMethodID;
179+
cy.mount(WrapperComponent, config).then(() => {
180+
cy.get('select').should('have.value', '1').focus().blur().then(() => {
181+
cy.wrap(onFocusLostMethodID).should('be.called');
182+
});
183+
});
184+
});
185+
186+
it('should emit dataProviderIDChange event on input change', () => {
187+
const dataProviderIDChange = cy.stub();
188+
config.componentProperties.dataProviderIDChange = dataProviderIDChange;
189+
cy.mount(WrapperComponent, config);
190+
cy.get('select').select('2').blur();
191+
cy.wrap(dataProviderIDChange).should('have.been.calledWith', '2');
192+
});
193+
194+
it('should not emit dataProviderIDChange event dataprovder change', () => {
195+
const dataProviderIDChange = cy.stub();
196+
config.componentProperties.dataProviderIDChange = dataProviderIDChange;
197+
cy.mount(WrapperComponent, config).then(wrapper => {
198+
cy.get('select').should('have.value', '1').then(() => {
199+
wrapper.component.dataProviderID = '2';
200+
wrapper.fixture.detectChanges();
201+
expect(dataProviderIDChange).not.to.have.been.called;
202+
cy.get('select').should('have.value', '2')
203+
});
204+
});
205+
});
206+
207+
it('should update the tooltip dynamically', () => {
208+
cy.mount(WrapperComponent, config).then((wrapper) => {
209+
wrapper.component.toolTipText = 'Updated tooltip';
210+
wrapper.fixture.detectChanges();
211+
cy.get('select').trigger('pointerenter').then(() => {
212+
cy.get('div[id="mktipmsg"]').should('have.text', 'Updated tooltip');
213+
});
214+
});
215+
});
216+
});

projects/bootstrapcomponents/src/select/select.spec.ts

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)