import {Atom} from '@theatre/dataverse' describe(`Atom`, () => { test(`Usage of Atom and pointer, without prism`, async () => { const data = {foo: 'foo', bar: 0} const atom = new Atom(data) // atom.get() returns an exact reference to the data expect(atom.get()).toBe(data) atom.set({foo: 'foo', bar: 1}) expect(atom.get()).not.toBe(data) expect(atom.get()).toEqual({foo: 'foo', bar: 1}) atom.reduce(({foo, bar}) => ({foo, bar: bar + 1})) expect(atom.get()).toEqual({foo: 'foo', bar: 2}) atom.setByPointer((p) => p.bar, 3) expect(atom.get()).toEqual({foo: 'foo', bar: 3}) atom.setByPointer((p) => p.foo, 'foo2') expect(atom.get()).toEqual({foo: 'foo2', bar: 3}) // this would work in runtime, but typescript will complain because `baz` is not a property of the state // let's silence the error for the sake of the test // @ts-ignore atom.setByPointer((p) => p.baz, 'baz') expect(atom.get()).toEqual({foo: 'foo2', bar: 3, baz: 'baz'}) atom.setByPointer((p) => p, {foo: 'newfoo', bar: -1}) expect(atom.get()).toEqual({foo: 'newfoo', bar: -1}) // `reduceByPointer()` is to `setByPointer()` what `reduce()` is to `set()` atom.reduceByPointer( (p) => p.bar, (bar) => bar + 1, ) expect(atom.get()).toEqual({foo: 'newfoo', bar: 0}) // we can use external pointers too const externalPointer = atom.pointer.bar atom.setByPointer(() => externalPointer, 1) expect(atom.get()).toEqual({foo: 'newfoo', bar: 1}) let internalPointer // the pointer passed to `setByPointer()` is the same as the one returned by `atom.pointer` atom.setByPointer((p) => { internalPointer = p return p.bar }, 2) expect(internalPointer).toBe(atom.pointer) expect(atom.pointer).toBe(atom.pointer) expect(atom.pointer.bar).toBe(atom.pointer.bar) // pointers don't change when the atom's state changes const oldPointer = atom.pointer.bar atom.set({foo: 'foo', bar: 10}) expect(atom.pointer.bar).toBe(oldPointer) }) })