glib-web 5.0.7 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/gen-cypress-test.md +101 -0
- package/.github/dependabot.yml +24 -12
- package/.nycrc.json +4 -0
- package/AGENTS.md +1 -0
- package/README.md +4 -0
- package/actions/logics/set.js +5 -0
- package/actions/panels/scrollTo.js +2 -2
- package/actions/timeouts/set.js +1 -1
- package/app.vue +1 -1
- package/components/charts/series.js +2 -2
- package/components/composable/gmap.js +1 -1
- package/components/composable/upload.js +1 -4
- package/components/composable/upload_nothing.js +1 -1
- package/components/fields/_buttonDate.vue +2 -2
- package/components/fields/_patternText.vue +2 -8
- package/components/fields/_select.vue +10 -8
- package/components/fields/_selectItemDefault.vue +1 -3
- package/components/fields/_selectItemWithIcon.vue +1 -3
- package/components/fields/_selectItemWithImage.vue +1 -3
- package/components/fields/clipboardUpload.vue +115 -0
- package/components/fields/dynamicGroup2.vue +1 -1
- package/components/fields/multiUpload.vue +12 -19
- package/components/fields/placeholderUpload.vue +8 -4
- package/components/fields/radioGroup.vue +0 -7
- package/components/fields/sign.vue +1 -1
- package/components/fields/text.vue +1 -9
- package/components/fields/upload.vue +4 -0
- package/components/mixins/longClick.js +1 -1
- package/components/panels/bulkEdit2.vue +1 -1
- package/components/panels/list.vue +1 -1
- package/components/popover.vue +1 -1
- package/components/responsive.vue +1 -1
- package/cypress/e2e/glib-web/dialog.cy.js +0 -1
- package/cypress/e2e/glib-web/dirtyState.cy.js +37 -37
- package/cypress/e2e/glib-web/fieldsDateTime.cy.js +46 -3
- package/cypress/e2e/glib-web/fieldsRadio.cy.js +65 -0
- package/cypress/e2e/glib-web/fieldsSelect.cy.js +116 -76
- package/cypress/e2e/glib-web/fieldsText.cy.js +83 -0
- package/cypress/e2e/glib-web/fieldsUpload.cy.js +230 -120
- package/cypress/e2e/glib-web/image.cy.js +62 -33
- package/cypress/e2e/glib-web/switch.cy.js +13 -0
- package/cypress/e2e/glib-web/tabBar.cy.js +23 -0
- package/cypress/fixtures/document.pdf +12 -0
- package/cypress/fixtures/large.png +0 -0
- package/cypress/fixtures/upload.png +0 -0
- package/cypress/helper.js +13 -1
- package/cypress/support/component.js +1 -1
- package/cypress/support/e2e.js +20 -13
- package/doc/dependabot.md +22 -0
- package/eslint-rules/index.js +6 -6
- package/nav/dialog.vue +1 -1
- package/package.json +18 -16
- package/templates/_menu.vue +2 -2
- package/cypress/component/inputUpload.cy.js +0 -103
- package/cypress/component/multiUpload.cy.js +0 -107
- package/cypress/component/placeholderUpload.cy.js +0 -91
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="container" class="placeholder-view" @click="trigger">
|
|
3
|
-
<v-img v-if="props.spec.type == 'image' && !uploading" :
|
|
3
|
+
<v-img v-if="props.spec.type == 'image' && !uploading" :src="sourceUrl" cover width="100%" />
|
|
4
4
|
<v-avatar v-else-if="props.spec.type == 'avatar' && !uploading" :size="props.spec.width">
|
|
5
5
|
<v-img :src="sourceUrl"></v-img>
|
|
6
6
|
</v-avatar>
|
|
@@ -26,10 +26,11 @@ export default {
|
|
|
26
26
|
|
|
27
27
|
<script setup>
|
|
28
28
|
import { computed, ref, getCurrentInstance, watch, nextTick } from "vue";
|
|
29
|
-
import { useFilesState } from "../composable/file";
|
|
29
|
+
import { useFilesState, useFileUtils } from "../composable/file";
|
|
30
30
|
import { useUploader } from "../composable/uploader";
|
|
31
31
|
import Action from "../../action";
|
|
32
32
|
|
|
33
|
+
const { makeKey, Item } = useFileUtils();
|
|
33
34
|
const props = defineProps(['spec']);
|
|
34
35
|
const files = ref({});
|
|
35
36
|
const { uploading, uploaded } = useFilesState(files);
|
|
@@ -44,6 +45,8 @@ const inputRef = ref(null);
|
|
|
44
45
|
const container = ref(null);
|
|
45
46
|
const blobUrl = ref(undefined);
|
|
46
47
|
const sourceUrl = computed(() => {
|
|
48
|
+
if (blobUrl.value === '') return '';
|
|
49
|
+
|
|
47
50
|
return blobUrl.value || props.spec.url;
|
|
48
51
|
});
|
|
49
52
|
const style = computed(() => {
|
|
@@ -70,8 +73,8 @@ if (props.spec.onFinishUpload) {
|
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
function reset() {
|
|
73
|
-
files.value = {};
|
|
74
|
-
blobUrl.value =
|
|
76
|
+
files.value = { [makeKey()]: new Item({ signedId: '', status: null, el: null }) };
|
|
77
|
+
blobUrl.value = '';
|
|
75
78
|
inputRef.value.value = null;
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -86,5 +89,6 @@ defineExpose({ reset, trigger });
|
|
|
86
89
|
.placeholder-view {
|
|
87
90
|
width: 100%;
|
|
88
91
|
cursor: pointer;
|
|
92
|
+
background-color: rgb(var(--v-theme-surface));
|
|
89
93
|
}
|
|
90
94
|
</style>
|
|
@@ -80,15 +80,7 @@ export default {
|
|
|
80
80
|
) ||
|
|
81
81
|
"Must be a valid URL",
|
|
82
82
|
],
|
|
83
|
-
}
|
|
84
|
-
search: {
|
|
85
|
-
type: "url",
|
|
86
|
-
prependIcon: "search",
|
|
87
|
-
onRightIconClick: function () { },
|
|
88
|
-
rules: [
|
|
89
|
-
(v) => !v || /^\w+:\/\/[.-\w]+$/.test(v) || "Must be a valid URL",
|
|
90
|
-
],
|
|
91
|
-
},
|
|
83
|
+
}
|
|
92
84
|
},
|
|
93
85
|
};
|
|
94
86
|
},
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<placeholderUpload v-if="props.spec.placeholderView" ref="realComp" :spec="childSpec" />
|
|
4
4
|
<inputUpload v-else-if="props.spec.inputView" ref="realComp" :spec="childSpec" />
|
|
5
5
|
<multiUpload v-else-if="props.spec.multiProgressView" ref="realComp" :spec="childSpec" />
|
|
6
|
+
<clipboardUpload v-else-if="props.spec.clipboardView" ref="realComp" :spec="childSpec" />
|
|
6
7
|
</div>
|
|
7
8
|
</template>
|
|
8
9
|
|
|
@@ -18,6 +19,7 @@ export default {
|
|
|
18
19
|
import placeholderUpload from "./placeholderUpload.vue";
|
|
19
20
|
import inputUpload from "./inputUpload.vue";
|
|
20
21
|
import multiUpload from "./multiUpload.vue";
|
|
22
|
+
import clipboardUpload from "./clipboardUpload.vue";
|
|
21
23
|
|
|
22
24
|
import { computed, ref } from "vue";
|
|
23
25
|
|
|
@@ -31,6 +33,8 @@ const childSpec = computed(() => {
|
|
|
31
33
|
return Object.assign({}, props.spec, { inputView: null }, props.spec.inputView);
|
|
32
34
|
} else if (props.spec.multiProgressView) {
|
|
33
35
|
return Object.assign({}, props.spec, { multiProgressView: null }, props.spec.multiProgressView);
|
|
36
|
+
} else if (props.spec.clipboardView) {
|
|
37
|
+
return Object.assign({}, props.spec, { clipboardView: null }, props.spec.clipboardView);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
return props.spec;
|
package/components/popover.vue
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { testPageUrl } from "../../helper.js"
|
|
2
|
-
const url = testPageUrl('dirty_state')
|
|
3
|
-
const prompt = 'Changes have not been saved. Are you sure you want to leave this page?'
|
|
1
|
+
import { testPageUrl } from "../../helper.js";
|
|
2
|
+
const url = testPageUrl('dirty_state');
|
|
3
|
+
const prompt = 'Changes have not been saved. Are you sure you want to leave this page?';
|
|
4
4
|
|
|
5
5
|
describe('dirtyState', () => {
|
|
6
6
|
it('can be disabled', () => {
|
|
7
|
-
cy.visit(url)
|
|
7
|
+
cy.visit(url);
|
|
8
8
|
|
|
9
9
|
cy.get('input[name="user[dirty_check_disabled]"]')
|
|
10
10
|
.type('TEST TEST TEST')
|
|
11
|
-
.blur()
|
|
11
|
+
.blur();
|
|
12
12
|
|
|
13
|
-
cy.reload()
|
|
13
|
+
cy.reload();
|
|
14
14
|
|
|
15
|
-
cy.get('input[name="user[dirty_check_disabled]"]').should('be.empty')
|
|
16
|
-
})
|
|
15
|
+
cy.get('input[name="user[dirty_check_disabled]"]').should('be.empty');
|
|
16
|
+
});
|
|
17
17
|
|
|
18
18
|
it('dirty if not equal to init value', () => {
|
|
19
|
-
cy.visit(url)
|
|
19
|
+
cy.visit(url);
|
|
20
20
|
|
|
21
21
|
cy.contains('Male').click();
|
|
22
22
|
|
|
23
23
|
cy.on('window:confirm', (str) => {
|
|
24
|
-
cy.then(() => expect(str).to.equal(prompt))
|
|
24
|
+
cy.then(() => expect(str).to.equal(prompt));
|
|
25
25
|
return false;
|
|
26
|
-
})
|
|
26
|
+
});
|
|
27
27
|
|
|
28
|
-
cy.contains('fields_upload').click()
|
|
29
|
-
cy.contains('Female').click()
|
|
30
|
-
cy.contains('fields_upload').click() // Try to navigate to another page
|
|
31
|
-
cy.location('href').should('eq', testPageUrl('fields_upload'))
|
|
32
|
-
})
|
|
28
|
+
cy.contains('fields_upload').click({ force: true });
|
|
29
|
+
cy.contains('Female').click();
|
|
30
|
+
cy.contains('fields_upload').click({ force: true }); // Try to navigate to another page
|
|
31
|
+
cy.location('href').should('eq', testPageUrl('fields_upload'));
|
|
32
|
+
});
|
|
33
33
|
|
|
34
34
|
it('have different context between window and dialog', () => {
|
|
35
|
-
cy.visit(url)
|
|
35
|
+
cy.visit(url);
|
|
36
36
|
|
|
37
|
-
cy.contains('Dialog Form').click()
|
|
37
|
+
cy.contains('Dialog Form').click();
|
|
38
38
|
|
|
39
|
-
cy.get('input[name="user[name]"]').click().type('John Doe')
|
|
39
|
+
cy.get('input[name="user[name]"]').click().type('John Doe');
|
|
40
40
|
|
|
41
|
-
cy.contains('cancel').click()
|
|
41
|
+
cy.contains('cancel').click();
|
|
42
42
|
|
|
43
43
|
let text = '';
|
|
44
44
|
cy.on('window:confirm', (str) => {
|
|
45
45
|
text = str;
|
|
46
46
|
return true;
|
|
47
|
-
})
|
|
47
|
+
});
|
|
48
48
|
|
|
49
|
-
cy.then(() => expect(text).to.equal(prompt))
|
|
49
|
+
cy.then(() => expect(text).to.equal(prompt));
|
|
50
50
|
|
|
51
|
-
cy.contains('fields_upload').click() // Try to navigate to another page
|
|
52
|
-
cy.location('href').should('eq', testPageUrl('fields_upload'))
|
|
53
|
-
})
|
|
51
|
+
cy.contains('fields_upload').click(); // Try to navigate to another page
|
|
52
|
+
cy.location('href').should('eq', testPageUrl('fields_upload'));
|
|
53
|
+
});
|
|
54
54
|
|
|
55
55
|
it('pop on history back', () => {
|
|
56
|
-
cy.visit(testPageUrl('fields_upload'))
|
|
57
|
-
cy.contains('dirty_state').click()
|
|
56
|
+
cy.visit(testPageUrl('fields_upload'));
|
|
57
|
+
cy.contains('dirty_state').click();
|
|
58
58
|
|
|
59
|
-
cy.contains('choice2').click()
|
|
59
|
+
cy.contains('choice2').click();
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let text = ''
|
|
61
|
+
let text = '';
|
|
64
62
|
cy.on('window:confirm', (str) => {
|
|
65
63
|
text = str;
|
|
66
64
|
return false;
|
|
67
|
-
})
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
cy.go('back');
|
|
68
68
|
|
|
69
|
-
cy.
|
|
69
|
+
cy.wrap(null).should(() => expect(text).to.equal(prompt));
|
|
70
70
|
|
|
71
71
|
// dirty state is removed after second try
|
|
72
|
-
cy.go('back')
|
|
72
|
+
cy.go('back');
|
|
73
73
|
|
|
74
|
-
cy.location('href').should('eq', testPageUrl('fields_upload'))
|
|
75
|
-
})
|
|
76
|
-
})
|
|
74
|
+
cy.location('href').should('eq', testPageUrl('fields_upload'));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -3,30 +3,38 @@ import { testPageUrl, withComponent } from "../../helper.js"
|
|
|
3
3
|
const url = testPageUrl('fields_date_time')
|
|
4
4
|
|
|
5
5
|
describe('fields_date_time', () => {
|
|
6
|
-
it('
|
|
6
|
+
it('sets date to today + 1 week', () => {
|
|
7
7
|
cy.visit(url)
|
|
8
8
|
|
|
9
9
|
cy.contains('Set today + 1 week').click()
|
|
10
10
|
cy.get('#date_status').should('contain.text', 'Date changed')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('clears date', () => {
|
|
14
|
+
cy.visit(url)
|
|
11
15
|
|
|
12
16
|
cy.contains('Clear date').click()
|
|
13
17
|
cy.get('#date_status').should('contain.text', 'Date changed')
|
|
14
18
|
cy.get('input[name="user[date_basic]"]').should('have.value', '')
|
|
15
19
|
})
|
|
16
20
|
|
|
17
|
-
it('
|
|
21
|
+
it('sets datetime to evening', () => {
|
|
18
22
|
cy.visit(url)
|
|
19
23
|
|
|
20
24
|
cy.contains('Set datetime (evening)').click()
|
|
21
25
|
cy.get('#datetime_status').should('contain.text', 'Datetime changed')
|
|
22
26
|
cy.get('input[name="user[datetime_basic]"]').should('have.value', '2024-12-12T18:45')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('clears datetime', () => {
|
|
30
|
+
cy.visit(url)
|
|
23
31
|
|
|
24
32
|
cy.contains('Clear datetime').click()
|
|
25
33
|
cy.get('#datetime_status').should('contain.text', 'Datetime changed')
|
|
26
34
|
cy.get('input[name="user[datetime_basic]"]').should('have.value', '')
|
|
27
35
|
})
|
|
28
36
|
|
|
29
|
-
it('
|
|
37
|
+
it('disables and enables date', () => {
|
|
30
38
|
cy.visit(url)
|
|
31
39
|
|
|
32
40
|
cy.contains('Disable date').click()
|
|
@@ -34,6 +42,41 @@ describe('fields_date_time', () => {
|
|
|
34
42
|
|
|
35
43
|
cy.contains('Enable date').click()
|
|
36
44
|
cy.get('#date_basic').find('.v-input--disabled').should('not.exist')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('opens datetime picker on click and reflects selected value', () => {
|
|
48
|
+
cy.visit(url)
|
|
49
|
+
|
|
50
|
+
cy.get('#datetime_basic').find('.v-field__input').click()
|
|
51
|
+
cy.get('#datetime_basic').find('.v-input--focused').should('exist')
|
|
52
|
+
|
|
53
|
+
cy.get('#datetime_basic').find('input.native-picker').then($el => {
|
|
54
|
+
const nativeSet = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set
|
|
55
|
+
nativeSet.call($el[0], '2024-12-20T14:30')
|
|
56
|
+
$el[0].dispatchEvent(new Event('input', { bubbles: true }))
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
cy.get('#datetime_basic').find('.v-field__input').should('have.value', '12/20/2024 14:30')
|
|
60
|
+
cy.get('input[name="user[datetime_basic]"]').should('have.value', '2024-12-20T14:30')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('opens plain template picker on click and reflects selected value', () => {
|
|
64
|
+
cy.visit(url)
|
|
65
|
+
|
|
66
|
+
cy.get('#datetime_plain').find('.date-button').click()
|
|
67
|
+
cy.get('#datetime_plain').find('input.date-input').should('be.focused')
|
|
68
|
+
|
|
69
|
+
cy.get('#datetime_plain').find('input.date-input').then($el => {
|
|
70
|
+
const nativeSet = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set
|
|
71
|
+
nativeSet.call($el[0], '2026-03-15T10:00')
|
|
72
|
+
$el[0].dispatchEvent(new Event('input', { bubbles: true }))
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
cy.get('input[name="user[datetime_plain]"]').should('have.value', '2026-03-15T10:00')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('switches datetime_plain between text and plain templates', () => {
|
|
79
|
+
cy.visit(url)
|
|
37
80
|
|
|
38
81
|
cy.contains('Use text template').click()
|
|
39
82
|
withComponent('datetime_plain', (comp) => {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { testPageUrl } from "../../helper.js";
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_radio');
|
|
4
|
+
|
|
5
|
+
describe('fields_radio', () => {
|
|
6
|
+
it('selects Female in basic example and shows status changed', () => {
|
|
7
|
+
cy.visit(url);
|
|
8
|
+
|
|
9
|
+
cy.contains('Status: idle').should('be.visible');
|
|
10
|
+
cy.contains('Female').click();
|
|
11
|
+
cy.contains('Status: changed').should('be.visible');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('programmatically sets Female then Male via action buttons', () => {
|
|
15
|
+
cy.visit(url);
|
|
16
|
+
|
|
17
|
+
cy.contains('Select Female').click();
|
|
18
|
+
cy.contains('Status: changed').should('be.visible');
|
|
19
|
+
cy.contains('Select Male').click();
|
|
20
|
+
cy.contains('Status: changed').should('be.visible');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('clears basic example selection via Clear selection button', () => {
|
|
24
|
+
cy.visit(url);
|
|
25
|
+
|
|
26
|
+
cy.contains('Clear selection').click();
|
|
27
|
+
cy.contains('Status: changed').should('be.visible');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('shows Phone number field when Phone is selected in onChangeAndLoad', () => {
|
|
31
|
+
cy.visit(url);
|
|
32
|
+
|
|
33
|
+
cy.contains('.v-field-label--floating', 'Email address').scrollIntoView().should('be.visible');
|
|
34
|
+
cy.contains('Phone').click();
|
|
35
|
+
cy.contains('.v-field-label--floating', 'Phone number').scrollIntoView().should('be.visible');
|
|
36
|
+
cy.contains('.v-field-label--floating', 'Email address').should('not.exist');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('restores Email address field when Email is re-selected', () => {
|
|
40
|
+
cy.visit(url);
|
|
41
|
+
|
|
42
|
+
cy.contains('Phone').click();
|
|
43
|
+
cy.contains('.v-field-label--floating', 'Phone number').scrollIntoView().should('be.visible');
|
|
44
|
+
cy.contains('Email').click();
|
|
45
|
+
cy.contains('.v-field-label--floating', 'Email address').scrollIntoView().should('be.visible');
|
|
46
|
+
cy.contains('.v-field-label--floating', 'Phone number').should('not.exist');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('toggles I agree single-option radio and submits form', () => {
|
|
50
|
+
cy.visit(url);
|
|
51
|
+
|
|
52
|
+
cy.contains('I agree to the terms and conditions').click();
|
|
53
|
+
cy.contains('Submit').click();
|
|
54
|
+
cy.contains('Method: POST').should('be.visible');
|
|
55
|
+
cy.contains('"agree": "yes"').should('be.visible');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('submits form without I agree and agree is absent from form data', () => {
|
|
59
|
+
cy.visit(url);
|
|
60
|
+
|
|
61
|
+
cy.contains('Submit').click();
|
|
62
|
+
cy.contains('Method: POST').should('be.visible');
|
|
63
|
+
cy.contains('"agree"').should('not.exist');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -1,82 +1,122 @@
|
|
|
1
|
-
import { testPageUrl } from "../../helper.js"
|
|
1
|
+
import { testPageUrl } from "../../helper.js";
|
|
2
2
|
|
|
3
|
-
const url = testPageUrl('fields_select')
|
|
4
|
-
|
|
5
|
-
const getSelectComponent = () =>
|
|
6
|
-
cy.window().then((win) => {
|
|
7
|
-
const comp = win.GLib.component.findById('select_media')
|
|
8
|
-
expect(comp).to.exist
|
|
9
|
-
return comp
|
|
10
|
-
})
|
|
3
|
+
const url = testPageUrl('fields_select');
|
|
11
4
|
|
|
12
5
|
describe('fields_select', () => {
|
|
13
6
|
it('updates option variants', () => {
|
|
14
|
-
cy.visit(url)
|
|
15
|
-
|
|
16
|
-
cy.contains('Use icon options').click()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
cy.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
cy.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
cy.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
7
|
+
cy.visit(url);
|
|
8
|
+
|
|
9
|
+
cy.contains('Use icon options').click();
|
|
10
|
+
cy.get('#select_media select[hidden] option').should('have.length', 4);
|
|
11
|
+
cy.get('#select_media').click();
|
|
12
|
+
cy.get('body').type('{esc}');
|
|
13
|
+
cy.get('#select_media .v-select--multiple').should('not.exist');
|
|
14
|
+
cy.get('#select_media .v-chip').should('not.exist');
|
|
15
|
+
|
|
16
|
+
cy.contains('Use image options').click();
|
|
17
|
+
cy.get('#select_media select[hidden] option').should('have.length', 4);
|
|
18
|
+
cy.get('#select_media').click();
|
|
19
|
+
cy.get('.v-overlay--active .v-list-item').first().find('img').should('have.attr', 'src').and('contain', 'select-1');
|
|
20
|
+
cy.get('body').type('{esc}');
|
|
21
|
+
cy.get('#select_media .v-select--multiple').should('not.exist');
|
|
22
|
+
cy.get('#select_media .v-chip').should('not.exist');
|
|
23
|
+
|
|
24
|
+
cy.contains('Text only').click();
|
|
25
|
+
cy.get('#select_media select[hidden] option').should('have.length', 4);
|
|
26
|
+
cy.get('#select_media').click();
|
|
27
|
+
cy.get('.v-overlay--active .v-list-item').first().find('.v-icon').should('not.exist');
|
|
28
|
+
cy.get('.v-overlay--active .v-list-item').first().find('img').should('not.exist');
|
|
29
|
+
cy.get('body').type('{esc}');
|
|
30
|
+
cy.get('#select_media .v-select--multiple').should('not.exist');
|
|
31
|
+
cy.get('#select_media .v-chip').should('not.exist');
|
|
32
|
+
|
|
33
|
+
cy.contains('Multiple + chips').click();
|
|
34
|
+
cy.get('#select_media select[hidden] option').should('have.length', 4);
|
|
35
|
+
cy.get('#select_media').click();
|
|
36
|
+
cy.get('body').type('{esc}');
|
|
37
|
+
cy.get('#select_media .v-select--multiple').should('exist');
|
|
38
|
+
cy.get('#select_media .v-chip').should('exist');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('selects all options in multiple mode', () => {
|
|
42
|
+
cy.on('uncaught:exception', (err) => {
|
|
43
|
+
if (err.message.includes('ResizeObserver')) return false;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
cy.visit(url);
|
|
47
|
+
|
|
48
|
+
cy.contains('Multiple + chips').click();
|
|
49
|
+
cy.get('#select_media').click();
|
|
50
|
+
cy.get('.v-list-item').contains('Option 2').click();
|
|
51
|
+
cy.get('.v-list-item').contains('Option 4').click();
|
|
52
|
+
cy.get('body').type('{esc}');
|
|
53
|
+
|
|
54
|
+
cy.get('#select_media input[type="hidden"]').should('have.length', 4);
|
|
55
|
+
cy.get('#select_media input[type="hidden"]').eq(0).should('have.value', 'option1');
|
|
56
|
+
cy.get('#select_media input[type="hidden"]').eq(1).should('have.value', 'option3');
|
|
57
|
+
cy.get('#select_media input[type="hidden"]').eq(2).should('have.value', 'option2');
|
|
58
|
+
cy.get('#select_media input[type="hidden"]').eq(3).should('have.value', 'option4');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('removes one chip from multiple selection', () => {
|
|
62
|
+
cy.visit(url);
|
|
63
|
+
|
|
64
|
+
cy.contains('Multiple + chips').click();
|
|
65
|
+
cy.get('#select_media').contains('.v-chip', 'Option 1').should('exist');
|
|
66
|
+
cy.get('#select_media').contains('.v-chip', 'Option 1').find('[data-testid="close-chip"]').click();
|
|
67
|
+
cy.get('#select_media').contains('.v-chip', 'Option 1').should('not.exist');
|
|
68
|
+
cy.get('#select_media input[type="hidden"][value="option1"]').should('not.exist');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('collapses expanded chips back to overflow state', () => {
|
|
72
|
+
cy.on('uncaught:exception', (err) => {
|
|
73
|
+
if (err.message.includes('ResizeObserver')) return false;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
cy.visit(url);
|
|
77
|
+
|
|
78
|
+
cy.contains('Multiple + chips').click();
|
|
79
|
+
|
|
80
|
+
// Initial collapsed state: overflow chip shows "X more"
|
|
81
|
+
cy.get('#select_media .expansion-chip').should('contain.text', 'more');
|
|
82
|
+
cy.get('#select_media').contains('.expansion-chip', 'Show less').should('not.exist');
|
|
83
|
+
|
|
84
|
+
// Expand: click the "X more" chip
|
|
85
|
+
cy.get('#select_media .expansion-chip').click();
|
|
86
|
+
cy.get('body').type('{esc}');
|
|
87
|
+
|
|
88
|
+
// Expanded state: "Show less" chip is visible, "X more" is gone
|
|
89
|
+
cy.get('#select_media .expansion-chip').should('contain.text', 'Show less');
|
|
90
|
+
cy.get('#select_media').contains('.expansion-chip', 'more').should('not.exist');
|
|
91
|
+
|
|
92
|
+
// Collapse: click "Show less" (calls collapseChips)
|
|
93
|
+
cy.get('#select_media .expansion-chip').click();
|
|
94
|
+
cy.get('body').type('{esc}');
|
|
95
|
+
|
|
96
|
+
// Back to collapsed state
|
|
97
|
+
cy.get('#select_media .expansion-chip').should('contain.text', 'more');
|
|
98
|
+
cy.get('#select_media').contains('.expansion-chip', 'Show less').should('not.exist');
|
|
99
|
+
});
|
|
51
100
|
|
|
52
101
|
it('toggles disabled and resets options', () => {
|
|
53
|
-
cy.visit(url)
|
|
54
|
-
|
|
55
|
-
cy.contains('Disable select').click()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
cy.get('#select_media').find('.v-input--disabled').should('exist')
|
|
60
|
-
|
|
61
|
-
cy.contains('
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
cy.get('#select_media').
|
|
66
|
-
|
|
67
|
-
cy.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(comp.spec.options).to.have.length(4)
|
|
75
|
-
expect(comp.spec.options[0].icon.name).to.eq('star')
|
|
76
|
-
expect(comp.fieldModel).to.eq('option1')
|
|
77
|
-
expect(comp.spec.disabled).to.not.eq(true)
|
|
78
|
-
expect(comp.spec.multiple).to.not.eq(true)
|
|
79
|
-
expect(comp.spec.useChips).to.not.eq(true)
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
})
|
|
102
|
+
cy.visit(url);
|
|
103
|
+
|
|
104
|
+
cy.contains('Disable select').click();
|
|
105
|
+
cy.get('#select_media').find('.v-input--disabled').should('exist');
|
|
106
|
+
|
|
107
|
+
cy.contains('Enable select').click();
|
|
108
|
+
cy.get('#select_media').find('.v-input--disabled').should('not.exist');
|
|
109
|
+
|
|
110
|
+
cy.contains('Empty options').click();
|
|
111
|
+
cy.get('#select_media select[hidden] option').should('have.length', 0);
|
|
112
|
+
|
|
113
|
+
cy.contains('Restore defaults').click();
|
|
114
|
+
cy.get('#select_media select[hidden] option').should('have.length', 4);
|
|
115
|
+
cy.get('#select_media').click();
|
|
116
|
+
cy.get('body').type('{esc}');
|
|
117
|
+
cy.get('#select_media input[type="hidden"]').should('have.length', 1).and('have.value', 'option1');
|
|
118
|
+
cy.get('#select_media .v-input--disabled').should('not.exist');
|
|
119
|
+
cy.get('#select_media .v-select--multiple').should('not.exist');
|
|
120
|
+
cy.get('#select_media .v-chip').should('not.exist');
|
|
121
|
+
});
|
|
122
|
+
});
|