glib-web 4.44.6 → 5.0.4
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/.github/workflows/lint.yml +2 -2
- package/.nycrc.json +3 -1
- package/README.md +9 -1
- package/agent/commands/generate_test.yaml +5 -5
- package/components/charts/series.js +23 -11
- package/components/component.vue +0 -5
- package/components/fields/checkGroup.vue +14 -7
- package/components/fields/richText2.vue +33 -3
- package/components/fields/upload.vue +5 -3
- package/components/mixins/styles.js +0 -1
- package/components/popover.vue +107 -78
- package/cypress/component/{inputUpload.cy.ts → inputUpload.cy.js} +3 -3
- package/cypress/component/{multiUpload.cy.ts → multiUpload.cy.js} +3 -3
- package/cypress/component/{placeholderUpload.cy.ts → placeholderUpload.cy.js} +3 -3
- package/cypress/component/{testUtils.ts → testUtils.js} +3 -15
- package/cypress/e2e/glib-web/{auth.cy.ts → auth.cy.js} +22 -1
- package/cypress/e2e/glib-web/{autoValidate.cy.ts → autoValidate.cy.js} +1 -1
- package/cypress/e2e/glib-web/{browsers.cy.ts → browsers.cy.js} +1 -1
- package/cypress/e2e/glib-web/{calendar.cy.ts → calendar.cy.js} +1 -1
- package/cypress/e2e/glib-web/{calendarEmptyData.cy.ts → calendarEmptyData.cy.js} +1 -1
- package/cypress/e2e/glib-web/{carousel.cy.ts → carousel.cy.js} +1 -1
- package/cypress/e2e/glib-web/{charts.cy.ts → charts.cy.js} +1 -1
- package/cypress/e2e/glib-web/{column.cy.ts → column.cy.js} +1 -1
- package/cypress/e2e/glib-web/{commands.cy.ts → commands.cy.js} +1 -1
- package/cypress/e2e/glib-web/{components.cy.ts → components.cy.js} +1 -1
- package/cypress/e2e/glib-web/{cookies.cy.ts → cookies.cy.js} +1 -1
- package/cypress/e2e/glib-web/{custom.cy.ts → custom.cy.js} +1 -1
- package/cypress/e2e/glib-web/dialog.cy.js +63 -0
- package/cypress/e2e/glib-web/{dialogOpen.cy.ts → dialogOpen.cy.js} +1 -1
- package/cypress/e2e/glib-web/{dirtyState.cy.ts → dirtyState.cy.js} +9 -24
- package/cypress/e2e/glib-web/{display.cy.ts → display.cy.js} +1 -1
- package/cypress/e2e/glib-web/{fields.cy.ts → fields.cy.js} +1 -1
- package/cypress/e2e/glib-web/{fieldsCaptcha.cy.ts → fieldsCaptcha.cy.js} +1 -1
- package/cypress/e2e/glib-web/fieldsCreditCard.cy.js +22 -0
- package/cypress/e2e/glib-web/fieldsDateTime.cy.js +48 -0
- package/cypress/e2e/glib-web/{fieldsDynamicSelect.cy.ts → fieldsDynamicSelect.cy.js} +1 -1
- package/cypress/e2e/glib-web/fieldsLocation.cy.js +40 -0
- package/cypress/e2e/glib-web/fieldsOtp.cy.js +68 -0
- package/cypress/e2e/glib-web/fieldsPhone.cy.js +87 -0
- package/cypress/e2e/glib-web/fieldsRating.cy.js +91 -0
- package/cypress/e2e/glib-web/fieldsRichText.cy.js +136 -0
- package/cypress/e2e/glib-web/{fieldsSelect.cy.ts → fieldsSelect.cy.js} +1 -1
- package/cypress/e2e/glib-web/{fieldsSign.cy.ts → fieldsSign.cy.js} +1 -1
- package/cypress/e2e/glib-web/fieldsStripeToken.cy.js +47 -0
- package/cypress/e2e/glib-web/{fieldsTimer.cy.ts → fieldsTimer.cy.js} +1 -1
- package/cypress/e2e/glib-web/fieldsUpload.cy.js +159 -0
- package/cypress/e2e/glib-web/{fieldsUrlFragment.cy.ts → fieldsUrlFragment.cy.js} +1 -1
- package/cypress/e2e/glib-web/{flow.cy.ts → flow.cy.js} +1 -1
- package/cypress/e2e/glib-web/{form.cy.ts → form.cy.js} +1 -1
- package/cypress/e2e/glib-web/{formDynamic.cy.ts → formDynamic.cy.js} +1 -1
- package/cypress/e2e/glib-web/{forms.cy.ts → forms.cy.js} +1 -1
- package/cypress/e2e/glib-web/{grid.cy.ts → grid.cy.js} +1 -1
- package/cypress/e2e/glib-web/{horizontal.cy.ts → horizontal.cy.js} +1 -1
- package/cypress/e2e/glib-web/{http.cy.ts → http.cy.js} +1 -1
- package/cypress/e2e/glib-web/{image.cy.ts → image.cy.js} +1 -1
- package/cypress/e2e/glib-web/{lifecycle.cy.ts → lifecycle.cy.js} +1 -1
- package/cypress/e2e/glib-web/{list.cy.ts → list.cy.js} +1 -1
- package/cypress/e2e/glib-web/{listEditable.cy.ts → listEditable.cy.js} +1 -1
- package/cypress/e2e/glib-web/{listsAppend.cy.ts → listsAppend.cy.js} +1 -1
- package/cypress/e2e/glib-web/{logicsSet.cy.ts → logicsSet.cy.js} +1 -1
- package/cypress/e2e/glib-web/{multimediaVideo.cy.ts → multimediaVideo.cy.js} +1 -1
- package/cypress/e2e/glib-web/{pagination.cy.ts → pagination.cy.js} +1 -1
- package/cypress/e2e/glib-web/{panels.cy.ts → panels.cy.js} +1 -1
- package/cypress/e2e/glib-web/{panelsBulkEdit2.cy.ts → panelsBulkEdit2.cy.js} +1 -1
- package/cypress/e2e/glib-web/{popovers.cy.ts → popovers.cy.js} +1 -1
- package/cypress/e2e/glib-web/{progressCircle.cy.ts → progressCircle.cy.js} +1 -1
- package/cypress/e2e/glib-web/{responsive.cy.ts → responsive.cy.js} +1 -1
- package/cypress/e2e/glib-web/{scroll.cy.ts → scroll.cy.js} +1 -1
- package/cypress/e2e/glib-web/{selectable.cy.ts → selectable.cy.js} +1 -1
- package/cypress/e2e/glib-web/{sheets.cy.ts → sheets.cy.js} +1 -1
- package/cypress/e2e/glib-web/{snackbars.cy.ts → snackbars.cy.js} +1 -1
- package/cypress/e2e/glib-web/{split.cy.ts → split.cy.js} +1 -1
- package/cypress/e2e/glib-web/{storageItems.cy.ts → storageItems.cy.js} +1 -1
- package/cypress/e2e/glib-web/{table.cy.ts → table.cy.js} +1 -1
- package/cypress/e2e/glib-web/{timeline.cy.ts → timeline.cy.js} +1 -1
- package/cypress/e2e/glib-web/{timeouts.cy.ts → timeouts.cy.js} +1 -1
- package/cypress/e2e/glib-web/{ul.cy.ts → ul.cy.js} +1 -1
- package/cypress/e2e/glib-web/{vertical.cy.ts → vertical.cy.js} +1 -1
- package/cypress/e2e/glib-web/{web.cy.ts → web.cy.js} +1 -1
- package/cypress/e2e/glib-web/window.cy.js +21 -0
- package/cypress/e2e/glib-web/{windows.cy.ts → windows.cy.js} +34 -2
- package/cypress/helper.js +19 -0
- package/cypress/support/{commands.ts → commands.js} +2 -2
- package/cypress/support/component.js +27 -0
- package/cypress/support/{e2e.ts → e2e.js} +18 -3
- package/{cypress.config.ts → cypress.config.js} +3 -2
- package/cypress.yml.example +6 -7
- package/doc/TESTING.md +2 -2
- package/package.json +1 -1
- package/components/composable/dropable.js +0 -52
- package/components/fields/googlePlace.vue +0 -162
- package/components/mixins/tooltip.js +0 -57
- package/cypress/e2e/glib-web/dialog.cy.ts +0 -25
- package/cypress/e2e/glib-web/fieldsUpload.cy.ts +0 -48
- package/cypress/e2e/glib-web/multiupload.cy.ts +0 -25
- package/cypress/e2e/glib-web/window.cy.ts +0 -14
- package/cypress/helper.ts +0 -7
- package/cypress/support/component.ts +0 -12
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper.js"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_rating')
|
|
4
|
+
|
|
5
|
+
describe('fields_rating', () => {
|
|
6
|
+
it('switches rating variants', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Full increments').click()
|
|
10
|
+
withComponent('rating_main', (comp) => {
|
|
11
|
+
expect(comp.spec.halfIncrements).to.not.eq(true)
|
|
12
|
+
expect(comp.spec.color).to.eq('primary')
|
|
13
|
+
expect(comp.spec.size).to.eq(24)
|
|
14
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
15
|
+
expect(comp.fieldModel).to.eq(4)
|
|
16
|
+
})
|
|
17
|
+
cy.get('#rating_variant_status').should('contain.text', 'Variant: full increments (primary)')
|
|
18
|
+
|
|
19
|
+
cy.contains('Half increments').click()
|
|
20
|
+
withComponent('rating_main', (comp) => {
|
|
21
|
+
expect(comp.spec.halfIncrements).to.eq(true)
|
|
22
|
+
expect(comp.spec.color).to.eq('secondary')
|
|
23
|
+
expect(comp.spec.size).to.eq(24)
|
|
24
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
25
|
+
expect(comp.fieldModel).to.eq(3.5)
|
|
26
|
+
})
|
|
27
|
+
cy.get('#rating_variant_status').should('contain.text', 'Variant: half increments (secondary)')
|
|
28
|
+
|
|
29
|
+
cy.contains('Large size').click()
|
|
30
|
+
withComponent('rating_main', (comp) => {
|
|
31
|
+
expect(comp.spec.halfIncrements).to.eq(true)
|
|
32
|
+
expect(comp.spec.color).to.eq('ternary')
|
|
33
|
+
expect(comp.spec.size).to.eq(40)
|
|
34
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
35
|
+
expect(comp.fieldModel).to.eq(4.5)
|
|
36
|
+
})
|
|
37
|
+
cy.get('#rating_variant_status').should('contain.text', 'Variant: large size (ternary)')
|
|
38
|
+
|
|
39
|
+
cy.contains('Read only').click()
|
|
40
|
+
withComponent('rating_main', (comp) => {
|
|
41
|
+
expect(comp.spec.readOnly).to.eq(true)
|
|
42
|
+
expect(comp.fieldModel).to.eq(5)
|
|
43
|
+
})
|
|
44
|
+
cy.get('#rating_variant_status').should('contain.text', 'Variant: read-only')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('updates rating actions', () => {
|
|
48
|
+
cy.visit(url)
|
|
49
|
+
|
|
50
|
+
cy.contains('Set to 2').click()
|
|
51
|
+
withComponent('rating_main', (comp) => {
|
|
52
|
+
expect(comp.fieldModel).to.eq(2)
|
|
53
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
54
|
+
})
|
|
55
|
+
cy.get('#rating_status').should('contain.text', 'Status: rating changed')
|
|
56
|
+
|
|
57
|
+
cy.contains('Set to 4.5').click()
|
|
58
|
+
withComponent('rating_main', (comp) => {
|
|
59
|
+
expect(comp.fieldModel).to.eq(4.5)
|
|
60
|
+
expect(comp.spec.halfIncrements).to.eq(true)
|
|
61
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
62
|
+
})
|
|
63
|
+
cy.get('#rating_status').should('contain.text', 'Status: rating changed')
|
|
64
|
+
|
|
65
|
+
cy.contains('Clear rating').click()
|
|
66
|
+
withComponent('rating_main', (comp) => {
|
|
67
|
+
expect(comp.fieldModel).to.eq('')
|
|
68
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
69
|
+
})
|
|
70
|
+
cy.get('#rating_status').should('contain.text', 'Status: rating changed')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('toggles disabled and size', () => {
|
|
74
|
+
cy.visit(url)
|
|
75
|
+
|
|
76
|
+
cy.contains('Disable rating').click()
|
|
77
|
+
withComponent('rating_main', (comp) => {
|
|
78
|
+
expect(comp.spec.disabled).to.eq(true)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
cy.contains('Enable rating').click()
|
|
82
|
+
withComponent('rating_main', (comp) => {
|
|
83
|
+
expect(comp.spec.disabled).to.not.eq(true)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
cy.contains('Small size').click()
|
|
87
|
+
withComponent('rating_main', (comp) => {
|
|
88
|
+
expect(comp.spec.size).to.eq(18)
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper.js"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_richText')
|
|
4
|
+
const csvFixtureContents = [
|
|
5
|
+
'month,electricity_usage,gas_usage,sources,compliant',
|
|
6
|
+
'January,120,10,Generators,yes',
|
|
7
|
+
'February,150,12,Solar Panels,no'
|
|
8
|
+
].join('\n')
|
|
9
|
+
|
|
10
|
+
describe('fields_richText', () => {
|
|
11
|
+
it('switches output variants', () => {
|
|
12
|
+
cy.visit(url)
|
|
13
|
+
|
|
14
|
+
cy.contains('Markdown output').click()
|
|
15
|
+
withComponent('rich_text_main', (comp) => {
|
|
16
|
+
expect(comp.spec.produce).to.eq('markdown')
|
|
17
|
+
expect(comp.spec.accept).to.eq('markdown')
|
|
18
|
+
})
|
|
19
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: markdown output')
|
|
20
|
+
|
|
21
|
+
// cy.contains('HTML output').click()
|
|
22
|
+
// withComponent('rich_text_main', (comp) => {
|
|
23
|
+
// expect(comp.spec.produce).to.eq('html')
|
|
24
|
+
// expect(comp.spec.accept).to.eq('html')
|
|
25
|
+
// })
|
|
26
|
+
// cy.get('#rich_text_variant_status').should('contain.text', 'Variant: HTML output')
|
|
27
|
+
|
|
28
|
+
cy.contains('No uploader').click()
|
|
29
|
+
withComponent('rich_text_main', (comp) => {
|
|
30
|
+
expect(comp.spec.imageUploader).to.not.exist
|
|
31
|
+
})
|
|
32
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: uploader removed')
|
|
33
|
+
|
|
34
|
+
cy.contains('Restore uploader').click()
|
|
35
|
+
withComponent('rich_text_main', (comp) => {
|
|
36
|
+
expect(comp.spec.imageUploader).to.exist
|
|
37
|
+
})
|
|
38
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: uploader restored')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// it('inserts template content', () => {
|
|
42
|
+
// cy.visit(url)
|
|
43
|
+
|
|
44
|
+
// cy.contains('Insert template').click()
|
|
45
|
+
// cy.get('#rich_text_status').should('contain.text', 'Status: content changed')
|
|
46
|
+
|
|
47
|
+
// cy.get('input[name="user[rich_text]"]').invoke('val').should('include', 'Quick update')
|
|
48
|
+
// })
|
|
49
|
+
|
|
50
|
+
it('toggles editor state', () => {
|
|
51
|
+
cy.visit(url)
|
|
52
|
+
|
|
53
|
+
cy.contains('Disable editor').click()
|
|
54
|
+
withComponent('rich_text_main', (comp) => {
|
|
55
|
+
expect(comp.spec.disabled).to.eq(true)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
cy.contains('Enable editor').click()
|
|
59
|
+
withComponent('rich_text_main', (comp) => {
|
|
60
|
+
expect(comp.spec.disabled).to.not.eq(true)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
cy.contains('Toggle debug').click()
|
|
64
|
+
withComponent('rich_text_main', (comp) => {
|
|
65
|
+
expect(comp.spec.debug).to.eq(false)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
cy.contains('Enable debug').click()
|
|
69
|
+
withComponent('rich_text_main', (comp) => {
|
|
70
|
+
expect(comp.spec.debug).to.eq(true)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('uploads files on drop and paste', () => {
|
|
75
|
+
cy.visit(url)
|
|
76
|
+
|
|
77
|
+
let uploadIndex = 0
|
|
78
|
+
cy.window().then((win) => {
|
|
79
|
+
const comp = win.GLib.component.findById('rich_text_main')
|
|
80
|
+
expect(comp).to.exist
|
|
81
|
+
const uploader = comp.spec.imageUploader
|
|
82
|
+
|
|
83
|
+
cy.intercept('POST', uploader.directUploadUrl, (req) => {
|
|
84
|
+
uploadIndex += 1
|
|
85
|
+
req.reply({
|
|
86
|
+
statusCode: 200,
|
|
87
|
+
body: {
|
|
88
|
+
signed_id: `signed-${uploadIndex}`,
|
|
89
|
+
direct_upload: {
|
|
90
|
+
url: `https://example.com/upload-${uploadIndex}`,
|
|
91
|
+
headers: { 'Content-Type': 'text/csv' }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
}).as('directUpload')
|
|
96
|
+
|
|
97
|
+
cy.intercept('PUT', 'https://example.com/upload-*', { statusCode: 200, body: '' }).as('directUploadStore')
|
|
98
|
+
cy.intercept('POST', uploader.blobUrlGenerator, { statusCode: 200, body: { url: 'https://example.com/blob' } }).as('blobUrl')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
cy.window().then((win) => {
|
|
102
|
+
const file = new win.File([csvFixtureContents], 'bulk_edit.csv', { type: 'text/csv' })
|
|
103
|
+
const dataTransfer = new win.DataTransfer()
|
|
104
|
+
dataTransfer.items.add(file)
|
|
105
|
+
cy.get('#rich_text_main .ql-editor').trigger('drop', { dataTransfer })
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
cy.wait('@directUpload')
|
|
109
|
+
cy.wait('@directUploadStore')
|
|
110
|
+
cy.wait('@blobUrl')
|
|
111
|
+
cy.get('input[name="user[images_attributes][]"]').should('have.length', 1)
|
|
112
|
+
cy.get('input[name="user[images_attributes][]"]').first().should('have.value', 'signed-1')
|
|
113
|
+
|
|
114
|
+
cy.window().then((win) => {
|
|
115
|
+
const file = new win.File([csvFixtureContents], 'bulk_edit.csv', { type: 'text/csv' })
|
|
116
|
+
const clipboardData = new win.DataTransfer()
|
|
117
|
+
clipboardData.items.add(file)
|
|
118
|
+
cy.get('#rich_text_main .ql-editor').trigger('paste', { clipboardData })
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
cy.wait('@directUpload')
|
|
122
|
+
cy.wait('@directUploadStore')
|
|
123
|
+
cy.wait('@blobUrl')
|
|
124
|
+
cy.get('input[name="user[images_attributes][]"]').should('have.length', 2)
|
|
125
|
+
cy.get('input[name="user[images_attributes][]"]').eq(1).should('have.value', 'signed-2')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('shows mention list when typing a person', () => {
|
|
129
|
+
cy.visit(url)
|
|
130
|
+
|
|
131
|
+
cy.get('#rich_text_main .ql-editor').click().type('{end} @jo')
|
|
132
|
+
cy.get('.ql-mention-list-container').should('be.visible')
|
|
133
|
+
cy.get('.ql-mention-list-container').should('contain.text', 'John Doe')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper.js"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_stripeToken')
|
|
4
|
+
|
|
5
|
+
describe('fields_stripeToken', () => {
|
|
6
|
+
it('switches style variants', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Default style').click()
|
|
10
|
+
withComponent('stripe_token_basic', (comp) => {
|
|
11
|
+
expect(comp.spec.styleClass).to.not.exist
|
|
12
|
+
expect(comp.spec.label).to.eq('Card details')
|
|
13
|
+
expect(comp.spec.hint).to.not.exist
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
cy.contains('Outlined').click()
|
|
17
|
+
withComponent('stripe_token_basic', (comp) => {
|
|
18
|
+
expect(comp.spec.styleClass).to.eq('outlined')
|
|
19
|
+
expect(comp.spec.label).to.eq('Card details')
|
|
20
|
+
expect(comp.spec.hint).to.not.exist
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
cy.contains('Individual').click()
|
|
24
|
+
withComponent('stripe_token_basic', (comp) => {
|
|
25
|
+
expect(comp.spec.styleClass).to.eq('individual')
|
|
26
|
+
expect(comp.spec.label).to.eq('Card details')
|
|
27
|
+
expect(comp.spec.hint).to.eq('Personal card')
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('submits the form', () => {
|
|
32
|
+
cy.visit(url)
|
|
33
|
+
|
|
34
|
+
cy.contains('Submit').click()
|
|
35
|
+
|
|
36
|
+
cy.get('body').then(($body) => {
|
|
37
|
+
if ($body.find('.v-dialog').length) {
|
|
38
|
+
cy.get('.v-dialog').should('contain.text', 'Method: POST')
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if ($body.find('.unformatted').length) {
|
|
43
|
+
cy.get('.unformatted').should('contain.text', 'Method: POST')
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { testPageUrl } from "../../helper.js"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_upload')
|
|
4
|
+
|
|
5
|
+
const getRealComponent = (win, component) => {
|
|
6
|
+
const { isObject, isNotNull } = win.Utils.type
|
|
7
|
+
let realComp = component
|
|
8
|
+
|
|
9
|
+
while (isObject(realComp) && isNotNull(realComp.$refs?.delegate)) {
|
|
10
|
+
realComp = realComp.$refs.delegate
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return realComp
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('fields_upload', () => {
|
|
17
|
+
it('invokes upload triggers and resets', () => {
|
|
18
|
+
cy.visit(url)
|
|
19
|
+
|
|
20
|
+
cy.window().then((win) => {
|
|
21
|
+
const basicComp = getRealComponent(win, win.GLib.component.findById('fields_upload_basic'))
|
|
22
|
+
const filesComp = getRealComponent(win, win.GLib.component.findById('fields_upload_files'))
|
|
23
|
+
|
|
24
|
+
cy.wrap(basicComp).should('exist')
|
|
25
|
+
cy.wrap(filesComp).should('exist')
|
|
26
|
+
|
|
27
|
+
cy.spy(basicComp, 'trigger').as('basicTrigger')
|
|
28
|
+
cy.spy(basicComp, 'reset').as('basicReset')
|
|
29
|
+
cy.spy(filesComp, 'trigger').as('filesTrigger')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
cy.contains('Trigger').click()
|
|
33
|
+
cy.get('@basicTrigger').should('have.been.calledOnce')
|
|
34
|
+
|
|
35
|
+
cy.contains('Reset').click()
|
|
36
|
+
cy.get('@basicReset').should('have.been.calledOnce')
|
|
37
|
+
|
|
38
|
+
cy.contains('Select file').click()
|
|
39
|
+
cy.get('@filesTrigger').should('have.been.calledOnce')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('handles multi progress view drag and drop uploads', () => {
|
|
43
|
+
const htmlUploadUrl = 'http://localhost:3000/glib/json_ui_garage?path=forms%2Ffile_upload_new&mode=html'
|
|
44
|
+
let uploadIndex = 0
|
|
45
|
+
const pngBase64 =
|
|
46
|
+
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII='
|
|
47
|
+
const pngFile = {
|
|
48
|
+
contents: Cypress.Buffer.from(pngBase64, 'base64'),
|
|
49
|
+
fileName: 'upload.png',
|
|
50
|
+
mimeType: 'image/png'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
cy.intercept('POST', /\/(glib\/glib_direct_uploads|rails\/active_storage\/direct_uploads)$/, (req) => {
|
|
54
|
+
uploadIndex += 1
|
|
55
|
+
req.reply({
|
|
56
|
+
statusCode: 200,
|
|
57
|
+
body: {
|
|
58
|
+
signed_id: `signed-${uploadIndex}`,
|
|
59
|
+
direct_upload: {
|
|
60
|
+
url: 'https://example.com/rails/active_storage/blobs/upload',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': 'text/plain'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
}).as('directUploadCreate')
|
|
68
|
+
|
|
69
|
+
cy.intercept('PUT', 'https://example.com/rails/active_storage/blobs/upload', {
|
|
70
|
+
statusCode: 200
|
|
71
|
+
}).as('directUploadStore')
|
|
72
|
+
|
|
73
|
+
cy.visit(url)
|
|
74
|
+
|
|
75
|
+
cy.window()
|
|
76
|
+
.should((win) => {
|
|
77
|
+
const multiComp = getRealComponent(win, win.GLib.component.findById('fields_upload_multiprogress'))
|
|
78
|
+
expect(multiComp, 'multi progress component').to.exist
|
|
79
|
+
expect(multiComp.$el, 'multi progress element').to.exist
|
|
80
|
+
expect(multiComp.$el.querySelector('.gdrop-file'), 'multi progress dropzone').to.exist
|
|
81
|
+
})
|
|
82
|
+
.then((win) => {
|
|
83
|
+
const multiComp = getRealComponent(win, win.GLib.component.findById('fields_upload_multiprogress'))
|
|
84
|
+
cy.wrap(multiComp.$el).as('multiRoot')
|
|
85
|
+
cy.wrap(multiComp.$el.querySelector('.gdrop-file')).as('dropzone')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
cy.get('@dropzone').should('have.class', 'border-[2px]')
|
|
89
|
+
cy.get('@dropzone').trigger('drag')
|
|
90
|
+
cy.get('@dropzone').trigger('dragover')
|
|
91
|
+
cy.get('@dropzone').should('have.class', 'border-[4px]').and('not.have.class', 'border-[2px]')
|
|
92
|
+
cy.get('@dropzone').trigger('dragleave')
|
|
93
|
+
cy.get('@dropzone').should('have.class', 'border-[2px]')
|
|
94
|
+
|
|
95
|
+
cy.get('@dropzone').click({ force: true })
|
|
96
|
+
cy.get('@multiRoot').find('input[type="file"]').should('exist')
|
|
97
|
+
|
|
98
|
+
cy.get('@dropzone').selectFile(
|
|
99
|
+
pngFile,
|
|
100
|
+
{ action: 'drag-drop' }
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
cy.wait('@directUploadCreate')
|
|
104
|
+
cy.wait('@directUploadStore')
|
|
105
|
+
cy.get('@multiRoot')
|
|
106
|
+
.find('input[type="hidden"][name="user[file_input_multiprogress][]"]')
|
|
107
|
+
.should('have.length', 1)
|
|
108
|
+
|
|
109
|
+
cy.get('@dropzone').selectFile(
|
|
110
|
+
{ ...pngFile, fileName: 'second.png' },
|
|
111
|
+
{ action: 'drag-drop' }
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
cy.wait('@directUploadCreate')
|
|
115
|
+
cy.wait('@directUploadStore')
|
|
116
|
+
|
|
117
|
+
cy.get('@multiRoot').find('.guploaded-file .file-container').should('have.length', 2)
|
|
118
|
+
cy.get('@multiRoot')
|
|
119
|
+
.find('input[type="hidden"][name="user[file_input_multiprogress][]"]')
|
|
120
|
+
.should('have.length', 2)
|
|
121
|
+
cy.get('@multiRoot').find('.guploaded-file .close-btn').first().click()
|
|
122
|
+
cy.get('@multiRoot').find('.guploaded-file .file-container').should('have.length', 1)
|
|
123
|
+
cy.get('@multiRoot')
|
|
124
|
+
.find('input[type="hidden"][name="user[file_input_multiprogress][]"]')
|
|
125
|
+
.should('have.length', 1)
|
|
126
|
+
|
|
127
|
+
cy.visit(htmlUploadUrl)
|
|
128
|
+
|
|
129
|
+
cy.window()
|
|
130
|
+
.should((win) => {
|
|
131
|
+
const multiComp = getRealComponent(win, win.GLib.component.findById('mp1'))
|
|
132
|
+
expect(multiComp, 'html multi progress component').to.exist
|
|
133
|
+
expect(multiComp.$el, 'html multi progress element').to.exist
|
|
134
|
+
expect(multiComp.$el.querySelector('.gdrop-file'), 'html multi progress dropzone').to.exist
|
|
135
|
+
})
|
|
136
|
+
.then((win) => {
|
|
137
|
+
const multiComp = getRealComponent(win, win.GLib.component.findById('mp1'))
|
|
138
|
+
cy.wrap(multiComp.$el).as('htmlMultiRoot')
|
|
139
|
+
cy.wrap(multiComp.$el.querySelector('.gdrop-file')).as('htmlDropzone')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
cy.get('@htmlDropzone').selectFile(
|
|
143
|
+
{ ...pngFile, fileName: 'html-mode.png' },
|
|
144
|
+
{ action: 'drag-drop' }
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
cy.get('@htmlMultiRoot').find('.guploaded-file .file-container').should('have.length', 1)
|
|
148
|
+
cy.get('@htmlMultiRoot')
|
|
149
|
+
.find('input[type="hidden"][name="user[file_multiprogress1][]"]')
|
|
150
|
+
.should('not.exist')
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('submits the form', () => {
|
|
154
|
+
cy.visit(url)
|
|
155
|
+
|
|
156
|
+
cy.contains('submit').click()
|
|
157
|
+
cy.get('.unformatted').should('contain.text', 'Method: POST')
|
|
158
|
+
})
|
|
159
|
+
})
|