Files
yjs/tests/y-map.tests.js

791 lines
21 KiB
JavaScript
Raw Normal View History

import * as Y from '../src/index.js'
import { init, compare, applyRandomTests, Doc } from './testHelper.js' // eslint-disable-line
2019-04-06 13:00:32 +02:00
import {
2025-04-28 02:42:06 +02:00
compareIDs,
noAttributionsManager,
TwosetAttributionManager,
createIdMapFromIdSet
2019-04-06 13:00:32 +02:00
} from '../src/internals.js'
2021-05-14 18:53:24 +02:00
import * as t from 'lib0/testing'
import * as prng from 'lib0/prng'
import * as delta from 'lib0/delta'
import * as s from 'lib0/schema'
2017-08-09 02:21:17 +02:00
2023-11-20 12:53:58 +01:00
/**
* @param {t.TestCase} _tc
*/
export const testIterators = _tc => {
const ydoc = new Y.Doc()
/**
* @type {Y.Map<number>}
*/
const ymap = ydoc.getMap()
// we are only checking if the type assumptions are correct
/**
* @type {Array<number>}
*/
const vals = Array.from(ymap.values())
/**
* @type {Array<[string,number]>}
*/
const entries = Array.from(ymap.entries())
/**
* @type {Array<string>}
*/
const keys = Array.from(ymap.keys())
console.log(vals, entries, keys)
}
/**
* Computing event changes after transaction should result in an error. See yjs#539
*
* @param {t.TestCase} _tc
*/
export const testMapEventError = _tc => {
const doc = new Y.Doc()
const ymap = doc.getMap()
/**
* @type {any}
*/
let event = null
ymap.observe((e) => {
event = e
})
t.fails(() => {
t.info(event.keys)
})
t.fails(() => {
t.info(event.keys)
})
}
/**
* @param {t.TestCase} tc
*/
export const testMapHavingIterableAsConstructorParamTests = tc => {
const { map0 } = init(tc, { users: 1 })
const m1 = new Y.Map(Object.entries({ number: 1, string: 'hello' }))
map0.set('m1', m1)
t.assert(m1.get('number') === 1)
t.assert(m1.get('string') === 'hello')
const m2 = new Y.Map([
['object', { x: 1 }],
['boolean', true]
])
map0.set('m2', m2)
t.assert(m2.get('object').x === 1)
t.assert(m2.get('boolean') === true)
const m3 = new Y.Map([...m1, ...m2])
map0.set('m3', m3)
t.assert(m3.get('number') === 1)
t.assert(m3.get('string') === 'hello')
t.assert(m3.get('object').x === 1)
t.assert(m3.get('boolean') === true)
}
/**
* @param {t.TestCase} tc
*/
export const testBasicMapTests = tc => {
const { testConnector, users, map0, map1, map2 } = init(tc, { users: 3 })
2017-08-09 02:21:17 +02:00
users[2].disconnect()
map0.set('null', null)
2017-08-09 02:21:17 +02:00
map0.set('number', 1)
map0.set('string', 'hello Y')
map0.set('object', { key: { key2: 'value' } })
map0.set('y-map', new Y.Map())
map0.set('boolean1', true)
map0.set('boolean0', false)
const map = map0.get('y-map')
map.set('y-array', new Y.Array())
const array = map.get('y-array')
2017-08-09 02:21:17 +02:00
array.insert(0, [0])
array.insert(0, [-1])
t.assert(map0.get('null') === null, 'client 0 computed the change (null)')
2017-08-09 02:21:17 +02:00
t.assert(map0.get('number') === 1, 'client 0 computed the change (number)')
t.assert(map0.get('string') === 'hello Y', 'client 0 computed the change (string)')
t.assert(map0.get('boolean0') === false, 'client 0 computed the change (boolean)')
t.assert(map0.get('boolean1') === true, 'client 0 computed the change (boolean)')
2017-08-09 02:21:17 +02:00
t.compare(map0.get('object'), { key: { key2: 'value' } }, 'client 0 computed the change (object)')
t.assert(map0.get('y-map').get('y-array').get(0) === -1, 'client 0 computed the change (type)')
t.assert(map0.size === 7, 'client 0 map has correct size')
2017-08-09 02:21:17 +02:00
users[2].connect()
testConnector.flushAllMessages()
2017-08-09 02:21:17 +02:00
t.assert(map1.get('null') === null, 'client 1 received the update (null)')
2017-08-09 02:21:17 +02:00
t.assert(map1.get('number') === 1, 'client 1 received the update (number)')
t.assert(map1.get('string') === 'hello Y', 'client 1 received the update (string)')
t.assert(map1.get('boolean0') === false, 'client 1 computed the change (boolean)')
t.assert(map1.get('boolean1') === true, 'client 1 computed the change (boolean)')
2017-08-09 02:21:17 +02:00
t.compare(map1.get('object'), { key: { key2: 'value' } }, 'client 1 received the update (object)')
t.assert(map1.get('y-map').get('y-array').get(0) === -1, 'client 1 received the update (type)')
t.assert(map1.size === 7, 'client 1 map has correct size')
2017-08-09 02:21:17 +02:00
// compare disconnected user
t.assert(map2.get('null') === null, 'client 2 received the update (null) - was disconnected')
2017-08-09 02:21:17 +02:00
t.assert(map2.get('number') === 1, 'client 2 received the update (number) - was disconnected')
t.assert(map2.get('string') === 'hello Y', 'client 2 received the update (string) - was disconnected')
t.assert(map2.get('boolean0') === false, 'client 2 computed the change (boolean)')
t.assert(map2.get('boolean1') === true, 'client 2 computed the change (boolean)')
2017-08-09 02:21:17 +02:00
t.compare(map2.get('object'), { key: { key2: 'value' } }, 'client 2 received the update (object) - was disconnected')
t.assert(map2.get('y-map').get('y-array').get(0) === -1, 'client 2 received the update (type) - was disconnected')
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testGetAndSetOfMapProperty = tc => {
const { testConnector, users, map0 } = init(tc, { users: 2 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'stuffy')
map0.set('undefined', undefined)
map0.set('null', null)
2017-08-09 02:21:17 +02:00
t.compare(map0.get('stuff'), 'stuffy')
testConnector.flushAllMessages()
2017-08-09 02:21:17 +02:00
2020-01-22 16:42:16 +01:00
for (const user of users) {
2019-04-03 03:08:10 +02:00
const u = user.getMap('map')
2017-08-09 02:21:17 +02:00
t.compare(u.get('stuff'), 'stuffy')
t.assert(u.get('undefined') === undefined, 'undefined')
t.compare(u.get('null'), null, 'null')
2017-08-09 02:21:17 +02:00
}
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testYmapSetsYmap = tc => {
const { users, map0 } = init(tc, { users: 2 })
const map = map0.set('Map', new Y.Map())
t.assert(map0.get('Map') === map)
2017-08-09 02:21:17 +02:00
map.set('one', 1)
t.compare(map.get('one'), 1)
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testYmapSetsYarray = tc => {
const { users, map0 } = init(tc, { users: 2 })
const array = map0.set('Array', new Y.Array())
2019-03-11 12:31:37 +01:00
t.assert(array === map0.get('Array'))
array.insert(0, [1, 2, 3])
2019-04-03 03:08:10 +02:00
// @ts-ignore
t.compare(map0.toJSON(), { Array: [1, 2, 3] })
compare(users)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testGetAndSetOfMapPropertySyncs = tc => {
const { testConnector, users, map0 } = init(tc, { users: 2 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'stuffy')
t.compare(map0.get('stuff'), 'stuffy')
testConnector.flushAllMessages()
2020-01-22 16:42:16 +01:00
for (const user of users) {
2020-12-19 16:29:17 +01:00
const u = user.getMap('map')
2017-08-09 02:21:17 +02:00
t.compare(u.get('stuff'), 'stuffy')
}
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testGetAndSetOfMapPropertyWithConflict = tc => {
const { testConnector, users, map0, map1 } = init(tc, { users: 3 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'c0')
map1.set('stuff', 'c1')
testConnector.flushAllMessages()
2020-01-22 16:42:16 +01:00
for (const user of users) {
2020-12-19 16:29:17 +01:00
const u = user.getMap('map')
t.compare(u.get('stuff'), 'c1')
2017-08-09 02:21:17 +02:00
}
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
2020-06-07 07:44:37 -06:00
/**
* @param {t.TestCase} tc
*/
export const testSizeAndDeleteOfMapProperty = tc => {
const { map0 } = init(tc, { users: 1 })
map0.set('stuff', 'c0')
map0.set('otherstuff', 'c1')
t.assert(map0.size === 2, `map size is ${map0.size} expected 2`)
map0.delete('stuff')
t.assert(map0.size === 1, `map size after delete is ${map0.size}, expected 1`)
map0.delete('otherstuff')
t.assert(map0.size === 0, `map size after delete is ${map0.size}, expected 0`)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testGetAndSetAndDeleteOfMapProperty = tc => {
const { testConnector, users, map0, map1 } = init(tc, { users: 3 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'c0')
map1.set('stuff', 'c1')
map1.delete('stuff')
testConnector.flushAllMessages()
2020-01-22 16:42:16 +01:00
for (const user of users) {
2020-12-19 16:29:17 +01:00
const u = user.getMap('map')
2017-08-09 02:21:17 +02:00
t.assert(u.get('stuff') === undefined)
}
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testSetAndClearOfMapProperties = tc => {
const { testConnector, users, map0 } = init(tc, { users: 1 })
map0.set('stuff', 'c0')
map0.set('otherstuff', 'c1')
map0.clear()
testConnector.flushAllMessages()
for (const user of users) {
const u = user.getMap('map')
t.assert(u.get('stuff') === undefined)
t.assert(u.get('otherstuff') === undefined)
t.assert(u.size === 0, `map size after clear is ${u.size}, expected 0`)
}
compare(users)
}
/**
* @param {t.TestCase} tc
*/
export const testSetAndClearOfMapPropertiesWithConflicts = tc => {
const { testConnector, users, map0, map1, map2, map3 } = init(tc, { users: 4 })
map0.set('stuff', 'c0')
map1.set('stuff', 'c1')
map1.set('stuff', 'c2')
map2.set('stuff', 'c3')
testConnector.flushAllMessages()
map0.set('otherstuff', 'c0')
map1.set('otherstuff', 'c1')
map2.set('otherstuff', 'c2')
map3.set('otherstuff', 'c3')
map3.clear()
testConnector.flushAllMessages()
for (const user of users) {
const u = user.getMap('map')
t.assert(u.get('stuff') === undefined)
t.assert(u.get('otherstuff') === undefined)
t.assert(u.size === 0, `map size after clear is ${u.size}, expected 0`)
}
compare(users)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testGetAndSetOfMapPropertyWithThreeConflicts = tc => {
const { testConnector, users, map0, map1, map2 } = init(tc, { users: 3 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'c0')
map1.set('stuff', 'c1')
map1.set('stuff', 'c2')
map2.set('stuff', 'c3')
testConnector.flushAllMessages()
2020-01-22 16:42:16 +01:00
for (const user of users) {
2020-12-19 16:29:17 +01:00
const u = user.getMap('map')
t.compare(u.get('stuff'), 'c3')
2017-08-09 02:21:17 +02:00
}
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testGetAndSetAndDeleteOfMapPropertyWithThreeConflicts = tc => {
const { testConnector, users, map0, map1, map2, map3 } = init(tc, { users: 4 })
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'c0')
map1.set('stuff', 'c1')
map1.set('stuff', 'c2')
map2.set('stuff', 'c3')
testConnector.flushAllMessages()
2017-08-09 02:21:17 +02:00
map0.set('stuff', 'deleteme')
map1.set('stuff', 'c1')
map2.set('stuff', 'c2')
map3.set('stuff', 'c3')
map3.delete('stuff')
testConnector.flushAllMessages()
2020-01-22 16:42:16 +01:00
for (const user of users) {
2020-12-19 16:29:17 +01:00
const u = user.getMap('map')
2017-08-09 02:21:17 +02:00
t.assert(u.get('stuff') === undefined)
}
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testObserveDeepProperties = tc => {
const { testConnector, users, map1, map2, map3 } = init(tc, { users: 4 })
const _map1 = map1.set('map', new Y.Map())
let calls = 0
let dmapid
2018-11-25 03:17:00 +01:00
map1.observeDeep(events => {
2017-11-10 12:54:33 -08:00
events.forEach(event => {
calls++
2019-04-03 03:08:10 +02:00
// @ts-ignore
2017-11-10 12:54:33 -08:00
t.assert(event.keysChanged.has('deepmap'))
t.assert(event.path.length === 1)
t.assert(event.path[0] === 'map')
2019-04-03 03:08:10 +02:00
// @ts-ignore
2019-04-06 13:00:32 +02:00
dmapid = event.target.get('deepmap')._item.id
2017-11-10 12:54:33 -08:00
})
2017-08-09 02:21:17 +02:00
})
testConnector.flushAllMessages()
2019-03-11 12:31:37 +01:00
const _map3 = map3.get('map')
_map3.set('deepmap', new Y.Map())
testConnector.flushAllMessages()
2019-03-11 12:31:37 +01:00
const _map2 = map2.get('map')
_map2.set('deepmap', new Y.Map())
testConnector.flushAllMessages()
2019-03-11 12:31:37 +01:00
const dmap1 = _map1.get('deepmap')
const dmap2 = _map2.get('deepmap')
const dmap3 = _map3.get('deepmap')
2017-08-09 02:21:17 +02:00
t.assert(calls > 0)
2019-04-06 13:00:32 +02:00
t.assert(compareIDs(dmap1._item.id, dmap2._item.id))
t.assert(compareIDs(dmap1._item.id, dmap3._item.id))
// @ts-ignore we want the possibility of dmapid being undefined
t.assert(compareIDs(dmap1._item.id, dmapid))
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testObserversUsingObservedeep = tc => {
const { users, map0 } = init(tc, { users: 2 })
2019-04-03 03:08:10 +02:00
/**
2019-04-07 23:08:08 +02:00
* @type {Array<Array<string|number>>}
2019-04-03 03:08:10 +02:00
*/
2025-01-03 18:11:43 +00:00
const paths = []
2019-03-11 12:31:37 +01:00
let calls = 0
2018-11-25 03:17:00 +01:00
map0.observeDeep(events => {
2017-11-10 12:54:33 -08:00
events.forEach(event => {
2025-01-03 18:11:43 +00:00
paths.push(event.path)
2017-11-10 12:54:33 -08:00
})
2017-08-09 02:21:17 +02:00
calls++
})
map0.set('map', new Y.Map())
map0.get('map').set('array', new Y.Array())
2017-08-09 02:21:17 +02:00
map0.get('map').get('array').insert(0, ['content'])
t.assert(calls === 3)
2025-01-03 18:11:43 +00:00
t.compare(paths, [[], ['map'], ['map', 'array']])
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testPathsOfSiblingEvents = tc => {
const { users, map0 } = init(tc, { users: 2 })
/**
* @type {Array<Array<string|number>>}
*/
2025-01-03 18:11:43 +00:00
const paths = []
let calls = 0
const doc = users[0]
map0.set('map', new Y.Map())
map0.get('map').set('text1', new Y.Text('initial'))
map0.observeDeep(events => {
events.forEach(event => {
2025-01-03 18:11:43 +00:00
paths.push(event.path)
})
calls++
})
doc.transact(() => {
map0.get('map').get('text1').insert(0, 'post-')
map0.get('map').set('text2', new Y.Text('new'))
})
t.assert(calls === 1)
2025-01-03 18:11:43 +00:00
t.compare(paths, [['map'], ['map', 'text1']])
compare(users)
}
2019-03-11 12:31:37 +01:00
// TODO: Test events in Y.Map
2019-04-03 03:08:10 +02:00
/**
* @param {Object<string,any>} is
* @param {Object<string,any>} should
*/
const compareEvent = (is, should) => {
2020-12-19 16:29:17 +01:00
for (const key in should) {
t.compare(should[key], is[key])
2017-08-09 02:21:17 +02:00
}
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testThrowsAddAndUpdateAndDeleteEvents = tc => {
const { users, map0 } = init(tc, { users: 2 })
2019-04-03 03:08:10 +02:00
/**
* @type {Object<string,any>}
*/
let event = {}
2018-11-25 03:17:00 +01:00
map0.observe(e => {
2017-08-09 02:21:17 +02:00
event = e // just put it on event, should be thrown synchronously anyway
})
map0.set('stuff', 4)
2019-04-03 03:08:10 +02:00
compareEvent(event, {
2019-03-11 17:52:51 +01:00
target: map0,
keysChanged: new Set(['stuff'])
2017-08-09 02:21:17 +02:00
})
// update, oldValue is in contents
map0.set('stuff', new Y.Array())
2019-04-03 03:08:10 +02:00
compareEvent(event, {
2019-03-11 17:52:51 +01:00
target: map0,
keysChanged: new Set(['stuff'])
2017-08-09 02:21:17 +02:00
})
// update, oldValue is in opContents
map0.set('stuff', 5)
// delete
map0.delete('stuff')
2019-04-03 03:08:10 +02:00
compareEvent(event, {
2019-03-11 17:52:51 +01:00
keysChanged: new Set(['stuff']),
target: map0
2017-08-09 02:21:17 +02:00
})
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testThrowsDeleteEventsOnClear = tc => {
const { users, map0 } = init(tc, { users: 2 })
/**
* @type {Object<string,any>}
*/
let event = {}
map0.observe(e => {
event = e // just put it on event, should be thrown synchronously anyway
})
// set values
map0.set('stuff', 4)
map0.set('otherstuff', new Y.Array())
// clear
map0.clear()
compareEvent(event, {
keysChanged: new Set(['stuff', 'otherstuff']),
target: map0
})
compare(users)
}
2019-09-03 16:33:29 +02:00
/**
* @param {t.TestCase} tc
*/
export const testChangeEvent = tc => {
const { map0, users } = init(tc, { users: 2 })
/**
* @type {delta.Delta<any,any,any,any>?}
2019-09-03 16:33:29 +02:00
*/
let changes = delta.create()
2019-09-03 16:33:29 +02:00
map0.observe(e => {
changes = e.delta
2019-09-03 16:33:29 +02:00
})
map0.set('a', 1)
let keyChange = changes.attrs.get('a')
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
2019-09-03 16:33:29 +02:00
map0.set('a', 2)
keyChange = changes.attrs.get('a')
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === 1)
2019-09-03 16:33:29 +02:00
users[0].transact(() => {
map0.set('a', 3)
map0.set('a', 4)
})
keyChange = changes.attrs.get('a')
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === 2)
2019-09-03 16:33:29 +02:00
users[0].transact(() => {
map0.set('b', 1)
map0.set('b', 2)
})
keyChange = changes.attrs.get('b')
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
2019-09-03 16:33:29 +02:00
users[0].transact(() => {
map0.set('c', 1)
map0.delete('c')
})
t.assert(changes !== null && changes.attrs.size === 0)
2019-09-03 16:33:29 +02:00
users[0].transact(() => {
map0.set('d', 1)
map0.set('d', 2)
})
keyChange = changes.attrs.get('d')
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
2019-09-03 16:33:29 +02:00
compare(users)
}
/**
2023-01-31 12:16:03 +01:00
* @param {t.TestCase} _tc
*/
2023-01-31 12:16:03 +01:00
export const testYmapEventExceptionsShouldCompleteTransaction = _tc => {
const doc = new Y.Doc()
const map = doc.getMap('map')
let updateCalled = false
let throwingObserverCalled = false
let throwingDeepObserverCalled = false
doc.on('update', () => {
updateCalled = true
})
const throwingObserver = () => {
throwingObserverCalled = true
throw new Error('Failure')
}
const throwingDeepObserver = () => {
throwingDeepObserverCalled = true
throw new Error('Failure')
}
map.observe(throwingObserver)
map.observeDeep(throwingDeepObserver)
t.fails(() => {
map.set('y', '2')
})
t.assert(updateCalled)
t.assert(throwingObserverCalled)
t.assert(throwingDeepObserverCalled)
// check if it works again
updateCalled = false
throwingObserverCalled = false
throwingDeepObserverCalled = false
t.fails(() => {
map.set('z', '3')
})
t.assert(updateCalled)
t.assert(throwingObserverCalled)
t.assert(throwingDeepObserverCalled)
t.assert(map.get('z') === '3')
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testYmapEventHasCorrectValueWhenSettingAPrimitive = tc => {
const { users, map0 } = init(tc, { users: 3 })
2019-04-03 03:08:10 +02:00
/**
* @type {Object<string,any>}
*/
let event = {}
2018-11-25 03:17:00 +01:00
map0.observe(e => {
2017-08-09 02:21:17 +02:00
event = e
})
map0.set('stuff', 2)
2017-10-26 19:50:43 +02:00
t.compare(event.value, event.target.get(event.name))
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testYmapEventHasCorrectValueWhenSettingAPrimitiveFromOtherUser = tc => {
const { users, map0, map1, testConnector } = init(tc, { users: 3 })
2019-04-03 03:08:10 +02:00
/**
* @type {Object<string,any>}
*/
let event = {}
2018-11-25 03:17:00 +01:00
map0.observe(e => {
2017-08-09 02:21:17 +02:00
event = e
})
map1.set('stuff', 2)
2019-03-11 12:31:37 +01:00
testConnector.flushAllMessages()
2017-10-26 19:50:43 +02:00
t.compare(event.value, event.target.get(event.name))
2019-03-11 12:31:37 +01:00
compare(users)
}
2017-08-09 02:21:17 +02:00
2025-04-28 02:42:06 +02:00
/**
* @param {t.TestCase} _tc
*/
export const testAttributedContent = _tc => {
const ydoc = new Y.Doc({ gc: false })
const ymap = ydoc.getMap()
let attributionManager = noAttributionsManager
ydoc.on('afterTransaction', tr => {
// attributionManager = new TwosetAttributionManager(createIdMapFromIdSet(tr.insertSet, [new Y.Attribution('insertedAt', 42), new Y.Attribution('insert', 'kevin')]), createIdMapFromIdSet(tr.deleteSet, [new Y.Attribution('delete', 'kevin')]))
attributionManager = new TwosetAttributionManager(createIdMapFromIdSet(tr.insertSet, []), createIdMapFromIdSet(tr.deleteSet, []))
})
t.group('initial value', () => {
ymap.set('test', 42)
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'insert', value: 42, attribution: { insert: [] } }) }
const attributedContent = ymap.getContent(attributionManager)
console.log(attributedContent.toJSON())
t.compare(expectedContent, attributedContent.toJSON().attrs)
2025-04-28 02:42:06 +02:00
})
t.group('overwrite value', () => {
ymap.set('test', 'fourtytwo')
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'insert', prevValue: 42, value: 'fourtytwo', attribution: { insert: [] } }) }
const attributedContent = ymap.getContent(attributionManager)
2025-04-28 02:42:06 +02:00
console.log(attributedContent)
t.compare(expectedContent, attributedContent.toJSON().attrs)
2025-04-28 02:42:06 +02:00
})
t.group('delete value', () => {
ymap.delete('test')
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'delete', prevValue: 'fourtytwo', attribution: { delete: [] } }) }
const attributedContent = ymap.getContent(attributionManager)
console.log(attributedContent.toJSON())
t.compare(expectedContent, attributedContent.toJSON().attrs)
2025-04-28 02:42:06 +02:00
})
}
2019-04-03 03:08:10 +02:00
/**
* @type {Array<function(Doc,prng.PRNG):void>}
2019-04-03 03:08:10 +02:00
*/
2019-03-11 12:31:37 +01:00
const mapTransactions = [
2019-04-03 03:08:10 +02:00
function set (user, gen) {
2020-01-22 16:42:16 +01:00
const key = prng.oneOf(gen, ['one', 'two'])
2020-12-19 16:29:17 +01:00
const value = prng.utf16String(gen)
2019-04-03 03:08:10 +02:00
user.getMap('map').set(key, value)
2017-08-09 02:21:17 +02:00
},
2019-04-03 03:08:10 +02:00
function setType (user, gen) {
2020-01-22 16:42:16 +01:00
const key = prng.oneOf(gen, ['one', 'two'])
2020-12-19 16:29:17 +01:00
const type = prng.oneOf(gen, [new Y.Array(), new Y.Map()])
2019-04-03 03:08:10 +02:00
user.getMap('map').set(key, type)
2017-10-26 19:50:43 +02:00
if (type instanceof Y.Array) {
2017-08-09 02:21:17 +02:00
type.insert(0, [1, 2, 3, 4])
} else {
type.set('deepkey', 'deepvalue')
}
},
2019-04-03 03:08:10 +02:00
function _delete (user, gen) {
2020-01-22 16:42:16 +01:00
const key = prng.oneOf(gen, ['one', 'two'])
2019-04-03 03:08:10 +02:00
user.getMap('map').delete(key)
2017-08-09 02:21:17 +02:00
}
]
/**
* @param {t.TestCase} tc
*/
2019-04-09 00:31:17 +02:00
export const testRepeatGeneratingYmapTests10 = tc => {
applyRandomTests(tc, mapTransactions, 3)
2019-03-11 12:31:37 +01:00
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests40 = tc => {
applyRandomTests(tc, mapTransactions, 40)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests42 = tc => {
applyRandomTests(tc, mapTransactions, 42)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests43 = tc => {
applyRandomTests(tc, mapTransactions, 43)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests44 = tc => {
applyRandomTests(tc, mapTransactions, 44)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests45 = tc => {
applyRandomTests(tc, mapTransactions, 45)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests46 = tc => {
applyRandomTests(tc, mapTransactions, 46)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests300 = tc => {
applyRandomTests(tc, mapTransactions, 300)
}
2017-08-09 02:21:17 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests400 = tc => {
applyRandomTests(tc, mapTransactions, 400)
}
2017-10-26 19:50:43 +02:00
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests500 = tc => {
applyRandomTests(tc, mapTransactions, 500)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests600 = tc => {
applyRandomTests(tc, mapTransactions, 600)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests1000 = tc => {
applyRandomTests(tc, mapTransactions, 1000)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests1800 = tc => {
applyRandomTests(tc, mapTransactions, 1800)
}
2019-04-09 00:48:24 +02:00
/**
* @param {t.TestCase} tc
*/
export const testRepeatGeneratingYmapTests5000 = tc => {
t.skip(!t.production)
applyRandomTests(tc, mapTransactions, 5000)
}
/**
* @param {t.TestCase} tc
*/
2019-03-11 12:31:37 +01:00
export const testRepeatGeneratingYmapTests10000 = tc => {
2019-04-09 00:48:24 +02:00
t.skip(!t.production)
2019-03-11 12:31:37 +01:00
applyRandomTests(tc, mapTransactions, 10000)
}
2019-04-09 00:31:17 +02:00
/**
* @param {t.TestCase} tc
*/
export const testRepeatGeneratingYmapTests100000 = tc => {
t.skip(!t.production)
applyRandomTests(tc, mapTransactions, 100000)
}