mirror of
https://github.com/yjs/yjs.git
synced 2025-12-15 19:27:45 +01:00
fix all tests
This commit is contained in:
@@ -571,7 +571,7 @@ export class AbstractType {
|
||||
if (c.deleted ? retainDeletes : retainInserts) {
|
||||
d.retain(c.content.getLength(), null, attribution ?? {})
|
||||
} else if (deep && c.content.constructor === ContentType) {
|
||||
d.insert([/** @type {any} */(c.content).type.getContent(am, opts)], null, attribution)
|
||||
d.insert([/** @type {any} */(c.content).type.getContent(am, { ...opts, renderChildren: true, renderAttrs: null })], null, attribution)
|
||||
} else {
|
||||
d.insert(c.content.getContent(), null, attribution)
|
||||
}
|
||||
@@ -579,6 +579,7 @@ export class AbstractType {
|
||||
d.delete(1)
|
||||
} else if (retainContent) {
|
||||
if (c.content.constructor === ContentType && modified?.has(/** @type {ContentType} */ (c.content).type)) {
|
||||
// @todo use current transaction instead
|
||||
d.modify(/** @type {any} */ (c.content).type.getContent(am, opts))
|
||||
} else {
|
||||
d.usedAttributes = changedAttributes
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
YEvent,
|
||||
AbstractType,
|
||||
typeListGet,
|
||||
typeListToArray,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
YEvent,
|
||||
AbstractType,
|
||||
typeListMap,
|
||||
typeListForEach,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
import * as Y from '../src/index.js'
|
||||
import * as delta from 'lib0/delta'
|
||||
import * as t from 'lib0/testing'
|
||||
import * as s from 'lib0/schema'
|
||||
|
||||
/**
|
||||
* Delta is a versatyle format enabling you to efficiently describe changes. It is part of lib0, so
|
||||
@@ -20,7 +21,7 @@ import * as t from 'lib0/testing'
|
||||
* The "|" describes the current cursor position.
|
||||
*
|
||||
* - d.retain(5) - "|hello world" => "hello| world" - jump over the next five characters
|
||||
* - d.delete(6) - "hello| world" => "hello|" - delete the next 6 characres
|
||||
* - d.delete(6) - "hello| world" => "hello|" - delete the next 6 characres
|
||||
* - d.insert('!') - "hello!|" - insert "!" at the current position
|
||||
* => compact form: d.retain(5).delete(6).insert('!')
|
||||
*
|
||||
@@ -44,6 +45,34 @@ export const testDeltaBasics = _tc => {
|
||||
t.assert(state.equals(delta.create().insert('hello!')))
|
||||
}
|
||||
|
||||
/**
|
||||
* lib0 also ships a schema library that can be used to validate JSON objects and custom data types,
|
||||
* like Yjs types.
|
||||
*
|
||||
* As a convention, schemas are usually prefixed with a $ sign. This clarifies the difference
|
||||
* between a schema, and an instance of a schema.
|
||||
*
|
||||
* const $myobj = s.$object({ key: s.$number })
|
||||
* let inputValue: any
|
||||
* if ($myobj.check(inputValue)) {
|
||||
* inputValue // is validated and of type $myobj
|
||||
* }
|
||||
*
|
||||
* We can also define the expected values on a delta.
|
||||
*
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
export const testDeltaBasicSchema = _tc => {
|
||||
const $d = delta.$delta({ attrs: s.$object({ key: s.$string }), children: s.$number, hasText: false })
|
||||
const d = delta.create($d)
|
||||
// @ts-expect-error
|
||||
d.set('key', false) // invalid change: will throw a type error
|
||||
t.fails(() => {
|
||||
// @ts-expect-error
|
||||
d.apply(delta.create().set('key', false)) // invalid delta: will throw a type error
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Deltas can describe changes on attributes and children. Textual insertions are children. But we
|
||||
* may also insert json-objects and other deltas as children.
|
||||
@@ -71,9 +100,9 @@ export const testDeltaValues = _tc => {
|
||||
} else if (delta.$deleteOp.check(childChange)) {
|
||||
console.log(`delete ${childChange.delete} child items`)
|
||||
} else if (delta.$insertOp.check(childChange)) {
|
||||
console.log(`insert child items:`, childChange.insert)
|
||||
console.log('insert child items:', childChange.insert)
|
||||
} else if (delta.$textOp.check(childChange)) {
|
||||
console.log(`insert textual content`, childChange.insert)
|
||||
console.log('insert textual content', childChange.insert)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export const testInconsistentFormat = () => {
|
||||
const content = /** @type {Y.XmlText} */ (ydoc.get('text', Y.XmlText))
|
||||
content.format(0, 6, { bold: null })
|
||||
content.format(6, 4, { type: 'text' })
|
||||
t.compare(content.getContent(), delta.create().insert('Merge Test', { type: 'text' }).insert(' After', { type: 'text', italic: true }))
|
||||
t.compare(content.getContent(), delta.create().insert('Merge Test', { type: 'text' }).insert(' After', { type: 'text', italic: true }).done())
|
||||
}
|
||||
const initializeYDoc = () => {
|
||||
const yDoc = new Y.Doc({ gc: false })
|
||||
@@ -298,17 +298,18 @@ export const testUndoXml = tc => {
|
||||
t.assert(xml0.toString() === '<undefined><p>content</p></undefined>')
|
||||
// format textchild and revert that change
|
||||
undoManager.stopCapturing()
|
||||
textchild.format(3, 4, { bold: {} })
|
||||
t.compare(xml0.getContentDeep(), delta.create('UNDEFINED').insert([delta.text().insert('con').insert('tent', { bold: true }).done()]).done())
|
||||
t.assert(xml0.toString() === '<undefined><p>con<bold>tent</bold></p></undefined>')
|
||||
textchild.format(3, 4, { bold: true })
|
||||
const v1 = delta.create('UNDEFINED').insert([delta.create('p').insert([delta.text().insert('con').insert('tent', { bold: true }).done()]).done()]).done()
|
||||
const v2 = delta.create('UNDEFINED').insert([delta.create('p').insert([delta.text().insert('content').done()]).done()]).done()
|
||||
t.compare(xml0.getContentDeep(), v1)
|
||||
undoManager.undo()
|
||||
t.assert(xml0.toString() === '<undefined><p>content</p></undefined>')
|
||||
t.compare(xml0.getContentDeep(), v2)
|
||||
undoManager.redo()
|
||||
t.assert(xml0.toString() === '<undefined><p>con<bold>tent</bold></p></undefined>')
|
||||
t.compare(xml0.getContentDeep(), v1)
|
||||
xml0.delete(0, 1)
|
||||
t.assert(xml0.toString() === '<undefined></undefined>')
|
||||
t.compare(xml0.getContentDeep(), delta.create('UNDEFINED'))
|
||||
undoManager.undo()
|
||||
t.assert(xml0.toString() === '<undefined><p>con<bold>tent</bold></p></undefined>')
|
||||
t.compare(xml0.getContentDeep(), v1)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1439,18 +1439,18 @@ export const testTypesAsEmbed = tc => {
|
||||
text0.applyDelta(delta.create()
|
||||
.insert([new Y.Map([['key', 'val']])])
|
||||
)
|
||||
t.compare(/** @type {any} */ (text0).getContentDeep().toJSON().children, [{ type: 'insert', insert: [{ attrs: { key: { type: 'insert', value: 'val' } } }] }])
|
||||
t.compare(/** @type {any} */ (text0).getContentDeep().toJSON().children, [{ type: 'insert', insert: [{ type: 'delta', attrs: { key: { type: 'insert', value: 'val' } } }] }])
|
||||
let firedEvent = false
|
||||
text1.observe(event => {
|
||||
const d = event.deltaDeep
|
||||
t.assert(d.children.len === 1)
|
||||
t.compare(d.toJSON().children?.map(x => /** @type {any} */ (x).insert), [[{ key: { type: 'insert', value: 'val' } }]])
|
||||
t.compare(d.toJSON().children?.map(x => /** @type {any} */ (x).insert), [[{ type: 'delta', attrs: { key: { type: 'insert', value: 'val' } } }]])
|
||||
firedEvent = true
|
||||
})
|
||||
testConnector.flushAllMessages()
|
||||
const dd = text1.getContent().toJSON().children
|
||||
const dd = text1.getContentDeep().toJSON().children
|
||||
t.assert(dd?.length === 1)
|
||||
t.compare(/** @type {any} */ (dd?.[0]).insert, { key: 'val' })
|
||||
t.compare(/** @type {any} */ (dd?.[0]).insert[0], { type: 'delta', attrs: { key: { type: 'insert', value: 'val' } } })
|
||||
t.assert(firedEvent, 'fired the event observer containing a Type-Embed')
|
||||
}
|
||||
|
||||
|
||||
@@ -59,46 +59,6 @@ export const testHasProperty = tc => {
|
||||
compare(users)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
*/
|
||||
export const testEvents = tc => {
|
||||
const { testConnector, users, xml0, xml1 } = init(tc, { users: 2 })
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
let event
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
let remoteEvent
|
||||
xml0.observe(e => {
|
||||
event = e
|
||||
})
|
||||
xml1.observe(e => {
|
||||
remoteEvent = e
|
||||
})
|
||||
xml0.setAttribute('key', 'value')
|
||||
t.assert(event.attributesChanged.has('key'), 'YXmlEvent.attributesChanged on updated key')
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(remoteEvent.attributesChanged.has('key'), 'YXmlEvent.attributesChanged on updated key (remote)')
|
||||
// check attributeRemoved
|
||||
xml0.removeAttribute('key')
|
||||
t.assert(event.attributesChanged.has('key'), 'YXmlEvent.attributesChanged on removed attribute')
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(remoteEvent.attributesChanged.has('key'), 'YXmlEvent.attributesChanged on removed attribute (remote)')
|
||||
xml0.insert(0, [new Y.XmlText('some text')])
|
||||
t.assert(event.childListChanged, 'YXmlEvent.childListChanged on inserted element')
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(remoteEvent.childListChanged, 'YXmlEvent.childListChanged on inserted element (remote)')
|
||||
// test childRemoved
|
||||
xml0.delete(0)
|
||||
t.assert(event.childListChanged, 'YXmlEvent.childListChanged on deleted element')
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(remoteEvent.childListChanged, 'YXmlEvent.childListChanged on deleted element (remote)')
|
||||
compare(users)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} _tc
|
||||
*/
|
||||
@@ -252,28 +212,31 @@ export const testElementAttributedContent = _tc => {
|
||||
yelement.insert(1, [elem3])
|
||||
yelement.setAttribute('key', '42')
|
||||
})
|
||||
const expectedContent = delta.create().insert([elem1], null, { delete: [] }).insert([elem2]).insert([elem3], null, { insert: [] })
|
||||
const expectedContent = delta.create('UNDEFINED').insert([elem1], null, { delete: [] }).insert([elem2]).insert([elem3], null, { insert: [] }).set('key', '42', { insert: [] })
|
||||
const attributedContent = yelement.getContent(attributionManager)
|
||||
console.log('children', attributedContent.toJSON())
|
||||
console.log('attributes', attributedContent)
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42', attribution: { insert: [] } } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42', attribution: { insert: [] } } })
|
||||
t.group('test getContentDeep', () => {
|
||||
const expectedContent = delta.create().insert(
|
||||
[delta.text().insert('hello', null, { delete: [] })],
|
||||
null,
|
||||
{ delete: [] }
|
||||
).insert([delta.create('span')])
|
||||
const expectedContent = delta.create('UNDEFINED')
|
||||
.insert(
|
||||
[delta.text().insert('hello', null, { delete: [] })],
|
||||
null,
|
||||
{ delete: [] }
|
||||
)
|
||||
.insert([delta.create('span')])
|
||||
.insert([
|
||||
delta.text().insert('world', null, { insert: [] })
|
||||
], null, { insert: [] })
|
||||
.set('key', '42', { insert: [] })
|
||||
.done()
|
||||
const attributedContent = yelement.getContentDeep(attributionManager)
|
||||
console.log('children', JSON.stringify(attributedContent.toJSON().children, null, 2))
|
||||
console.log('cs expec', JSON.stringify(expectedContent.toJSON(), null, 2))
|
||||
console.log('attributes', attributedContent.toJSON().attrs)
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent, delta.map().set('key', '42', { insert: [] }))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42', attribution: { insert: [] } } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42', attribution: { insert: [] } } })
|
||||
t.assert(attributedContent.name === 'UNDEFINED')
|
||||
})
|
||||
})
|
||||
@@ -296,28 +259,31 @@ export const testElementAttributedContentViaDiffer = _tc => {
|
||||
yelement.setAttribute('key', '42')
|
||||
})
|
||||
const attributionManager = Y.createAttributionManagerFromDiff(ydocV1, ydoc)
|
||||
const expectedContent = delta.create().insert([delta.create().insert('hello')], null, { delete: [] }).insert([elem2.getContentDeep()]).insert([delta.create().insert('world', null, { insert: [] })], null, { insert: [] })
|
||||
const expectedContent = delta.create('UNDEFINED').insert([delta.create().insert('hello')], null, { delete: [] }).insert([elem2.getContentDeep()]).insert([delta.create().insert('world', null, { insert: [] })], null, { insert: [] }).set('key', '42', { insert: [] })
|
||||
const attributedContent = yelement.getContentDeep(attributionManager)
|
||||
console.log('children', attributedContent.toJSON().children)
|
||||
console.log('attributes', attributedContent.toJSON().attrs)
|
||||
t.compare(attributedContent.toJSON(), expectedContent.toJSON())
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42', attribution: { insert: [] } } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42', attribution: { insert: [] } } })
|
||||
t.group('test getContentDeep', () => {
|
||||
const expectedContent = delta.create().insert(
|
||||
[delta.create().insert('hello')],
|
||||
null,
|
||||
{ delete: [] }
|
||||
).insert([delta.create('span')])
|
||||
const expectedContent = delta.create('UNDEFINED')
|
||||
.insert(
|
||||
[delta.create().insert('hello')],
|
||||
null,
|
||||
{ delete: [] }
|
||||
)
|
||||
.insert([delta.create('span')])
|
||||
.insert([
|
||||
delta.create().insert('world', null, { insert: [] })
|
||||
], null, { insert: [] })
|
||||
.set('key', '42', { insert: [] })
|
||||
const attributedContent = yelement.getContentDeep(attributionManager)
|
||||
console.log('children', JSON.stringify(attributedContent.toJSON().children, null, 2))
|
||||
console.log('cs expec', JSON.stringify(expectedContent.toJSON(), null, 2))
|
||||
console.log('attributes', attributedContent.toJSON().attrs)
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42', attribution: { insert: [] } } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42', attribution: { insert: [] } } })
|
||||
t.assert(attributedContent.name === 'UNDEFINED')
|
||||
})
|
||||
ydoc.transact(() => {
|
||||
@@ -325,34 +291,37 @@ export const testElementAttributedContentViaDiffer = _tc => {
|
||||
})
|
||||
t.group('test getContentDeep after some more updates', () => {
|
||||
t.info('expecting diffingAttributionManager to auto update itself')
|
||||
const expectedContent = delta.create().insert(
|
||||
[delta.create().insert('hello')],
|
||||
null,
|
||||
{ delete: [] }
|
||||
).insert([delta.create('span')])
|
||||
const expectedContent = delta.create('UNDEFINED')
|
||||
.insert(
|
||||
[delta.create().insert('hello')],
|
||||
null,
|
||||
{ delete: [] }
|
||||
)
|
||||
.insert([delta.create('span')])
|
||||
.insert([
|
||||
delta.create().insert('bigworld', null, { insert: [] })
|
||||
], null, { insert: [] })
|
||||
.set('key', '42', { insert: [] })
|
||||
const attributedContent = yelement.getContentDeep(attributionManager)
|
||||
console.log('children', JSON.stringify(attributedContent.toJSON().children, null, 2))
|
||||
console.log('cs expec', JSON.stringify(expectedContent.toJSON(), null, 2))
|
||||
console.log('attributes', attributedContent.toJSON().attrs)
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42', attribution: { insert: [] } } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42', attribution: { insert: [] } } })
|
||||
t.assert(attributedContent.name === 'UNDEFINED')
|
||||
})
|
||||
Y.applyUpdate(ydocV1, Y.encodeStateAsUpdate(ydoc))
|
||||
t.group('test getContentDeep both docs synced', () => {
|
||||
t.info('expecting diffingAttributionManager to auto update itself')
|
||||
const expectedContent = delta.create().insert([delta.create('span')]).insert([
|
||||
const expectedContent = delta.create('UNDEFINED').insert([delta.create('span')]).insert([
|
||||
delta.create().insert('bigworld')
|
||||
])
|
||||
]).set('key', '42')
|
||||
const attributedContent = yelement.getContentDeep(attributionManager)
|
||||
console.log('children', JSON.stringify(attributedContent.toJSON().children, null, 2))
|
||||
console.log('cs expec', JSON.stringify(expectedContent.toJSON(), null, 2))
|
||||
console.log('attributes', attributedContent.toJSON().attrs)
|
||||
t.assert(attributedContent.equals(expectedContent))
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', prevValue: undefined, value: '42' } })
|
||||
t.compare(attributedContent.toJSON().attrs, { key: { type: 'insert', value: '42' } })
|
||||
t.assert(attributedContent.name === 'UNDEFINED')
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user