@json-editor/json-editor 2.11.0 → 2.13.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/.env +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +90 -6
- package/README_ADDON.md +5 -1
- package/dist/jsoneditor.js +1 -1
- package/dist/jsoneditor.js.LICENSE.txt +1 -1
- package/dist/nonmin/jsoneditor.js +417 -227
- package/dist/nonmin/jsoneditor.js.map +1 -1
- package/docs/cleave.html +1 -1
- package/docs/datetime.html +1 -1
- package/docs/describedby.html +1 -1
- package/docs/index.html +66 -14
- package/docs/meta_schema.json +16 -1
- package/docs/radio.html +1 -1
- package/docs/scripts/ajv-validator.js +8695 -0
- package/docs/select2.html +1 -1
- package/docs/selectize.html +2 -5
- package/docs/signature.html +12 -11
- package/docs/wysiwyg.html +1 -1
- package/package.json +1 -1
- package/src/core.js +10 -1
- package/src/defaults.js +3 -1
- package/src/editor.js +19 -1
- package/src/editors/array/selectize.js +0 -2
- package/src/editors/array.js +24 -13
- package/src/editors/base64.js +9 -0
- package/src/editors/button.js +8 -2
- package/src/editors/integer.js +3 -2
- package/src/editors/multiple.js +3 -0
- package/src/editors/number.js +4 -2
- package/src/editors/object.js +71 -3
- package/src/editors/signature.js +16 -16
- package/src/editors/simplemde.js +2 -1
- package/src/editors/string.js +4 -0
- package/src/editors/table.js +17 -14
- package/src/resolvers.js +13 -6
- package/src/schemaloader.js +13 -0
- package/src/theme.js +4 -0
- package/src/themes/bootstrap3.js +6 -0
- package/src/themes/bootstrap4.js +6 -0
- package/src/themes/bootstrap5.js +6 -0
- package/src/validator.js +28 -0
- package/tests/codeceptjs/codecept.json +1 -1
- package/tests/codeceptjs/constrains/contains_test.js +3 -2
- package/tests/codeceptjs/constrains/dependentRequired_test.js +33 -0
- package/tests/codeceptjs/constrains/dependentSchemas_test.js +1 -0
- package/tests/codeceptjs/core_test.js +14 -4
- package/tests/codeceptjs/editors/advanced_test.js +1 -1
- package/tests/codeceptjs/editors/array_test.js +59 -0
- package/tests/codeceptjs/editors/autocomplete_test.js +3 -1
- package/tests/codeceptjs/editors/object_test.js +20 -0
- package/tests/codeceptjs/editors/tabs_test.js +1 -1
- package/tests/codeceptjs/issues/issue-gh-1330_test.js +8 -0
- package/tests/codeceptjs/issues/issue-gh-1338_test.js +2 -0
- package/tests/codeceptjs/issues/issue-gh-1364_test.js +13 -0
- package/tests/codeceptjs/issues/issue-gh-1367_test.js +11 -0
- package/tests/codeceptjs/issues/issue-gh-1383_test.js +9 -0
- package/tests/codeceptjs/issues/issue-gh-1384_test.js +9 -0
- package/tests/codeceptjs/issues/issue-gh-1410_test.js +13 -0
- package/tests/codeceptjs/issues/issue-gh-1422_test.js +9 -0
- package/tests/codeceptjs/issues/issue-gh-1431_test.js +12 -0
- package/tests/codeceptjs/issues/issue-gh-1439_test.js +12 -0
- package/tests/docker-compose-local.yml +4 -0
- package/tests/pages/array-header-template.html +59 -0
- package/tests/pages/array-selectize-create.html +62 -0
- package/tests/pages/array-table-responsive.html +65 -0
- package/tests/pages/button-icons.html +1 -1
- package/tests/pages/button_state_mode_1.html +34 -0
- package/tests/pages/button_state_mode_2.html +35 -0
- package/tests/pages/dependentRequired.html +71 -0
- package/tests/pages/issues/issue-gh-1330.html +52 -0
- package/tests/pages/issues/issue-gh-1364.html +64 -0
- package/tests/pages/issues/issue-gh-1367.html +49 -0
- package/tests/pages/issues/issue-gh-1383.html +31 -0
- package/tests/pages/issues/issue-gh-1383.json +14 -0
- package/tests/pages/issues/issue-gh-1384.html +31 -0
- package/tests/pages/issues/issue-gh-1384.json +36 -0
- package/tests/pages/issues/issue-gh-1410.html +57 -0
- package/tests/pages/issues/issue-gh-1422.html +68 -0
- package/tests/pages/issues/issue-gh-1431.html +49 -0
- package/tests/pages/issues/issue-gh-1439.html +69 -0
- package/tests/pages/keep_only_existing_values.html +1 -1
- package/tests/pages/load-events.html +60 -0
- package/tests/pages/meta-schema.html +16 -2
- package/tests/pages/meta_schema.json +5 -1
- package/tests/pages/object-case-sensitive-property-search-false.html +41 -0
- package/tests/pages/object-case-sensitive-property-search-true.html +41 -0
- package/dist/dev/jsoneditor.js +0 -3687
- package/dist/jsoneditor.js.map +0 -1
package/src/resolvers.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
/* Use "multiple" as a
|
|
1
|
+
/* Use "multiple" as a fallback for everything */
|
|
2
2
|
const defaultResolver = schema => typeof schema.type !== 'string' && 'multiple'
|
|
3
3
|
|
|
4
|
+
/* If the type is a script type, then presume the Editor's type is "string" until later resolvers decide otherwise */
|
|
5
|
+
const defaultResolverString = schema => typeof schema.type === 'string' && 'string'
|
|
6
|
+
|
|
4
7
|
/* If the type is not set but properties are defined, we can infer the type is actually object */
|
|
5
8
|
const object = schema => !schema.type && schema.properties && 'object'
|
|
6
9
|
|
|
7
|
-
/* If
|
|
8
|
-
const primitive = schema => typeof schema.type === 'string' && schema.type
|
|
10
|
+
/* If type is set, and it's a basic JSON type, use the primitive editor */
|
|
11
|
+
const primitive = schema => typeof schema.type === 'string' && ['string', 'number', 'integer', 'boolean', 'null', 'array', 'object'].includes(schema.type) && schema.type
|
|
9
12
|
|
|
10
13
|
/* Use specialized editor for signatures */
|
|
11
14
|
const signature = schema => schema.type === 'string' && schema.format === 'signature' && 'signature'
|
|
@@ -61,7 +64,11 @@ const enumeratedProperties = schema => {
|
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
/* Specialized editors for arrays of strings */
|
|
64
|
-
const arraysOfStrings = schema => {
|
|
67
|
+
const arraysOfStrings = (schema, je) => {
|
|
68
|
+
if (schema.items) {
|
|
69
|
+
schema.items = je.expandSchema(schema.items)
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
if (schema.type === 'array' && schema.items && !(Array.isArray(schema.items)) && ['string', 'number', 'integer'].includes(schema.items.type)) {
|
|
66
73
|
if (schema.format === 'choices') return 'arrayChoices'
|
|
67
74
|
if (schema.uniqueItems) {
|
|
@@ -117,7 +124,7 @@ const markdown = schema => schema.type === 'string' && schema.format === 'markdo
|
|
|
117
124
|
const xhtml = schema => schema.type === 'string' && ['xhtml', 'bbcode'].includes(schema.format) && 'sceditor'
|
|
118
125
|
|
|
119
126
|
/* Use the ace editor for schemas with format equals any of ace editor modes */
|
|
120
|
-
const aceModes = ['actionscript', 'batchfile', 'c', 'c++', 'cpp', 'coffee', 'csharp', 'css', 'dart', 'django', 'ejs', 'erlang', 'golang', 'groovy', 'handlebars', 'haskell', 'haxe', 'html', 'ini', 'jade', 'java', 'javascript', 'json', 'less', 'lisp', 'lua', 'makefile', 'matlab', 'mysql', 'objectivec', 'pascal', 'perl', 'pgsql', 'php', 'python', 'r', 'ruby', 'sass', 'scala', 'scss', 'sh', 'smarty', 'sql', 'sqlserver', 'stylus', 'svg', 'twig', 'vbscript', 'xml', 'yaml']
|
|
127
|
+
const aceModes = ['actionscript', 'batchfile', 'c', 'c++', 'cpp', 'coffee', 'csharp', 'css', 'dart', 'django', 'ejs', 'erlang', 'golang', 'groovy', 'handlebars', 'haskell', 'haxe', 'html', 'ini', 'jade', 'java', 'javascript', 'json', 'less', 'lisp', 'lua', 'makefile', 'matlab', 'mysql', 'objectivec', 'pascal', 'perl', 'pgsql', 'php', 'python', 'prql', 'r', 'ruby', 'rust', 'sass', 'scala', 'scss', 'sh', 'smarty', 'sql', 'sqlserver', 'stylus', 'svg', 'typescript', 'twig', 'vbscript', 'xml', 'yaml', 'zig']
|
|
121
128
|
const ace = schema => schema.type === 'string' && aceModes.includes(schema.format) && 'ace'
|
|
122
129
|
|
|
123
130
|
const ip = schema => schema.type === 'string' && ['ip', 'ipv4', 'ipv6', 'hostname'].includes(schema.format) && 'ip'
|
|
@@ -125,4 +132,4 @@ const ip = schema => schema.type === 'string' && ['ip', 'ipv4', 'ipv6', 'hostnam
|
|
|
125
132
|
const colorPicker = schema => schema.type === 'string' && schema.format === 'color' && 'colorpicker'
|
|
126
133
|
|
|
127
134
|
/* Export resolvers in order of discovery, first to last */
|
|
128
|
-
export const resolvers = [colorPicker, ip, ace, xhtml, markdown, jodit, autoComplete, uuid, info, button, stepper, describeBy, starratings, date, oneOf, ifThenElse, arraysOfStrings, enumeratedProperties, enumSource, table, upload, base64, any, boolean, signature, primitive, object, defaultResolver]
|
|
135
|
+
export const resolvers = [colorPicker, ip, ace, xhtml, markdown, jodit, autoComplete, uuid, info, button, stepper, describeBy, starratings, date, oneOf, ifThenElse, arraysOfStrings, enumeratedProperties, enumSource, table, upload, base64, any, boolean, signature, primitive, object, defaultResolver, defaultResolverString]
|
package/src/schemaloader.js
CHANGED
|
@@ -449,6 +449,12 @@ export class SchemaLoader {
|
|
|
449
449
|
if (typeof response === 'undefined') throw new Error(`Failed to fetch ref via ajax - ${uri}`)
|
|
450
450
|
try {
|
|
451
451
|
externalSchema = JSON.parse(response.responseText)
|
|
452
|
+
|
|
453
|
+
this.onSchemaLoaded({
|
|
454
|
+
schema: externalSchema,
|
|
455
|
+
schemaUrl: url
|
|
456
|
+
})
|
|
457
|
+
|
|
452
458
|
if (this.options.ajax_cache_responses) {
|
|
453
459
|
this.cacheSet(url, externalSchema)
|
|
454
460
|
}
|
|
@@ -472,11 +478,18 @@ export class SchemaLoader {
|
|
|
472
478
|
}
|
|
473
479
|
await this._asyncloadExternalRefs(externalSchema, url, newfileBase)
|
|
474
480
|
}
|
|
481
|
+
|
|
475
482
|
if (!waiting) {
|
|
476
483
|
return true
|
|
477
484
|
}
|
|
485
|
+
|
|
486
|
+
this.onAllSchemasLoaded()
|
|
478
487
|
}
|
|
479
488
|
|
|
489
|
+
onSchemaLoaded (payload) {}
|
|
490
|
+
|
|
491
|
+
onAllSchemasLoaded () {}
|
|
492
|
+
|
|
480
493
|
extendSchemas (obj1, obj2) {
|
|
481
494
|
obj1 = extend({}, obj1)
|
|
482
495
|
obj2 = extend({}, obj2)
|
package/src/theme.js
CHANGED
|
@@ -414,6 +414,10 @@ export class AbstractTheme {
|
|
|
414
414
|
if (title) button.setAttribute('title', title)
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
getTableContainer () {
|
|
418
|
+
return document.createElement('div')
|
|
419
|
+
}
|
|
420
|
+
|
|
417
421
|
/* Table functions */
|
|
418
422
|
getTable () {
|
|
419
423
|
return document.createElement('table')
|
package/src/themes/bootstrap3.js
CHANGED
|
@@ -136,6 +136,12 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
136
136
|
return el
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
getTableContainer () {
|
|
140
|
+
const el = super.getTableContainer()
|
|
141
|
+
el.classList.add('table-responsive')
|
|
142
|
+
return el
|
|
143
|
+
}
|
|
144
|
+
|
|
139
145
|
getTable () {
|
|
140
146
|
const el = document.createElement('table')
|
|
141
147
|
el.classList.add('table', 'table-bordered')
|
package/src/themes/bootstrap4.js
CHANGED
|
@@ -454,6 +454,12 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
454
454
|
return el
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
+
getTableContainer () {
|
|
458
|
+
const el = super.getTableContainer()
|
|
459
|
+
el.classList.add('table-responsive')
|
|
460
|
+
return el
|
|
461
|
+
}
|
|
462
|
+
|
|
457
463
|
getTable () {
|
|
458
464
|
const el = document.createElement('table')
|
|
459
465
|
el.classList.add('table', 'table-sm')
|
package/src/themes/bootstrap5.js
CHANGED
|
@@ -390,6 +390,12 @@ export class bootstrap5Theme extends AbstractTheme {
|
|
|
390
390
|
return el
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
+
getTableContainer () {
|
|
394
|
+
const el = super.getTableContainer()
|
|
395
|
+
el.classList.add('table-responsive')
|
|
396
|
+
return el
|
|
397
|
+
}
|
|
398
|
+
|
|
393
399
|
getTable () {
|
|
394
400
|
const el = document.createElement('table')
|
|
395
401
|
el.classList.add('table', 'table-sm')
|
package/src/validator.js
CHANGED
|
@@ -11,6 +11,34 @@ export class Validator {
|
|
|
11
11
|
this.defaults = defaults
|
|
12
12
|
|
|
13
13
|
this._validateSubSchema = {
|
|
14
|
+
dependentRequired (schema, value, path) {
|
|
15
|
+
const errors = []
|
|
16
|
+
|
|
17
|
+
if (typeof schema.dependentRequired !== 'undefined') {
|
|
18
|
+
let missingProperties = []
|
|
19
|
+
|
|
20
|
+
Object.keys(schema.dependentRequired).forEach((key) => {
|
|
21
|
+
if (typeof value[key] !== 'undefined') {
|
|
22
|
+
const requiredProperties = schema.dependentRequired[key]
|
|
23
|
+
|
|
24
|
+
missingProperties = requiredProperties.filter((property) => {
|
|
25
|
+
return !hasOwnProperty(value, property)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const invalid = missingProperties.length > 0
|
|
31
|
+
|
|
32
|
+
if (invalid) {
|
|
33
|
+
errors.push({
|
|
34
|
+
message: 'Must have the required properties: ' + missingProperties.join(', '),
|
|
35
|
+
path: path
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return errors
|
|
41
|
+
},
|
|
14
42
|
dependentSchemas (schema, value, path) {
|
|
15
43
|
let errors = []
|
|
16
44
|
|
|
@@ -7,18 +7,18 @@ Scenario('should display contains validation errors @contains', ({ I }) => {
|
|
|
7
7
|
I.waitForElement('.je-ready')
|
|
8
8
|
I.waitForText('No items match contains')
|
|
9
9
|
I.click('.json-editor-btn-add')
|
|
10
|
+
I.waitForInvisible('.alert-danger')
|
|
10
11
|
I.dontSee('No items match contains')
|
|
11
12
|
})
|
|
12
13
|
|
|
13
14
|
Scenario('should display @minContains validation errors @contains', ({ I }) => {
|
|
14
15
|
I.amOnPage('minContains.html')
|
|
15
16
|
I.waitForElement('.je-ready')
|
|
16
|
-
I.dontSee('No items match contains')
|
|
17
17
|
I.waitForText('Contains match count 0 is less than minimum contains count of 2')
|
|
18
18
|
I.click('.json-editor-btn-add')
|
|
19
|
-
I.dontSee('No items match contains')
|
|
20
19
|
I.waitForText('Contains match count 1 is less than minimum contains count of 2')
|
|
21
20
|
I.click('.json-editor-btn-add')
|
|
21
|
+
I.waitForInvisible('.alert-danger')
|
|
22
22
|
I.dontSee('No items match contains')
|
|
23
23
|
I.dontSee('minimum contains count of 2')
|
|
24
24
|
})
|
|
@@ -28,6 +28,7 @@ Scenario('should display @maxContains validation errors @contains', ({ I }) => {
|
|
|
28
28
|
I.waitForElement('.je-ready')
|
|
29
29
|
I.waitForText('No items match contains')
|
|
30
30
|
I.click('.json-editor-btn-add')
|
|
31
|
+
I.waitForInvisible('.alert-danger')
|
|
31
32
|
I.dontSee('No items match contains')
|
|
32
33
|
I.click('.json-editor-btn-add')
|
|
33
34
|
I.dontSee('No items match contains')
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('dependentRequired')
|
|
4
|
+
|
|
5
|
+
Scenario('@dependentRequired should display validation errors', ({ I }) => {
|
|
6
|
+
I.amOnPage('dependentRequired.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForValue('#textarea-value', '{"name":""}')
|
|
9
|
+
|
|
10
|
+
I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
|
|
11
|
+
I.waitForValue('#textarea-value', '{"name":"","credit_card":0,"billing_address_1":"","billing_address_2":""}')
|
|
12
|
+
I.waitForText('Must have the required properties: billing_address_3')
|
|
13
|
+
|
|
14
|
+
I.click('[data-schemapath="root.billing_address_1"] .json-editor-opt-in')
|
|
15
|
+
I.waitForValue('#textarea-value', '{"name":"","credit_card":0,"billing_address_1":"","billing_address_2":""}')
|
|
16
|
+
I.waitForText('Must have the required properties: billing_address_3')
|
|
17
|
+
|
|
18
|
+
I.click('[data-schemapath="root.billing_address_2"] .json-editor-opt-in')
|
|
19
|
+
I.waitForValue('#textarea-value', '{"name":"","credit_card":0,"billing_address_1":"","billing_address_2":""}')
|
|
20
|
+
I.waitForText('Must have the required properties: billing_address_3')
|
|
21
|
+
|
|
22
|
+
I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
|
|
23
|
+
I.waitForValue('#textarea-value', '{"name":"","billing_address_1":"","billing_address_2":""}')
|
|
24
|
+
I.waitForText('Must have the required properties: billing_address_3')
|
|
25
|
+
|
|
26
|
+
I.click('[data-schemapath="root.billing_address_1"] .json-editor-opt-in')
|
|
27
|
+
I.waitForValue('#textarea-value', '{"name":"","billing_address_2":""}')
|
|
28
|
+
I.waitForText('Must have the required properties: billing_address_3')
|
|
29
|
+
|
|
30
|
+
I.click('[data-schemapath="root.billing_address_2"] .json-editor-opt-in')
|
|
31
|
+
I.waitForValue('#textarea-value', '{"name":""}')
|
|
32
|
+
I.dontSee('Must have the required properties: billing_address_3')
|
|
33
|
+
})
|
|
@@ -9,6 +9,7 @@ Scenario('@dependentSchemas should display validation errors', ({ I }) => {
|
|
|
9
9
|
I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
|
|
10
10
|
I.waitForText('Object is missing the required property \'billing_address\'')
|
|
11
11
|
I.click('[data-schemapath="root.billing_address"] .json-editor-opt-in')
|
|
12
|
+
I.waitForInvisible('.alert-danger')
|
|
12
13
|
I.dontSee('Object is missing the required property \'billing_address\'')
|
|
13
14
|
I.click('[data-schemapath="root.credit_card"] .json-editor-opt-in')
|
|
14
15
|
I.dontSee('Object is missing the required property \'billing_address\'')
|
|
@@ -5,6 +5,16 @@ const { DEFAULT_WAIT_TIME } = require('./test-config')
|
|
|
5
5
|
|
|
6
6
|
Feature('core')
|
|
7
7
|
|
|
8
|
+
Scenario('should listen to @load-events', async ({ I }) => {
|
|
9
|
+
I.amOnPage('load-events.html')
|
|
10
|
+
I.waitForElement('.je-ready')
|
|
11
|
+
I.waitForText('/tests/pages/../fixtures/basic_person.json')
|
|
12
|
+
I.waitForText('{"title":"Person","type":"object","id":"person","properties":{"name":{"type":"string","description":"First and Last name","minLength":4},"age":{"type":"integer","default":21,"minimum":18,"maximum":99},"gender":{"type":"string","enum":["male","female","other"]}}}')
|
|
13
|
+
I.waitForText('/tests/pages/../fixtures/person.json')
|
|
14
|
+
I.waitForText('{"$ref":"../fixtures/basic_person.json","properties":{"location":{"type":"object","title":"Location","properties":{"city":{"type":"string"},"state":{"type":"string"},"citystate":{"type":"string","description":"This is generated automatically from the previous two fields","template":"{{city}}, {{state}}","watch":{"city":"person.location.city","state":"person.location.state"}}}},"pets":{"type":"array","format":"table","title":"Pets","uniqueItems":true,"items":{"type":"object","properties":{"type":{"type":"string","enum":["cat","dog","bird","reptile","other"],"default":"dog"},"name":{"type":"string"},"fixed":{"type":"boolean","title":"spayed / neutered"}}}}}}')
|
|
15
|
+
I.waitForText('All schemas loaded')
|
|
16
|
+
})
|
|
17
|
+
|
|
8
18
|
Scenario('should set per-editor options @per-editor-options', async ({ I }) => {
|
|
9
19
|
I.amOnPage('per-editor-options.html')
|
|
10
20
|
I.waitForElement('.je-ready')
|
|
@@ -79,18 +89,18 @@ Scenario('should set and get individual values', async ({ I }) => {
|
|
|
79
89
|
I.waitForValue('.value', '"john kaminski"')
|
|
80
90
|
})
|
|
81
91
|
|
|
82
|
-
Scenario('should watch a specific field for changes', async ({ I }) => {
|
|
92
|
+
Scenario('should watch a specific field for changes @core @change', async ({ I }) => {
|
|
83
93
|
I.amOnPage('core.html')
|
|
84
94
|
I.dontSeeElement('.name-changed')
|
|
85
95
|
I.click('.set-individual-value')
|
|
86
|
-
I.
|
|
96
|
+
I.waitForElement('.name-changed')
|
|
87
97
|
})
|
|
88
98
|
|
|
89
|
-
Scenario('should watch form for changes', async ({ I }) => {
|
|
99
|
+
Scenario('should watch form for changes @core @change', async ({ I }) => {
|
|
90
100
|
I.amOnPage('core.html')
|
|
91
101
|
I.dontSeeElement('.form-changed')
|
|
92
102
|
I.click('.set-value')
|
|
93
|
-
I.
|
|
103
|
+
I.waitForElement('.form-changed')
|
|
94
104
|
})
|
|
95
105
|
|
|
96
106
|
Scenario('should change the form if form_name_root option is set @core', async ({ I }) => {
|
|
@@ -4,6 +4,43 @@ const { DEFAULT_WAIT_TIME } = require('../test-config')
|
|
|
4
4
|
|
|
5
5
|
Feature('array')
|
|
6
6
|
|
|
7
|
+
Scenario('Should display properties enum titles in items headerTemplate @headerTemplate', async ({ I }) => {
|
|
8
|
+
I.amOnPage('array-header-template.html')
|
|
9
|
+
I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
|
|
10
|
+
I.waitForText('Dog', DEFAULT_WAIT_TIME, '.nav-link span')
|
|
11
|
+
I.waitForText('Cat', DEFAULT_WAIT_TIME, '.nav-link span')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
Scenario('Should set buttons states correctly @button_state_mode', async ({ I }) => {
|
|
15
|
+
I.amOnPage('button_state_mode_1.html')
|
|
16
|
+
I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
|
|
17
|
+
I.waitForElement('.json-editor-btntype-add', DEFAULT_WAIT_TIME)
|
|
18
|
+
I.waitForElement('.json-editor-btn-movedown', DEFAULT_WAIT_TIME)
|
|
19
|
+
I.waitForElement('.json-editor-btn-moveup', DEFAULT_WAIT_TIME)
|
|
20
|
+
I.dontSeeElement('.json-editor-btntype-delete')
|
|
21
|
+
I.dontSeeElement('.json-editor-btntype-deletelast')
|
|
22
|
+
I.dontSeeElement('.json-editor-btntype-deleteall')
|
|
23
|
+
I.click('.json-editor-btntype-add')
|
|
24
|
+
I.waitForElement('.json-editor-btntype-delete')
|
|
25
|
+
I.waitForElement('.json-editor-btntype-deletelast')
|
|
26
|
+
I.waitForElement('.json-editor-btntype-deleteall')
|
|
27
|
+
|
|
28
|
+
I.amOnPage('button_state_mode_2.html')
|
|
29
|
+
I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
|
|
30
|
+
I.waitForElement('.json-editor-btntype-add', DEFAULT_WAIT_TIME)
|
|
31
|
+
I.waitForElement('.json-editor-btn-movedown', DEFAULT_WAIT_TIME)
|
|
32
|
+
I.waitForElement('.json-editor-btn-moveup', DEFAULT_WAIT_TIME)
|
|
33
|
+
I.waitForElement('.json-editor-btntype-delete', DEFAULT_WAIT_TIME)
|
|
34
|
+
I.waitForElement('.json-editor-btntype-deletelast', DEFAULT_WAIT_TIME)
|
|
35
|
+
I.seeDisabledAttribute('.json-editor-btntype-delete')
|
|
36
|
+
I.seeDisabledAttribute('.json-editor-btntype-deletelast')
|
|
37
|
+
I.seeDisabledAttribute('.json-editor-btntype-deleteall')
|
|
38
|
+
I.click('.json-editor-btntype-add')
|
|
39
|
+
I.dontSeeDisabledAttribute('.json-editor-btntype-delete')
|
|
40
|
+
I.dontSeeDisabledAttribute('.json-editor-btntype-deletelast')
|
|
41
|
+
I.dontSeeDisabledAttribute('.json-editor-btntype-deleteall')
|
|
42
|
+
})
|
|
43
|
+
|
|
7
44
|
Scenario('should have correct initial value', async ({ I }) => {
|
|
8
45
|
I.amOnPage('array.html')
|
|
9
46
|
I.click('.get-value')
|
|
@@ -963,3 +1000,25 @@ Scenario('should work well with selectize multiselect editors', async ({ I }) =>
|
|
|
963
1000
|
I.seeElement('[data-schemapath="root.0"] .selectize-dropdown-content [data-value="3"]')
|
|
964
1001
|
I.seeElement('[data-schemapath="root.0"] .selectize-dropdown-content [data-value="4"]')
|
|
965
1002
|
})
|
|
1003
|
+
|
|
1004
|
+
Scenario('should be possible to add items to selectize array @selectize-add', async ({ I }) => {
|
|
1005
|
+
I.amOnPage('array-selectize-create.html')
|
|
1006
|
+
I.click('.selectize-input')
|
|
1007
|
+
I.pressKey('g')
|
|
1008
|
+
I.pressKey('Enter')
|
|
1009
|
+
I.pressKey('r')
|
|
1010
|
+
I.pressKey('Enter')
|
|
1011
|
+
I.pressKey('e')
|
|
1012
|
+
I.pressKey('Enter')
|
|
1013
|
+
I.pressKey('a')
|
|
1014
|
+
I.pressKey('Enter')
|
|
1015
|
+
I.pressKey('t')
|
|
1016
|
+
I.pressKey('Enter')
|
|
1017
|
+
I.waitForValue('#value', '["g","r","e","a","t"]')
|
|
1018
|
+
})
|
|
1019
|
+
|
|
1020
|
+
Scenario('Tables should have a container parent that makes tables responsive @array-table', async ({ I }) => {
|
|
1021
|
+
I.amOnPage('array-table-responsive.html')
|
|
1022
|
+
I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
|
|
1023
|
+
I.waitForElement('.table-responsive')
|
|
1024
|
+
})
|
|
@@ -5,7 +5,9 @@ Feature('autocomplete')
|
|
|
5
5
|
Scenario('autocomplete should work @autocomplete', async ({ I }) => {
|
|
6
6
|
I.amOnPage('autocomplete.html')
|
|
7
7
|
I.waitForElement('.je-ready', 10)
|
|
8
|
-
I.
|
|
8
|
+
I.click('[name="root"]')
|
|
9
|
+
I.pressKey('i')
|
|
10
|
+
I.pressKey('r')
|
|
9
11
|
I.waitForText('iran', 20, '.autocomplete-result-list')
|
|
10
12
|
I.waitForText('iraq', 20, '.autocomplete-result-list')
|
|
11
13
|
I.click('iraq', '.autocomplete-result:nth-child(2)')
|
|
@@ -5,6 +5,26 @@ const { DEFAULT_WAIT_TIME } = require('../test-config')
|
|
|
5
5
|
|
|
6
6
|
Feature('object')
|
|
7
7
|
|
|
8
|
+
Scenario('@case-sensitive-property-search', async ({ I }) => {
|
|
9
|
+
I.amOnPage('object-case-sensitive-property-search-true.html')
|
|
10
|
+
I.click('.json-editor-btn-edit_properties')
|
|
11
|
+
I.fillField('.property-selector-input', 'aaa')
|
|
12
|
+
I.see('aaa', '.form-check label')
|
|
13
|
+
I.dontSee('AAA', '.form-check label')
|
|
14
|
+
I.fillField('.property-selector-input', 'AAA')
|
|
15
|
+
I.see('AAA', '.form-check label')
|
|
16
|
+
I.dontSee('aaa', '.form-check label')
|
|
17
|
+
|
|
18
|
+
I.amOnPage('object-case-sensitive-property-search-false.html')
|
|
19
|
+
I.click('.json-editor-btn-edit_properties')
|
|
20
|
+
I.fillField('.property-selector-input', 'aaa')
|
|
21
|
+
I.see('aaa', '.form-check label')
|
|
22
|
+
I.see('AAA', '.form-check label')
|
|
23
|
+
I.fillField('.property-selector-input', 'AAA')
|
|
24
|
+
I.see('AAA', '.form-check label')
|
|
25
|
+
I.see('aaa', '.form-check label')
|
|
26
|
+
})
|
|
27
|
+
|
|
8
28
|
Scenario('should respect property orders', async ({ I }) => {
|
|
9
29
|
I.amOnPage('object.html')
|
|
10
30
|
assert.strictEqual(await I.grabAttributeFrom('[data-schemapath^="root"] .row:nth-of-type(1) [data-schemapath^="root."]', 'data-schemapath'), 'root.age')
|
|
@@ -4,7 +4,7 @@ const { DEFAULT_WAIT_TIME } = require('../test-config')
|
|
|
4
4
|
|
|
5
5
|
Feature('Tabs')
|
|
6
6
|
|
|
7
|
-
Scenario('test top-tabs', ({ I }) => {
|
|
7
|
+
Scenario('test @top-tabs', ({ I }) => {
|
|
8
8
|
I.amOnPage('tabs.html')
|
|
9
9
|
I.waitForElement('[data-schemapath="root"] .json-editor-btn-add')
|
|
10
10
|
I.click('[data-schemapath="root"] .json-editor-btn-add')
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1330 should remain fixed @issue-1330 @multiselect', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1330.html')
|
|
7
|
+
I.waitForElement('[data-schemapath="root.test"] input[type="checkbox"]')
|
|
8
|
+
})
|
|
@@ -7,10 +7,12 @@ Scenario('GitHub issue 1338 should remain fixed @issue-1338', async ({ I }) => {
|
|
|
7
7
|
I.waitForText('Value required')
|
|
8
8
|
I.fillField('[id="root[field_a]"]', 'test')
|
|
9
9
|
I.pressKey('Tab')
|
|
10
|
+
I.waitForInvisible('.invalid-feedback')
|
|
10
11
|
I.dontSee('Value required')
|
|
11
12
|
I.refreshPage()
|
|
12
13
|
I.waitForText('Value required')
|
|
13
14
|
I.fillField('[id="root[field_b]"]', 'test')
|
|
14
15
|
I.pressKey('Tab')
|
|
16
|
+
I.waitForInvisible('.invalid-feedback')
|
|
15
17
|
I.dontSee('Value required')
|
|
16
18
|
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('GitHub issue 1364')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1364 should remain fixed @issue-1364', ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1364.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForValue('#value', '{"engine":"none","child1":{}}')
|
|
9
|
+
I.selectOption('[id="root[engine]"]', 'test1')
|
|
10
|
+
I.waitForValue('#value', '{"engine":"test1","child1":{"L2Name":""},"L1Name":""}')
|
|
11
|
+
I.selectOption('[id="root[engine]"]', 'none')
|
|
12
|
+
I.waitForValue('#value', '{"engine":"none","child1":{}}')
|
|
13
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
|
|
4
|
+
Feature('GitHub issue 1367')
|
|
5
|
+
|
|
6
|
+
Scenario('GitHub issue 1367 should remain fixed @issue-1367', async ({ I }) => {
|
|
7
|
+
I.amOnPage('issues/issue-gh-1367.html')
|
|
8
|
+
I.waitForElement('.je-ready')
|
|
9
|
+
I.click('canvas')
|
|
10
|
+
assert.match(await I.grabValueFrom('#value'), /base64/)
|
|
11
|
+
})
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1384 should remain fixed @issue-1384 @optional', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1384.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForText('Zope layout definition')
|
|
9
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1410 should remain fixed @issue-1410', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1410.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.click('[data-schemapath="root.standard"] .json-editor-btn-edit_properties')
|
|
9
|
+
I.waitForInvisible('[data-schemapath="root.standard"] .json-editor-btn-add')
|
|
10
|
+
I.click('[data-schemapath="root.standard"] .json-editor-btn-edit_properties')
|
|
11
|
+
I.click('[data-schemapath="root.extras"] .json-editor-btn-edit_properties')
|
|
12
|
+
I.waitForVisible('[data-schemapath="root.extras"] .json-editor-btn-add')
|
|
13
|
+
})
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1422 should remain fixed @issue-1422', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1422.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForValue('#value', '{"req":5,"opt":5,"req_with_default":5}')
|
|
9
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1431 should remain fixed @issue-1431', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1431.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForElement('.CodeMirror')
|
|
9
|
+
I.click('.CodeMirror')
|
|
10
|
+
I.pressKeys('simple-mde')
|
|
11
|
+
I.waitForValue('#value', '{"name":"simple-mde"}')
|
|
12
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* global Feature Scenario */
|
|
2
|
+
|
|
3
|
+
Feature('issues')
|
|
4
|
+
|
|
5
|
+
Scenario('GitHub issue 1439 should remain fixed @issue-1439', async ({ I }) => {
|
|
6
|
+
I.amOnPage('issues/issue-gh-1439.html')
|
|
7
|
+
I.waitForElement('.je-ready')
|
|
8
|
+
I.waitForElement('[name="root[wrong]"]')
|
|
9
|
+
I.waitForElement('[data-schemapath="root.correct"] button')
|
|
10
|
+
I.waitForText('Button text')
|
|
11
|
+
I.waitForValue('#value', '{"wrong":""}')
|
|
12
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"/>
|
|
5
|
+
<title>array-header-template</title>
|
|
6
|
+
<script src="../../dist/jsoneditor.js"></script>
|
|
7
|
+
<link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
|
|
8
|
+
<link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
|
|
12
|
+
<div class="container">
|
|
13
|
+
<div id='editor-container'></div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<script>
|
|
17
|
+
const editorContainer = document.querySelector('#editor-container')
|
|
18
|
+
const schema1 = {
|
|
19
|
+
"title": "Pets",
|
|
20
|
+
"format": "tabs",
|
|
21
|
+
"type": "array",
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"default": [
|
|
24
|
+
{
|
|
25
|
+
"pet": "pet_1"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"pet": "pet_2"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"items": {
|
|
32
|
+
"title": "Pets",
|
|
33
|
+
"type": "object",
|
|
34
|
+
"headerTemplate": "{{ properties.pet.enumTitle }}",
|
|
35
|
+
"properties": {
|
|
36
|
+
"pet": {
|
|
37
|
+
"title": "Pet",
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": [ "pet_1", "pet_2" ],
|
|
40
|
+
"options": {
|
|
41
|
+
"enum_titles": [ "Dog", "Cat" ]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const editor = new JSONEditor(editorContainer, {
|
|
49
|
+
schema: schema1,
|
|
50
|
+
theme: 'bootstrap4',
|
|
51
|
+
iconlib: 'fontawesome',
|
|
52
|
+
disable_collapse: true,
|
|
53
|
+
disable_edit_json: true,
|
|
54
|
+
disable_properties: true
|
|
55
|
+
})
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|