glib-web 4.44.6 → 5.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/.github/workflows/lint.yml +2 -2
- package/.nycrc.json +3 -1
- package/README.md +1 -0
- 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/e2e/glib-web/auth.cy.ts +21 -0
- package/cypress/e2e/glib-web/dialog.cy.ts +39 -1
- package/cypress/e2e/glib-web/dirtyState.cy.ts +8 -23
- package/cypress/e2e/glib-web/fieldsCreditCard.cy.ts +22 -0
- package/cypress/e2e/glib-web/fieldsDateTime.cy.ts +48 -0
- package/cypress/e2e/glib-web/fieldsLocation.cy.ts +40 -0
- package/cypress/e2e/glib-web/fieldsOtp.cy.ts +68 -0
- package/cypress/e2e/glib-web/fieldsPhone.cy.ts +87 -0
- package/cypress/e2e/glib-web/fieldsRating.cy.ts +91 -0
- package/cypress/e2e/glib-web/fieldsRichText.cy.ts +137 -0
- package/cypress/e2e/glib-web/fieldsStripeToken.cy.ts +47 -0
- package/cypress/e2e/glib-web/fieldsUpload.cy.ts +111 -0
- package/cypress/e2e/glib-web/window.cy.ts +13 -6
- package/cypress/e2e/glib-web/windows.cy.ts +33 -1
- package/cypress/helper.ts +13 -1
- package/cypress/support/component.ts +15 -0
- package/cypress/support/e2e.ts +15 -0
- 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/multiupload.cy.ts +0 -25
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_date_time')
|
|
4
|
+
|
|
5
|
+
describe('fields_date_time', () => {
|
|
6
|
+
it('updates date actions', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Set today + 1 week').click()
|
|
10
|
+
cy.get('#date_status').should('contain.text', 'Date changed')
|
|
11
|
+
|
|
12
|
+
cy.contains('Clear date').click()
|
|
13
|
+
cy.get('#date_status').should('contain.text', 'Date changed')
|
|
14
|
+
cy.get('input[name="user[date_basic]"]').should('have.value', '')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('updates datetime actions', () => {
|
|
18
|
+
cy.visit(url)
|
|
19
|
+
|
|
20
|
+
cy.contains('Set datetime (evening)').click()
|
|
21
|
+
cy.get('#datetime_status').should('contain.text', 'Datetime changed')
|
|
22
|
+
cy.get('input[name="user[datetime_basic]"]').should('have.value', '2024-12-12T18:45')
|
|
23
|
+
|
|
24
|
+
cy.contains('Clear datetime').click()
|
|
25
|
+
cy.get('#datetime_status').should('contain.text', 'Datetime changed')
|
|
26
|
+
cy.get('input[name="user[datetime_basic]"]').should('have.value', '')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('toggles templates and disabled state', () => {
|
|
30
|
+
cy.visit(url)
|
|
31
|
+
|
|
32
|
+
cy.contains('Disable date').click()
|
|
33
|
+
cy.get('#date_basic').find('.v-input--disabled').should('exist')
|
|
34
|
+
|
|
35
|
+
cy.contains('Enable date').click()
|
|
36
|
+
cy.get('#date_basic').find('.v-input--disabled').should('not.exist')
|
|
37
|
+
|
|
38
|
+
cy.contains('Use text template').click()
|
|
39
|
+
withComponent('datetime_plain', (comp) => {
|
|
40
|
+
expect(comp.spec.template.type).to.eq('text')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
cy.contains('Restore plain template').click()
|
|
44
|
+
withComponent('datetime_plain', (comp) => {
|
|
45
|
+
expect(comp.spec.template.type).to.eq('plain')
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { testPageUrl } from "../../helper"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_location')
|
|
4
|
+
|
|
5
|
+
describe('fields_location', () => {
|
|
6
|
+
// it('shows autocomplete suggestions', () => {
|
|
7
|
+
// cy.visit(url)
|
|
8
|
+
|
|
9
|
+
// cy.window().its('google').should('exist')
|
|
10
|
+
|
|
11
|
+
// cy.get('input[name="user[address]"]').clear().type('Sydney')
|
|
12
|
+
|
|
13
|
+
// cy.get('.pac-container', { timeout: 10000 }).should('be.visible')
|
|
14
|
+
// cy.get('.pac-container .pac-item').its('length').should('be.gt', 0)
|
|
15
|
+
// })
|
|
16
|
+
|
|
17
|
+
it('updates the zoom field', () => {
|
|
18
|
+
cy.visit(url)
|
|
19
|
+
|
|
20
|
+
cy.get('input[name="user[zoom]"]').clear().type('10')
|
|
21
|
+
cy.get('input[name="user[zoom]"]').should('have.value', '10')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('submits the form', () => {
|
|
25
|
+
cy.visit(url)
|
|
26
|
+
|
|
27
|
+
cy.contains('Submit').click()
|
|
28
|
+
|
|
29
|
+
cy.get('body').then(($body) => {
|
|
30
|
+
if ($body.find('.v-dialog').length) {
|
|
31
|
+
cy.get('.v-dialog').should('contain.text', 'Method: POST')
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if ($body.find('.unformatted').length) {
|
|
36
|
+
cy.get('.unformatted').should('contain.text', 'Method: POST')
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_otp')
|
|
4
|
+
|
|
5
|
+
describe('fields_otp', () => {
|
|
6
|
+
it('switches otp variants', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Length 4 (text)').click()
|
|
10
|
+
withComponent('otp_basic', (comp) => {
|
|
11
|
+
expect(comp.spec.length).to.eq(4)
|
|
12
|
+
expect(comp.spec.type).to.eq('text')
|
|
13
|
+
expect(comp.fieldModel).to.eq('ABCD')
|
|
14
|
+
})
|
|
15
|
+
cy.get('#otp_variant_status').should('contain.text', 'Variant: 4 digits (text)')
|
|
16
|
+
|
|
17
|
+
cy.contains('Length 6 (number)').click()
|
|
18
|
+
withComponent('otp_basic', (comp) => {
|
|
19
|
+
expect(comp.spec.length).to.eq(6)
|
|
20
|
+
expect(comp.spec.type).to.eq('number')
|
|
21
|
+
expect(comp.fieldModel).to.eq('123456')
|
|
22
|
+
})
|
|
23
|
+
cy.get('#otp_variant_status').should('contain.text', 'Variant: 6 digits (number)')
|
|
24
|
+
|
|
25
|
+
cy.contains('Length 8 (text)').click()
|
|
26
|
+
withComponent('otp_basic', (comp) => {
|
|
27
|
+
expect(comp.spec.length).to.eq(8)
|
|
28
|
+
expect(comp.spec.type).to.eq('text')
|
|
29
|
+
expect(comp.fieldModel).to.eq('A1B2C3D4')
|
|
30
|
+
})
|
|
31
|
+
cy.get('#otp_variant_status').should('contain.text', 'Variant: 8 digits (text)')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('updates status actions', () => {
|
|
35
|
+
cy.visit(url)
|
|
36
|
+
|
|
37
|
+
cy.contains('Autofill code').click()
|
|
38
|
+
withComponent('otp_basic', (comp) => {
|
|
39
|
+
expect(comp.fieldModel).to.eq('654321')
|
|
40
|
+
})
|
|
41
|
+
cy.get('#otp_status').should('contain.text', 'Status: code changed')
|
|
42
|
+
|
|
43
|
+
cy.contains('Clear code').click()
|
|
44
|
+
withComponent('otp_basic', (comp) => {
|
|
45
|
+
expect(comp.fieldModel).to.eq('')
|
|
46
|
+
})
|
|
47
|
+
cy.get('#otp_status').should('contain.text', 'Status: code changed')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('toggles disabled and clears value', () => {
|
|
51
|
+
cy.visit(url)
|
|
52
|
+
|
|
53
|
+
cy.contains('Disable field').click()
|
|
54
|
+
withComponent('otp_basic', (comp) => {
|
|
55
|
+
expect(comp.spec.disabled).to.eq(true)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
cy.contains('Enable field').click()
|
|
59
|
+
withComponent('otp_basic', (comp) => {
|
|
60
|
+
expect(comp.spec.disabled).to.not.eq(true)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
cy.contains('Clear value').click()
|
|
64
|
+
withComponent('otp_basic', (comp) => {
|
|
65
|
+
expect(comp.fieldModel).to.eq('')
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_phone')
|
|
4
|
+
|
|
5
|
+
describe('fields_phone', () => {
|
|
6
|
+
it('switches variants', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Auto-detect (default)').click()
|
|
10
|
+
withComponent('phone_basic', (comp) => {
|
|
11
|
+
expect(comp.spec.disableAutoDetect).to.not.eq(true)
|
|
12
|
+
expect(comp.spec.defaultCountry).to.not.eq('US')
|
|
13
|
+
expect(comp.spec.defaultCountry).to.not.eq('AU')
|
|
14
|
+
expect(comp.spec.label).to.eq('Phone number')
|
|
15
|
+
})
|
|
16
|
+
cy.get('#phone_variant_status').should('contain.text', 'Variant: auto-detect (default)')
|
|
17
|
+
|
|
18
|
+
cy.contains('Default country: US').click()
|
|
19
|
+
withComponent('phone_basic', (comp) => {
|
|
20
|
+
expect(comp.spec.disableAutoDetect).to.eq(true)
|
|
21
|
+
expect(comp.spec.defaultCountry).to.eq('US')
|
|
22
|
+
expect(comp.spec.label).to.eq('Phone (US default)')
|
|
23
|
+
})
|
|
24
|
+
cy.get('#phone_variant_status').should('contain.text', 'Variant: default country US')
|
|
25
|
+
|
|
26
|
+
cy.contains('Default country: AU').click()
|
|
27
|
+
withComponent('phone_basic', (comp) => {
|
|
28
|
+
expect(comp.spec.disableAutoDetect).to.eq(true)
|
|
29
|
+
expect(comp.spec.defaultCountry).to.eq('AU')
|
|
30
|
+
expect(comp.spec.label).to.eq('Phone (AU default)')
|
|
31
|
+
})
|
|
32
|
+
cy.get('#phone_variant_status').should('contain.text', 'Variant: default country AU')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('updates values via actions', () => {
|
|
36
|
+
cy.visit(url)
|
|
37
|
+
|
|
38
|
+
cy.contains('Set sample number').click()
|
|
39
|
+
withComponent('phone_basic', (comp) => {
|
|
40
|
+
expect(comp.fieldModel).to.contain('+1')
|
|
41
|
+
})
|
|
42
|
+
cy.get('#phone_status').should('contain.text', 'Status: number changed')
|
|
43
|
+
|
|
44
|
+
cy.contains('Clear value').click()
|
|
45
|
+
withComponent('phone_basic', (comp) => {
|
|
46
|
+
expect(comp.fieldModel).to.eq('')
|
|
47
|
+
})
|
|
48
|
+
cy.get('#phone_status').should('contain.text', 'Status: number changed')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('toggles disabled/read-only and submits', () => {
|
|
52
|
+
cy.visit(url)
|
|
53
|
+
|
|
54
|
+
cy.contains('Disable field').click()
|
|
55
|
+
withComponent('phone_basic', (comp) => {
|
|
56
|
+
expect(comp.spec.disabled).to.eq(true)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
cy.contains('Enable field').click()
|
|
60
|
+
withComponent('phone_basic', (comp) => {
|
|
61
|
+
expect(comp.spec.disabled).to.not.eq(true)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
cy.contains('Read-only').click()
|
|
65
|
+
withComponent('phone_basic', (comp) => {
|
|
66
|
+
expect(comp.spec.readOnly).to.eq(true)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
cy.contains('Editable').click()
|
|
70
|
+
withComponent('phone_basic', (comp) => {
|
|
71
|
+
expect(comp.spec.readOnly).to.not.eq(true)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
cy.contains('Submit').click()
|
|
75
|
+
|
|
76
|
+
cy.get('body').then(($body) => {
|
|
77
|
+
if ($body.find('.v-dialog').length) {
|
|
78
|
+
cy.get('.v-dialog').should('contain.text', 'Method: POST')
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if ($body.find('.unformatted').length) {
|
|
83
|
+
cy.get('.unformatted').should('contain.text', 'Method: POST')
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
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,137 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
2
|
+
|
|
3
|
+
const url = testPageUrl('fields_richText')
|
|
4
|
+
|
|
5
|
+
describe('fields_richText', () => {
|
|
6
|
+
it('switches output variants', () => {
|
|
7
|
+
cy.visit(url)
|
|
8
|
+
|
|
9
|
+
cy.contains('Markdown output').click()
|
|
10
|
+
withComponent('rich_text_main', (comp) => {
|
|
11
|
+
expect(comp.spec.produce).to.eq('markdown')
|
|
12
|
+
expect(comp.spec.accept).to.eq('markdown')
|
|
13
|
+
})
|
|
14
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: markdown output')
|
|
15
|
+
|
|
16
|
+
// cy.contains('HTML output').click()
|
|
17
|
+
// withComponent('rich_text_main', (comp) => {
|
|
18
|
+
// expect(comp.spec.produce).to.eq('html')
|
|
19
|
+
// expect(comp.spec.accept).to.eq('html')
|
|
20
|
+
// })
|
|
21
|
+
// cy.get('#rich_text_variant_status').should('contain.text', 'Variant: HTML output')
|
|
22
|
+
|
|
23
|
+
cy.contains('No uploader').click()
|
|
24
|
+
withComponent('rich_text_main', (comp) => {
|
|
25
|
+
expect(comp.spec.imageUploader).to.not.exist
|
|
26
|
+
})
|
|
27
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: uploader removed')
|
|
28
|
+
|
|
29
|
+
cy.contains('Restore uploader').click()
|
|
30
|
+
withComponent('rich_text_main', (comp) => {
|
|
31
|
+
expect(comp.spec.imageUploader).to.exist
|
|
32
|
+
})
|
|
33
|
+
cy.get('#rich_text_variant_status').should('contain.text', 'Variant: uploader restored')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// it('inserts template content', () => {
|
|
37
|
+
// cy.visit(url)
|
|
38
|
+
|
|
39
|
+
// cy.contains('Insert template').click()
|
|
40
|
+
// cy.get('#rich_text_status').should('contain.text', 'Status: content changed')
|
|
41
|
+
|
|
42
|
+
// cy.get('input[name="user[rich_text]"]').invoke('val').should('include', 'Quick update')
|
|
43
|
+
// })
|
|
44
|
+
|
|
45
|
+
it('toggles editor state', () => {
|
|
46
|
+
cy.visit(url)
|
|
47
|
+
|
|
48
|
+
cy.contains('Disable editor').click()
|
|
49
|
+
withComponent('rich_text_main', (comp) => {
|
|
50
|
+
expect(comp.spec.disabled).to.eq(true)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
cy.contains('Enable editor').click()
|
|
54
|
+
withComponent('rich_text_main', (comp) => {
|
|
55
|
+
expect(comp.spec.disabled).to.not.eq(true)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
cy.contains('Toggle debug').click()
|
|
59
|
+
withComponent('rich_text_main', (comp) => {
|
|
60
|
+
expect(comp.spec.debug).to.eq(false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
cy.contains('Enable debug').click()
|
|
64
|
+
withComponent('rich_text_main', (comp) => {
|
|
65
|
+
expect(comp.spec.debug).to.eq(true)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('uploads files on drop and paste', () => {
|
|
70
|
+
cy.visit(url)
|
|
71
|
+
|
|
72
|
+
let uploadIndex = 0
|
|
73
|
+
cy.window().then((win) => {
|
|
74
|
+
const comp = win.GLib.component.findById('rich_text_main')
|
|
75
|
+
expect(comp).to.exist
|
|
76
|
+
const uploader = comp.spec.imageUploader
|
|
77
|
+
|
|
78
|
+
cy.intercept('POST', uploader.directUploadUrl, (req) => {
|
|
79
|
+
uploadIndex += 1
|
|
80
|
+
req.reply({
|
|
81
|
+
statusCode: 200,
|
|
82
|
+
body: {
|
|
83
|
+
signed_id: `signed-${uploadIndex}`,
|
|
84
|
+
direct_upload: {
|
|
85
|
+
url: `https://example.com/upload-${uploadIndex}`,
|
|
86
|
+
headers: { 'Content-Type': 'text/csv' }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
}).as('directUpload')
|
|
91
|
+
|
|
92
|
+
cy.intercept('PUT', 'https://example.com/upload-*', { statusCode: 200, body: '' }).as('directUploadStore')
|
|
93
|
+
cy.intercept('POST', uploader.blobUrlGenerator, { statusCode: 200, body: { url: 'https://example.com/blob' } }).as('blobUrl')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
cy.fixture('bulk_edit.csv', 'binary').then((fileContent) => {
|
|
97
|
+
const blob = Cypress.Blob.binaryStringToBlob(fileContent, 'text/csv')
|
|
98
|
+
cy.window().then((win) => {
|
|
99
|
+
const file = new win.File([blob], 'bulk_edit.csv', { type: 'text/csv' })
|
|
100
|
+
const dataTransfer = new win.DataTransfer()
|
|
101
|
+
dataTransfer.items.add(file)
|
|
102
|
+
cy.get('#rich_text_main .ql-editor').trigger('drop', { dataTransfer })
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
cy.wait('@directUpload')
|
|
107
|
+
cy.wait('@directUploadStore')
|
|
108
|
+
cy.wait('@blobUrl')
|
|
109
|
+
cy.get('input[name="user[images_attributes][]"]').should('have.length', 1)
|
|
110
|
+
cy.get('input[name="user[images_attributes][]"]').first().should('have.value', 'signed-1')
|
|
111
|
+
|
|
112
|
+
cy.fixture('bulk_edit.csv', 'binary').then((fileContent) => {
|
|
113
|
+
const blob = Cypress.Blob.binaryStringToBlob(fileContent, 'text/csv')
|
|
114
|
+
cy.window().then((win) => {
|
|
115
|
+
const file = new win.File([blob], '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
|
+
|
|
122
|
+
cy.wait('@directUpload')
|
|
123
|
+
cy.wait('@directUploadStore')
|
|
124
|
+
cy.wait('@blobUrl')
|
|
125
|
+
cy.get('input[name="user[images_attributes][]"]').should('have.length', 2)
|
|
126
|
+
cy.get('input[name="user[images_attributes][]"]').eq(1).should('have.value', 'signed-2')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('shows mention list when typing a person', () => {
|
|
130
|
+
cy.visit(url)
|
|
131
|
+
|
|
132
|
+
cy.get('#rich_text_main .ql-editor').click().type('{end} @jo')
|
|
133
|
+
cy.get('.ql-mention-list-container').should('be.visible')
|
|
134
|
+
cy.get('.ql-mention-list-container').should('contain.text', 'John Doe')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { testPageUrl, withComponent } from "../../helper"
|
|
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
|
+
})
|
|
@@ -39,6 +39,117 @@ describe('fields_upload', () => {
|
|
|
39
39
|
cy.get('@filesTrigger').should('have.been.calledOnce')
|
|
40
40
|
})
|
|
41
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
|
+
|
|
42
153
|
it('submits the form', () => {
|
|
43
154
|
cy.visit(url)
|
|
44
155
|
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { testPageUrl } from "../../helper"
|
|
2
|
+
|
|
2
3
|
const url = testPageUrl('window')
|
|
3
4
|
|
|
4
|
-
describe(
|
|
5
|
-
it('
|
|
5
|
+
describe('window', () => {
|
|
6
|
+
it('opens a new window with updateExisting', () => {
|
|
6
7
|
cy.visit(url)
|
|
7
8
|
|
|
8
9
|
cy.contains('windows/open updateExisting: true').click()
|
|
10
|
+
cy.location('href').should('contain', 'fields_upload')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('closes the current window', () => {
|
|
14
|
+
const previousUrl = testPageUrl('fields_upload')
|
|
15
|
+
|
|
16
|
+
cy.visit(previousUrl)
|
|
17
|
+
cy.visit(url)
|
|
9
18
|
|
|
10
|
-
cy.
|
|
11
|
-
expect(loc.href).to.eq(testPageUrl('multiupload'))
|
|
12
|
-
})
|
|
19
|
+
cy.contains('windows/close').click()
|
|
13
20
|
})
|
|
14
|
-
})
|
|
21
|
+
})
|