glib-web 4.42.1 → 4.42.2

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 (57) hide show
  1. package/.nycrc.json +20 -5
  2. package/action.js +0 -6
  3. package/agent/glib_test_sync.yaml +108 -0
  4. package/components/_internal_button.vue +6 -5
  5. package/components/component.vue +0 -1
  6. package/components/fields/_select.vue +10 -28
  7. package/components/fields/radioGroup.vue +1 -1
  8. package/components/multimedia/video.vue +13 -1
  9. package/cypress/component/component.cy.ts +0 -9
  10. package/cypress/e2e/glib-web/browsers.cy.ts +55 -0
  11. package/cypress/e2e/glib-web/calendar.cy.ts +34 -0
  12. package/cypress/e2e/glib-web/calendarEmptyData.cy.ts +10 -0
  13. package/cypress/e2e/glib-web/carousel.cy.ts +53 -0
  14. package/cypress/e2e/glib-web/charts.cy.ts +11 -0
  15. package/cypress/e2e/glib-web/column.cy.ts +27 -0
  16. package/cypress/e2e/glib-web/commands.cy.ts +35 -0
  17. package/cypress/e2e/glib-web/components.cy.ts +50 -0
  18. package/cypress/e2e/glib-web/custom.cy.ts +17 -0
  19. package/cypress/e2e/glib-web/dialogOpen.cy.ts +14 -0
  20. package/cypress/e2e/glib-web/fileUploadNew.cy.ts +12 -0
  21. package/cypress/e2e/glib-web/flow.cy.ts +29 -0
  22. package/cypress/e2e/glib-web/form.cy.ts +1 -1
  23. package/cypress/e2e/glib-web/forms.cy.ts +46 -0
  24. package/cypress/e2e/glib-web/grid.cy.ts +27 -0
  25. package/cypress/e2e/glib-web/horizontal.cy.ts +39 -0
  26. package/cypress/e2e/glib-web/http.cy.ts +55 -19
  27. package/cypress/e2e/glib-web/image.cy.ts +53 -0
  28. package/cypress/e2e/glib-web/list.cy.ts +41 -0
  29. package/cypress/e2e/glib-web/listsAppend.cy.ts +27 -0
  30. package/cypress/e2e/glib-web/multimediaVideo.cy.ts +43 -0
  31. package/cypress/e2e/glib-web/pagination.cy.ts +34 -0
  32. package/cypress/e2e/glib-web/panels.cy.ts +50 -0
  33. package/cypress/e2e/glib-web/popovers.cy.ts +34 -0
  34. package/cypress/e2e/glib-web/progressCircle.cy.ts +45 -0
  35. package/cypress/e2e/glib-web/responsive.cy.ts +21 -0
  36. package/cypress/e2e/glib-web/scroll.cy.ts +37 -0
  37. package/cypress/e2e/glib-web/sheets.cy.ts +77 -10
  38. package/cypress/e2e/glib-web/snackbars.cy.ts +33 -22
  39. package/cypress/e2e/glib-web/split.cy.ts +12 -0
  40. package/cypress/e2e/glib-web/storageItems.cy.ts +71 -0
  41. package/cypress/e2e/glib-web/table.cy.ts +28 -0
  42. package/cypress/e2e/glib-web/timeline.cy.ts +32 -0
  43. package/cypress/e2e/glib-web/timeouts.cy.ts +26 -0
  44. package/cypress/e2e/glib-web/ul.cy.ts +19 -0
  45. package/cypress/e2e/glib-web/vertical.cy.ts +41 -0
  46. package/cypress/e2e/glib-web/web.cy.ts +29 -0
  47. package/cypress/e2e/glib-web/windows.cy.ts +69 -0
  48. package/index.js +1 -5
  49. package/package.json +3 -3
  50. package/actions/global_states/set.js +0 -13
  51. package/actions/global_states/watch.js +0 -19
  52. package/actions/right_banners/close.js +0 -7
  53. package/actions/right_banners/open.js +0 -25
  54. package/components/fields/richText.vue +0 -361
  55. package/components/fields/select.vue +0 -27
  56. package/components/mixins/extension.js +0 -9
  57. package/components/panels/table2.vue +0 -113
package/.nycrc.json CHANGED
@@ -9,10 +9,25 @@
9
9
  ".ts",
10
10
  ".vue"
11
11
  ],
12
+ "exclude-after-remap": true,
13
+ "include": [
14
+ "action.js",
15
+ "actions/**",
16
+ "app.vue",
17
+ "components/**",
18
+ "constant.js",
19
+ "extensions/**",
20
+ "index.js",
21
+ "keys.js",
22
+ "nav/**",
23
+ "plugins/**",
24
+ "store.js",
25
+ "templates/**",
26
+ "utils/**"
27
+ ],
12
28
  "exclude": [
13
- "cypress/**",
14
- "coverage/**",
15
- "doc/**",
16
- "node_modules/**"
29
+ "actions/cables",
30
+ "actions/analytics",
31
+ "utils/private"
17
32
  ]
18
- }
33
+ }
package/action.js CHANGED
@@ -85,9 +85,6 @@ import ActionListsAppend from "./actions/lists/append";
85
85
  import ActionBottomBannersOpen from "./actions/bottom_banners/open";
86
86
  import ActionBottomBannersClose from "./actions/bottom_banners/close";
87
87
 
88
- import ActionGlobalStatesWatch from "./actions/global_states/watch";
89
- import ActionGlobalStatesSet from "./actions/global_states/set";
90
-
91
88
  import ActionDetectCountry from "./actions/browsers/detectCountry";
92
89
  import ActionDetectTimezone from "./actions/browsers/detectTimezone";
93
90
 
@@ -189,9 +186,6 @@ const actions = {
189
186
  "bottomBanners/open": ActionBottomBannersOpen,
190
187
  "bottomBanners/close": ActionBottomBannersClose,
191
188
 
192
- "globalStates/watch": ActionGlobalStatesWatch,
193
- "globalStates/set": ActionGlobalStatesSet,
194
-
195
189
  "files/upload": ActionFilesUpload,
196
190
 
197
191
  "browsers/detectCountry": ActionDetectCountry,
@@ -0,0 +1,108 @@
1
+ version: 1
2
+ name: glib-web-test-sync
3
+ description: >
4
+ Compare doc/garage/test_page pages with Cypress tests in cypress/e2e/glib-web and
5
+ scaffold missing tests when a page exists without coverage.
6
+
7
+ inputs:
8
+ doc_dir: doc/garage/test_page
9
+ test_dir: cypress/e2e/glib-web
10
+ test_helper: cypress/helper.ts
11
+ ai_test_prompt: |
12
+ Generate a Cypress e2e test for the glib test page: {{page_slug}}.
13
+ Inputs you can use:
14
+ - Source: {{doc_page_path}}
15
+ - Existing tests: {{existing_tests_dir}}
16
+ Requirements:
17
+ - Must use: import { testPageUrl } from "../../helper"
18
+ - Must set: const url = testPageUrl('{{page_slug}}')
19
+ - Click every button defined in {{doc_page_path}} (include nested buttons in dialogs/sheets/menus).
20
+ - For each button click, assert the expected result implied by its onClick action.
21
+ - Use one or more it blocks; revisit the page when state needs a reset.
22
+ - Match existing project patterns (describe/it, cy.visit, selectors, etc).
23
+ - Use ASCII only.
24
+ fallback_test_template: |
25
+ import { testPageUrl } from "../../helper"
26
+ const url = testPageUrl('{{page_slug}}')
27
+
28
+ const overlaySelectors = [
29
+ '.v-dialog',
30
+ '.v-snackbar',
31
+ '.v-menu__content',
32
+ '.v-sheet',
33
+ '.v-overlay__content',
34
+ ].join(',')
35
+
36
+ describe('{{page_slug}}', () => {
37
+ it('clicks each button', () => {
38
+ cy.visit(url)
39
+ cy.get('button').should('have.length.at.least', 1)
40
+ cy.get('button').then(($buttons) => {
41
+ const labels = Array.from($buttons)
42
+ .map((button) => button.innerText.trim())
43
+ .filter(Boolean)
44
+
45
+ cy.wrap(labels).each((label) => {
46
+ cy.visit(url)
47
+ cy.contains('button', label).click({ force: true })
48
+ cy.location('href').then((hrefAfter) => {
49
+ if (hrefAfter !== url) {
50
+ expect(hrefAfter).to.not.eq(url)
51
+ return
52
+ }
53
+
54
+ cy.get('body').then(($body) => {
55
+ if ($body.find(overlaySelectors).length) {
56
+ cy.get(overlaySelectors).should('exist')
57
+ } else {
58
+ cy.contains('button', label).should('exist')
59
+ }
60
+ })
61
+ })
62
+ })
63
+ })
64
+ })
65
+ })
66
+
67
+ constraints:
68
+ - Use utils/type.js for any type checks in helper scripts.
69
+ - Ignore files that begin with "_" under doc/garage/test_page.
70
+
71
+ steps:
72
+ - id: collect-doc-pages
73
+ instruction: |
74
+ List *.json.jbuilder files under {{inputs.doc_dir}}.
75
+ Remove the ".json.jbuilder" suffix to get page slugs.
76
+ Drop any file that starts with "_".
77
+ Output: doc_page_slugs.
78
+
79
+ - id: collect-test-page-slugs
80
+ instruction: |
81
+ Scan every *.cy.ts under {{inputs.test_dir}} and extract all occurrences of
82
+ testPageUrl('...'). Collect the string values into test_page_slugs.
83
+ If a file contains no testPageUrl calls, derive a fallback slug by:
84
+ - Removing the .cy.ts suffix.
85
+ - Converting camelCase to snake_case.
86
+ Output: test_page_slugs.
87
+
88
+ - id: diff-docs-vs-tests
89
+ instruction: |
90
+ Compute missing_page_slugs = doc_page_slugs - test_page_slugs.
91
+ Output: missing_page_slugs.
92
+
93
+ - id: generate-missing-test-content
94
+ instruction: |
95
+ For each slug in missing_page_slugs:
96
+ 1) Set doc_page_path = {{inputs.doc_dir}}/<slug>.json.jbuilder.
97
+ 2) Use the AI with {{inputs.ai_test_prompt}} to generate test content.
98
+ 3) If AI output is empty or invalid, use {{inputs.fallback_test_template}}.
99
+ Output: generated_tests_map (slug -> test_content).
100
+
101
+ - id: scaffold-missing-tests
102
+ instruction: |
103
+ For each slug in missing_page_slugs:
104
+ 1) Derive a filename by converting snake_case to camelCase and append ".cy.ts".
105
+ Example: file_upload_new -> fileUploadNew.cy.ts
106
+ 2) Create {{inputs.test_dir}}/<filename> if it does not already exist.
107
+ 3) Write generated_tests_map[<slug>] to the file.
108
+ Output: created_test_files.
@@ -82,8 +82,13 @@ export default {
82
82
  <style lang="scss">
83
83
  .v-btn {
84
84
  &.link {
85
+ /* `height: inherit/auto/initial` will stretch to max height when used inside a horizontal panel,
86
+ presumably because it is affected by the panel's flex arrangement. */
87
+ height: 16px;
88
+ font-size: 1rem;
89
+
85
90
  .v-icon {
86
- font-size: 16px;
91
+ font-size: 1.2rem;
87
92
  }
88
93
  }
89
94
  }
@@ -102,10 +107,6 @@ button {
102
107
  /* text-decoration: underline; */
103
108
  padding-left: 0;
104
109
  padding-right: 0;
105
- /* `height: inherit/auto/initial` will stretch to max height when used inside a horizontal panel,
106
- presumably because it is affected by the panel's flex arrangement. */
107
- height: 16px;
108
- font-size: 16px;
109
110
  line-height: 1;
110
111
  min-width: auto;
111
112
  box-shadow: none !important;
@@ -68,7 +68,6 @@ import HiddenField from "./fields/hidden.vue";
68
68
  import TextField from "./fields/text.vue";
69
69
  import SubmitField from "./fields/submit.vue";
70
70
  import TextAreaField from "./fields/textarea.vue";
71
- const RichTextField = defineAsyncComponent(() => import("./fields/richText.vue"));
72
71
  const RichTextField2 = defineAsyncComponent(() => import("./fields/richText2.vue"));
73
72
  // import NewRichTextField from "./fields/newRichText.vue";
74
73
  const FileField = defineAsyncComponent(() => import("./fields/file.vue"));
@@ -3,11 +3,10 @@
3
3
  <!-- Set `menu-props` so the menu will never be wider than the select field.
4
4
  See https://github.com/vuetifyjs/vuetify/issues/17751 -->
5
5
  <component ref="comp" :is="compName" :color="gcolor" v-model="fieldModel" :label="label" :items="normalizedOptions"
6
- :disabled="inputDisabled" :multiple="spec.multiple" :readonly="spec.readOnly"
7
- :clearable="spec.clearable" :placeholder="spec.placeholder" :rules="$validation()" persistent-hint
8
- :append-icon="append.icon" validate-on="blur" item-title='text' :variant="variant"
9
- :density="density" persistent-placeholder @update:modelValue="onChange" @focus="focused = true"
10
- @blur="focused = false" :menu-props="{ maxWidth: 0 }">
6
+ :disabled="inputDisabled" :multiple="spec.multiple" :readonly="spec.readOnly" :clearable="spec.clearable"
7
+ :placeholder="spec.placeholder" :rules="$validation()" persistent-hint :append-icon="append.icon"
8
+ validate-on="input" item-title='text' :variant="variant" :density="density" persistent-placeholder
9
+ @update:modelValue="onChange" @focus="focused = true" @blur="focused = false" :menu-props="{ maxWidth: 0 }">
11
10
 
12
11
  <template #item="{ props, item }">
13
12
  <div class="fields-select-option">
@@ -23,7 +22,7 @@
23
22
  <select-item-default v-else :context="props" :item="item" :spec="spec"></select-item-default>
24
23
  </div>
25
24
  </template>
26
-
25
+
27
26
  <template v-slot:prepend-item>
28
27
  <template v-if="spec.prependSelectAll">
29
28
  <v-list-item title="Select All" @click="checkAll">
@@ -40,35 +39,18 @@
40
39
  </template>
41
40
 
42
41
  <template v-if="useChips" #selection="{ item, index }">
43
- <v-chip
44
- v-if="index < maxVisibleChips"
45
- :density="density"
46
- closable
47
- @click:close="removeItem(item)"
48
- >
42
+ <v-chip v-if="index < maxVisibleChips" :density="density" closable @click:close="removeItem(item)">
49
43
  <span>{{ item.title }}</span>
50
44
  </v-chip>
51
45
  <v-chip
52
46
  v-if="!expanded && chipExceedsTwoLines && visibleChipCount < fieldModel.length && index === visibleChipCount"
53
- :density="density"
54
- clickable
55
- @click="expanded = true"
56
- class="text-caption expansion-chip"
57
- variant="outlined"
58
- color="primary"
59
- >
47
+ :density="density" clickable @click="expanded = true" class="text-caption expansion-chip" variant="outlined"
48
+ color="primary">
60
49
  {{ fieldModel.length - visibleChipCount }} more
61
50
  <common-icon :spec="{ material: { name: 'expand_more' } }" class="ml-1" />
62
51
  </v-chip>
63
- <v-chip
64
- v-if="expanded && chipExceedsTwoLines && index === fieldModel.length - 1"
65
- :density="density"
66
- clickable
67
- @click="collapseChips"
68
- class="text-caption expansion-chip"
69
- variant="outlined"
70
- color="primary"
71
- >
52
+ <v-chip v-if="expanded && chipExceedsTwoLines && index === fieldModel.length - 1" :density="density" clickable
53
+ @click="collapseChips" class="text-caption expansion-chip" variant="outlined" color="primary">
72
54
  Show less
73
55
  <common-icon :spec="{ material: { name: 'expand_less' } }" class="ml-1" />
74
56
  </v-chip>
@@ -4,7 +4,7 @@
4
4
  validation error on page load.
5
5
  -->
6
6
  <v-radio-group v-model="fieldModel" :name="fieldName" :readonly="spec.readOnly" :disabled="inputDisabled"
7
- :rules="$validation()" :inline="spec.row" validate-on="blur" @change="$executeOnChange()" :class="$classes()"
7
+ :rules="$validation()" :inline="spec.row" validate-on="input" @change="$executeOnChange()" :class="$classes()"
8
8
  :style="$styles()" v-if="loadIf">
9
9
  <!-- <div v-for="(childView, index) in spec.childViews" :key="index">
10
10
  <glib-component :spec="childView" />
@@ -24,12 +24,24 @@ export default {
24
24
  paddingBottom: null
25
25
  };
26
26
  },
27
+ watch: {
28
+ spec: {
29
+ deep: true,
30
+ handler() {
31
+ this.updateFromSpec();
32
+ }
33
+ }
34
+ },
27
35
  methods: {
28
36
  $ready() {
37
+ this.updateFromSpec();
38
+ },
39
+ updateFromSpec() {
40
+ this.paddingBottom = null;
29
41
  this.width = this.$length(this.spec.width);
30
42
  this.height = this.$length(this.spec.height);
31
43
 
32
- if (this.height == null) {
44
+ if (Utils.type.isNull(this.height)) {
33
45
  // Let the container calculates the height
34
46
  this.height = "100%";
35
47
 
@@ -230,15 +230,6 @@ const componentSpecOverrides: Record<string, Record<string, unknown>> = {
230
230
  },
231
231
  ],
232
232
  },
233
- "panels-bulkEdit": {
234
- sections: [
235
- {
236
- header: { dataCells: ["Header"] },
237
- rows: [],
238
- dataRows: [],
239
- },
240
- ],
241
- },
242
233
  "panels-bulkEdit2": {
243
234
  viewHeaders: [{ id: "col-1", text: "Header" }],
244
235
  viewCells: [{ view: "fields/text", name: "col-1", label: "Header" }],
@@ -0,0 +1,55 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('browsers')
4
+
5
+ const stubCountryLookup = () => {
6
+ cy.intercept('GET', 'http://ip-api.com/json/', {
7
+ statusCode: 200,
8
+ body: {
9
+ country: 'Testland',
10
+ countryCode: 'TT'
11
+ }
12
+ }).as('ipLookup')
13
+ }
14
+
15
+ describe('browsers', () => {
16
+ it('detects timezone and posts form data', () => {
17
+ stubCountryLookup()
18
+ cy.visit(url)
19
+
20
+ cy.contains('button', 'browsers/detectTimezone').click()
21
+
22
+ cy.get('.v-dialog').should('contain.text', 'Method: POST')
23
+ cy.get('.v-dialog').should('contain.text', 'timezone')
24
+ })
25
+
26
+ it('detects country with form data and posts', () => {
27
+ stubCountryLookup()
28
+ cy.visit(url)
29
+
30
+ cy.contains('button', 'browsers/detectCountry (with formData)').click()
31
+
32
+ cy.get('.v-dialog').should('contain.text', 'Method: POST')
33
+ cy.get('.v-dialog').should('contain.text', 'message')
34
+ cy.get('.v-dialog').should('contain.text', 'country')
35
+ })
36
+
37
+ it('updates status after detectTimezone', () => {
38
+ stubCountryLookup()
39
+ cy.visit(url)
40
+
41
+ cy.contains('button', 'browsers/detectTimezone (update status)').click()
42
+
43
+ cy.contains('#browsers_status', 'Status: detected timezone').should('exist')
44
+ cy.contains('.v-snackbar', 'Timezone detected').should('exist')
45
+ })
46
+
47
+ it('alerts for detectCountry without form data', () => {
48
+ stubCountryLookup()
49
+ cy.visit(url)
50
+
51
+ cy.contains('button', 'browsers/detectCountry (no formData)').click()
52
+
53
+ cy.contains('.v-snackbar', 'Country detect requested').should('exist')
54
+ })
55
+ })
@@ -0,0 +1,34 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('calendar')
4
+ const sheetSelector = '#calendar_main .v-sheet'
5
+
6
+ const expectSheetHeight = (height) => {
7
+ cy.get(sheetSelector).should(($sheet) => {
8
+ expect($sheet[0].style.height).to.eq(height)
9
+ })
10
+ }
11
+
12
+ const expectSheetWidth = (width) => {
13
+ cy.get(sheetSelector).should(($sheet) => {
14
+ expect($sheet[0].style.width).to.eq(width)
15
+ })
16
+ }
17
+
18
+ describe('calendar', () => {
19
+ it('resizes calendar with variant buttons', () => {
20
+ cy.visit(url)
21
+
22
+ cy.contains('button', 'Default size').click()
23
+ expectSheetHeight('420px')
24
+
25
+ cy.contains('button', 'Compact').click()
26
+ expectSheetHeight('320px')
27
+
28
+ cy.contains('button', 'Tall').click()
29
+ expectSheetHeight('560px')
30
+
31
+ cy.contains('button', 'Fixed width').click()
32
+ expectSheetWidth('720px')
33
+ })
34
+ })
@@ -0,0 +1,10 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('calendar_empty_data')
4
+
5
+ describe('calendar_empty_data', () => {
6
+ it('loads the empty calendar data page', () => {
7
+ cy.visit(url)
8
+ cy.get('body').should('exist')
9
+ })
10
+ })
@@ -0,0 +1,53 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('carousel')
4
+
5
+ describe('carousel', () => {
6
+ it('updates distribution buttons', () => {
7
+ cy.visit(url)
8
+
9
+ cy.contains('button', 'Fill equally').click()
10
+ cy.window().then((win) => {
11
+ const comp = win.GLib.component.findById('carousel_main')
12
+ expect(comp).to.exist
13
+ expect(comp.spec.distribution).to.eq('fillEqually')
14
+ })
15
+
16
+ cy.contains('button', 'Space equally').click()
17
+ cy.window().then((win) => {
18
+ const comp = win.GLib.component.findById('carousel_main')
19
+ expect(comp.spec.distribution).to.eq('spaceEqually')
20
+ })
21
+
22
+ cy.contains('button', 'Clear distribution').click()
23
+ cy.window().then((win) => {
24
+ const comp = win.GLib.component.findById('carousel_main')
25
+ expect(comp.spec.distribution).to.eq(null)
26
+ })
27
+ })
28
+
29
+ it('updates action status from carousel items', () => {
30
+ cy.visit(url)
31
+
32
+ cy.contains('button', 'Pick A')
33
+ .closest('.v-carousel')
34
+ .as('actionCarousel')
35
+
36
+ cy.get('@actionCarousel').within(() => {
37
+ cy.contains('button', 'Pick A').click({ force: true })
38
+ })
39
+ cy.get('#carousel_action_status').should('contain.text', 'Action status: A')
40
+
41
+ cy.get('@actionCarousel').within(() => {
42
+ cy.get('.v-window__right').click({ force: true })
43
+ cy.contains('button', 'Pick B').click({ force: true })
44
+ })
45
+ cy.get('#carousel_action_status').should('contain.text', 'Action status: B')
46
+
47
+ cy.get('@actionCarousel').within(() => {
48
+ cy.get('.v-window__right').click({ force: true })
49
+ cy.contains('button', 'Pick C').click({ force: true })
50
+ })
51
+ cy.get('#carousel_action_status').should('contain.text', 'Action status: C')
52
+ })
53
+ })
@@ -0,0 +1,11 @@
1
+ import { testPageUrl } from "../../helper"
2
+ const url = testPageUrl('charts')
3
+
4
+ describe('charts', () => {
5
+ it('opens full charts demo', () => {
6
+ cy.visit(url)
7
+
8
+ cy.contains('h2', 'Charts').should('be.visible')
9
+ cy.get('#charts_preview').should('exist')
10
+ })
11
+ })
@@ -0,0 +1,27 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('column')
4
+
5
+ describe('column', () => {
6
+ it('shows snackbars for column size buttons', () => {
7
+ cy.visit(url)
8
+
9
+ cy.contains('button', '6 cols').click()
10
+ cy.get('.v-snackbar').should('contain.text', 'Not implemented yet!')
11
+
12
+ cy.contains('button', '4 cols').click()
13
+ cy.get('.v-snackbar').should('contain.text', 'Not implemented yet!')
14
+ })
15
+
16
+ it('updates column padding', () => {
17
+ cy.visit(url)
18
+
19
+ cy.contains('button', 'Add padding').click()
20
+ cy.get('#column_main')
21
+ .should('have.css', 'padding-top', '12px')
22
+
23
+ cy.contains('button', 'Clear padding').click()
24
+ cy.get('#column_main')
25
+ .should('not.have.css', 'padding-top', '12px')
26
+ })
27
+ })
@@ -0,0 +1,35 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('commands')
4
+
5
+ describe('commands', () => {
6
+ it('copies values to the clipboard', () => {
7
+ cy.visit(url)
8
+
9
+ cy.window().then((win) => {
10
+ cy.stub(win.navigator.clipboard, 'writeText')
11
+ .callsFake((text) => Promise.resolve(text))
12
+ .as('writeText')
13
+ })
14
+
15
+ cy.contains('button', 'commands/copy').click()
16
+ cy.get('@writeText').should('have.been.calledWith', 'Paste this somewhere else')
17
+
18
+ cy.contains('button', 'commands/copy (short)').click()
19
+ cy.get('@writeText').should('have.been.calledWith', 'Copied from commands test page')
20
+
21
+ cy.contains('button', 'commands/copy (long)').click()
22
+ cy.get('@writeText').should(
23
+ 'have.been.calledWith',
24
+ 'Long text: Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
25
+ )
26
+
27
+ cy.contains('button', 'commands/copy (with onCopy)').click()
28
+ cy.get('@writeText').should('have.been.calledWith', 'Copied with callback')
29
+ cy.get('#commands_status').should('contain.text', 'Status: copied')
30
+ cy.contains('.v-snackbar', 'Copied').should('exist')
31
+
32
+ cy.contains('button', 'commands/copy (multiline)').click()
33
+ cy.get('@writeText').should('have.been.calledWith', 'Line 1\nLine 2\nLine 3')
34
+ })
35
+ })
@@ -0,0 +1,50 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('components')
4
+
5
+ describe('components', () => {
6
+ it('updates label text with components/set', () => {
7
+ cy.visit(url)
8
+
9
+ cy.contains('button', 'components/set text').click()
10
+
11
+ cy.contains('#components_basic', 'Label text: updated').should('exist')
12
+ })
13
+
14
+ it('toggles visibility with components/set', () => {
15
+ cy.visit(url)
16
+
17
+ cy.contains('button', 'Hide').click()
18
+ cy.get('#components_basic').should('not.be.visible')
19
+
20
+ cy.contains('button', 'Show').click()
21
+ cy.get('#components_basic').should('be.visible')
22
+ })
23
+
24
+ it('fires onSet callbacks', () => {
25
+ cy.visit(url)
26
+
27
+ cy.contains('button', 'components/set (with onSet)').click()
28
+
29
+ cy.contains('#components_status', 'Status: set callback fired').should('exist')
30
+ cy.contains('.v-snackbar', 'Updated').should('exist')
31
+ })
32
+
33
+ // it('replaces components and restores label', () => {
34
+ // cy.visit(url)
35
+
36
+ // cy.contains('button', 'Replace with icon').click()
37
+ // cy.get('#components_replace_target', { timeout: 10000 })
38
+ // .should('have.class', 'v-icon')
39
+ // .and('contain.text', 'verified')
40
+
41
+ // cy.contains('button', 'Replace with button').click()
42
+ // cy.get('#components_replace_target', { timeout: 10000 })
43
+ // .should('contain.text', 'New button')
44
+ // .click()
45
+ // cy.contains('.v-snackbar', 'Button clicked').should('exist')
46
+
47
+ // cy.contains('button', 'Restore label').click()
48
+ // cy.contains('#components_replace_target', 'Replace me').should('exist')
49
+ // })
50
+ })
@@ -0,0 +1,17 @@
1
+ import { testPageUrl } from "../../helper"
2
+
3
+ const url = testPageUrl('custom')
4
+
5
+ describe('custom', () => {
6
+ it('switches custom data payloads', () => {
7
+ cy.visit(url)
8
+
9
+ cy.get('#custom_main').should('contain.text', 'Primary')
10
+
11
+ cy.contains('button', 'Alternate data').click()
12
+ cy.get('#custom_main').should('contain.text', 'Alternate')
13
+
14
+ cy.contains('button', 'Primary data').click()
15
+ cy.get('#custom_main').should('contain.text', 'Primary')
16
+ })
17
+ })
@@ -0,0 +1,14 @@
1
+ import { testPageUrl } from "../../helper"
2
+ const url = testPageUrl('dialog_open')
3
+
4
+ describe('dialog open', () => {
5
+ it('opens and closes dialog', () => {
6
+ cy.visit(url)
7
+
8
+ cy.contains('open').click()
9
+ cy.get('.v-dialog').should('exist')
10
+
11
+ cy.get('.v-dialog').contains('close').click()
12
+ cy.get('.v-dialog').should('not.exist')
13
+ })
14
+ })
@@ -0,0 +1,12 @@
1
+ import { testPageUrl } from "../../helper"
2
+ const url = testPageUrl('file_upload_new')
3
+
4
+ describe('file upload new', () => {
5
+ it('renders upload fields', () => {
6
+ cy.visit(url)
7
+
8
+ cy.contains('Reset').click()
9
+ cy.contains('Field Upload').should('exist')
10
+ cy.get('input[type="file"]').should('exist')
11
+ })
12
+ })