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.
Files changed (98) hide show
  1. package/.github/workflows/lint.yml +2 -2
  2. package/.nycrc.json +3 -1
  3. package/README.md +9 -1
  4. package/agent/commands/generate_test.yaml +5 -5
  5. package/components/charts/series.js +23 -11
  6. package/components/component.vue +0 -5
  7. package/components/fields/checkGroup.vue +14 -7
  8. package/components/fields/richText2.vue +33 -3
  9. package/components/fields/upload.vue +5 -3
  10. package/components/mixins/styles.js +0 -1
  11. package/components/popover.vue +107 -78
  12. package/cypress/component/{inputUpload.cy.ts → inputUpload.cy.js} +3 -3
  13. package/cypress/component/{multiUpload.cy.ts → multiUpload.cy.js} +3 -3
  14. package/cypress/component/{placeholderUpload.cy.ts → placeholderUpload.cy.js} +3 -3
  15. package/cypress/component/{testUtils.ts → testUtils.js} +3 -15
  16. package/cypress/e2e/glib-web/{auth.cy.ts → auth.cy.js} +22 -1
  17. package/cypress/e2e/glib-web/{autoValidate.cy.ts → autoValidate.cy.js} +1 -1
  18. package/cypress/e2e/glib-web/{browsers.cy.ts → browsers.cy.js} +1 -1
  19. package/cypress/e2e/glib-web/{calendar.cy.ts → calendar.cy.js} +1 -1
  20. package/cypress/e2e/glib-web/{calendarEmptyData.cy.ts → calendarEmptyData.cy.js} +1 -1
  21. package/cypress/e2e/glib-web/{carousel.cy.ts → carousel.cy.js} +1 -1
  22. package/cypress/e2e/glib-web/{charts.cy.ts → charts.cy.js} +1 -1
  23. package/cypress/e2e/glib-web/{column.cy.ts → column.cy.js} +1 -1
  24. package/cypress/e2e/glib-web/{commands.cy.ts → commands.cy.js} +1 -1
  25. package/cypress/e2e/glib-web/{components.cy.ts → components.cy.js} +1 -1
  26. package/cypress/e2e/glib-web/{cookies.cy.ts → cookies.cy.js} +1 -1
  27. package/cypress/e2e/glib-web/{custom.cy.ts → custom.cy.js} +1 -1
  28. package/cypress/e2e/glib-web/dialog.cy.js +63 -0
  29. package/cypress/e2e/glib-web/{dialogOpen.cy.ts → dialogOpen.cy.js} +1 -1
  30. package/cypress/e2e/glib-web/{dirtyState.cy.ts → dirtyState.cy.js} +9 -24
  31. package/cypress/e2e/glib-web/{display.cy.ts → display.cy.js} +1 -1
  32. package/cypress/e2e/glib-web/{fields.cy.ts → fields.cy.js} +1 -1
  33. package/cypress/e2e/glib-web/{fieldsCaptcha.cy.ts → fieldsCaptcha.cy.js} +1 -1
  34. package/cypress/e2e/glib-web/fieldsCreditCard.cy.js +22 -0
  35. package/cypress/e2e/glib-web/fieldsDateTime.cy.js +48 -0
  36. package/cypress/e2e/glib-web/{fieldsDynamicSelect.cy.ts → fieldsDynamicSelect.cy.js} +1 -1
  37. package/cypress/e2e/glib-web/fieldsLocation.cy.js +40 -0
  38. package/cypress/e2e/glib-web/fieldsOtp.cy.js +68 -0
  39. package/cypress/e2e/glib-web/fieldsPhone.cy.js +87 -0
  40. package/cypress/e2e/glib-web/fieldsRating.cy.js +91 -0
  41. package/cypress/e2e/glib-web/fieldsRichText.cy.js +136 -0
  42. package/cypress/e2e/glib-web/{fieldsSelect.cy.ts → fieldsSelect.cy.js} +1 -1
  43. package/cypress/e2e/glib-web/{fieldsSign.cy.ts → fieldsSign.cy.js} +1 -1
  44. package/cypress/e2e/glib-web/fieldsStripeToken.cy.js +47 -0
  45. package/cypress/e2e/glib-web/{fieldsTimer.cy.ts → fieldsTimer.cy.js} +1 -1
  46. package/cypress/e2e/glib-web/fieldsUpload.cy.js +159 -0
  47. package/cypress/e2e/glib-web/{fieldsUrlFragment.cy.ts → fieldsUrlFragment.cy.js} +1 -1
  48. package/cypress/e2e/glib-web/{flow.cy.ts → flow.cy.js} +1 -1
  49. package/cypress/e2e/glib-web/{form.cy.ts → form.cy.js} +1 -1
  50. package/cypress/e2e/glib-web/{formDynamic.cy.ts → formDynamic.cy.js} +1 -1
  51. package/cypress/e2e/glib-web/{forms.cy.ts → forms.cy.js} +1 -1
  52. package/cypress/e2e/glib-web/{grid.cy.ts → grid.cy.js} +1 -1
  53. package/cypress/e2e/glib-web/{horizontal.cy.ts → horizontal.cy.js} +1 -1
  54. package/cypress/e2e/glib-web/{http.cy.ts → http.cy.js} +1 -1
  55. package/cypress/e2e/glib-web/{image.cy.ts → image.cy.js} +1 -1
  56. package/cypress/e2e/glib-web/{lifecycle.cy.ts → lifecycle.cy.js} +1 -1
  57. package/cypress/e2e/glib-web/{list.cy.ts → list.cy.js} +1 -1
  58. package/cypress/e2e/glib-web/{listEditable.cy.ts → listEditable.cy.js} +1 -1
  59. package/cypress/e2e/glib-web/{listsAppend.cy.ts → listsAppend.cy.js} +1 -1
  60. package/cypress/e2e/glib-web/{logicsSet.cy.ts → logicsSet.cy.js} +1 -1
  61. package/cypress/e2e/glib-web/{multimediaVideo.cy.ts → multimediaVideo.cy.js} +1 -1
  62. package/cypress/e2e/glib-web/{pagination.cy.ts → pagination.cy.js} +1 -1
  63. package/cypress/e2e/glib-web/{panels.cy.ts → panels.cy.js} +1 -1
  64. package/cypress/e2e/glib-web/{panelsBulkEdit2.cy.ts → panelsBulkEdit2.cy.js} +1 -1
  65. package/cypress/e2e/glib-web/{popovers.cy.ts → popovers.cy.js} +1 -1
  66. package/cypress/e2e/glib-web/{progressCircle.cy.ts → progressCircle.cy.js} +1 -1
  67. package/cypress/e2e/glib-web/{responsive.cy.ts → responsive.cy.js} +1 -1
  68. package/cypress/e2e/glib-web/{scroll.cy.ts → scroll.cy.js} +1 -1
  69. package/cypress/e2e/glib-web/{selectable.cy.ts → selectable.cy.js} +1 -1
  70. package/cypress/e2e/glib-web/{sheets.cy.ts → sheets.cy.js} +1 -1
  71. package/cypress/e2e/glib-web/{snackbars.cy.ts → snackbars.cy.js} +1 -1
  72. package/cypress/e2e/glib-web/{split.cy.ts → split.cy.js} +1 -1
  73. package/cypress/e2e/glib-web/{storageItems.cy.ts → storageItems.cy.js} +1 -1
  74. package/cypress/e2e/glib-web/{table.cy.ts → table.cy.js} +1 -1
  75. package/cypress/e2e/glib-web/{timeline.cy.ts → timeline.cy.js} +1 -1
  76. package/cypress/e2e/glib-web/{timeouts.cy.ts → timeouts.cy.js} +1 -1
  77. package/cypress/e2e/glib-web/{ul.cy.ts → ul.cy.js} +1 -1
  78. package/cypress/e2e/glib-web/{vertical.cy.ts → vertical.cy.js} +1 -1
  79. package/cypress/e2e/glib-web/{web.cy.ts → web.cy.js} +1 -1
  80. package/cypress/e2e/glib-web/window.cy.js +21 -0
  81. package/cypress/e2e/glib-web/{windows.cy.ts → windows.cy.js} +34 -2
  82. package/cypress/helper.js +19 -0
  83. package/cypress/support/{commands.ts → commands.js} +2 -2
  84. package/cypress/support/component.js +27 -0
  85. package/cypress/support/{e2e.ts → e2e.js} +18 -3
  86. package/{cypress.config.ts → cypress.config.js} +3 -2
  87. package/cypress.yml.example +6 -7
  88. package/doc/TESTING.md +2 -2
  89. package/package.json +1 -1
  90. package/components/composable/dropable.js +0 -52
  91. package/components/fields/googlePlace.vue +0 -162
  92. package/components/mixins/tooltip.js +0 -57
  93. package/cypress/e2e/glib-web/dialog.cy.ts +0 -25
  94. package/cypress/e2e/glib-web/fieldsUpload.cy.ts +0 -48
  95. package/cypress/e2e/glib-web/multiupload.cy.ts +0 -25
  96. package/cypress/e2e/glib-web/window.cy.ts +0 -14
  97. package/cypress/helper.ts +0 -7
  98. 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
+ })
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('fields_select')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('fields_sign')
4
4
 
@@ -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
+ })
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('fields_timer')
4
4
 
@@ -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
+ })
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('fields_url_fragment')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('flow')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
  const url = testPageUrl('form')
3
3
 
4
4
  describe('form', () => {
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
  const url = testPageUrl('form_dynamic')
3
3
 
4
4
  describe('form dynamic', () => {
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('forms')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('grid')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('horizontal')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('http')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('image')
4
4
  const imageSelector = '#image_main'
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
  const url = testPageUrl('lifecycle')
3
3
 
4
4
  describe('glib lifecycle hooks', () => {
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('list')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('list_editable')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('lists_append')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
  const url = testPageUrl('logics_set')
3
3
 
4
4
  describe('logics_set', () => {
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('multimedia_video')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('pagination')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('panels')
4
4
  const pageBodySelector = '#page_body'
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('panels_bulkEdit2')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('popovers')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('progressCircle')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('responsive')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('scroll')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
  const url = testPageUrl('selectable')
3
3
 
4
4
  describe("selectable", () => {
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('sheets')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('snackbars')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('split')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('storage_items')
4
4
 
@@ -1,4 +1,4 @@
1
- import { testPageUrl } from "../../helper"
1
+ import { testPageUrl } from "../../helper.js"
2
2
 
3
3
  const url = testPageUrl('table')
4
4