Skip to content

Commit

Permalink
feat(primitives): add new set methods and tests for reatomSet (#866)
Browse files Browse the repository at this point in the history
* feat(primitives): add new set methods and tests for reatomSet

* feat(primitives): rename set method from swtich to toggle

* feat(primitives): delete useless new Set

* feat(primitives): add types for set proposal, fix test for reatomSet.isDisjointFrom

* feat(primitives): add core js for set tests

* chore: fix ProposalSet

---------

Co-authored-by: Arutiunian Artem <[email protected]>
  • Loading branch information
debabin and artalar authored Jun 9, 2024
1 parent 026b458 commit a8ae20f
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 0 deletions.
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/react-dom": "^18.2.22",
"@types/use-sync-external-store": "^0.0.6",
"@vitejs/plugin-react": "^4.2.1",
"core-js": "^3.37.1",
"history": "^5.3.0",
"husky": "^8.0.3 ",
"linkedom": "^0.16.10",
Expand Down
1 change: 1 addition & 0 deletions packages/primitives/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import './reatomArray.test'
import './reatomEnum.test'
import './reatomLinkedList.test'
import './reatomRecord.test'
import './reatomSet.test'
import './reatomString.test'
import './withComputed.test'
126 changes: 126 additions & 0 deletions packages/primitives/src/reatomSet.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import 'core-js/proposals/set-methods-v2'

import { createCtx } from '@reatom/core'
import { suite } from 'uvu'
import * as assert from 'uvu/assert'

import { reatomSet } from './reatomSet'

const test = suite('reatomSet')

test(`reatomSet. init`, () => {
const ctx = createCtx()

assert.equal(ctx.get(reatomSet(new Set([1, 2, 3]))), new Set([1, 2, 3]))
})

test(`reatomSet. add`, () => {
const ctx = createCtx()

assert.equal(reatomSet(new Set([1, 2, 3])).add(ctx, 4), new Set([1, 2, 3, 4]))
})

test(`reatomSet. delete`, () => {
const ctx = createCtx()

assert.equal(reatomSet(new Set([1, 2, 3])).delete(ctx, 3), new Set([1, 2]))
})

test(`reatomSet. toggle`, () => {
const ctx = createCtx()
const a = reatomSet(new Set([1, 2, 3]))

assert.equal(a.toggle(ctx, 3), new Set([1, 2]))
assert.equal(a.toggle(ctx, 3), new Set([1, 2, 3]))
})

test(`reatomSet. clear`, () => {
const ctx = createCtx()

assert.equal(reatomSet(new Set([1, 2, 3])).clear(ctx), new Set())
})

test(`reatomSet. reset`, () => {
const ctx = createCtx()
const a = reatomSet(new Set([1, 2, 3]))

assert.equal(a.add(ctx, 4), new Set([1, 2, 3, 4]))
assert.equal(a.reset(ctx), new Set([1, 2, 3]))
})

test(`reatomSet. intersection`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).intersection(ctx, new Set([2, 3, 4])),
new Set([2, 3]),
)
})

test(`reatomSet. union`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).union(ctx, new Set([2, 3, 4])),
new Set([1, 2, 3, 4]),
)
})

test(`reatomSet. difference`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).difference(ctx, new Set([2, 3, 4])),
new Set([1]),
)
})

test(`reatomSet. symmetricDifference`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).symmetricDifference(ctx, new Set([2, 3, 4])),
new Set([1, 4]),
)
})

test(`reatomSet. isSubsetOf`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).isSubsetOf(ctx, new Set([2, 3, 4])),
false,
)
assert.equal(
reatomSet(new Set([1, 2, 3])).isSubsetOf(ctx, new Set([1, 2, 3])),
true,
)
})

test(`reatomSet. isSupersetOf`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).isSupersetOf(ctx, new Set([2, 3, 4])),
false,
)
assert.equal(
reatomSet(new Set([1, 2, 3])).isSupersetOf(ctx, new Set([1, 2, 3])),
true,
)
})

test(`reatomSet. isDisjointFrom`, () => {
const ctx = createCtx()

assert.equal(
reatomSet(new Set([1, 2, 3])).isDisjointFrom(ctx, new Set([4, 5, 6])),
true,
)
assert.equal(
reatomSet(new Set([1, 2, 3])).isDisjointFrom(ctx, new Set([3, 4, 5])),
false,
)
})

test.run()
54 changes: 54 additions & 0 deletions packages/primitives/src/reatomSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,31 @@ import { withAssign } from './withAssign'
export interface SetAtom<T> extends AtomMut<Set<T>> {
add: Action<[el: T], Set<T>>
delete: Action<[el: T], Set<T>>
toggle: Action<[el: T], Set<T>>
clear: Action<[], Set<T>>
reset: Action<[], Set<T>>
intersection: Action<[set: Set<T>], Set<T>>
union: Action<[set: Set<T>], Set<T>>
difference: Action<[set: Set<T>], Set<T>>
symmetricDifference: Action<[set: Set<T>], Set<T>>
has: (ctx: Ctx, el: T) => boolean
isSubsetOf: (ctx: Ctx, set: Set<T>) => boolean
isSupersetOf: (ctx: Ctx, set: Set<T>) => boolean
isDisjointFrom: (ctx: Ctx, set: Set<T>) => boolean
/** @deprecated */
set: Action<[el: T], Set<T>>
}

interface ProposalSet<T> extends Set<T> {
difference(other: Set<T>): Set<T>
intersection(other: Set<T>): Set<T>
isDisjointFrom(other: Set<T>): boolean
isSubsetOf(other: Set<T>): boolean
isSupersetOf(other: Set<T>): boolean
symmetricDifference(other: Set<T>): Set<T>
union(other: Set<T>): Set<T>
}

export const reatomSet = <T>(
initState = new Set<T>(),
name?: string,
Expand Down Expand Up @@ -43,6 +61,42 @@ export const reatomSet = <T>(
})
}, `${name}.clear`),
reset: action((ctx) => target(ctx, initState), `${name}.reset`),
intersection: action(
(ctx, set) =>
target(ctx, (prev) => (prev as ProposalSet<T>).intersection(set)),
`${name}.intersection`,
),
union: action(
(ctx, set) =>
target(ctx, (prev) => (prev as ProposalSet<T>).union(set)),
`${name}.union`,
),
difference: action(
(ctx, set) =>
target(ctx, (prev) => (prev as ProposalSet<T>).difference(set)),
`${name}.difference`,
),
symmetricDifference: action(
(ctx, set) =>
target(ctx, (prev) =>
(prev as ProposalSet<T>).symmetricDifference(set),
),
`${name}.symmetricDifference`,
),
toggle: action((ctx, el) => {
return target(ctx, (prev) => {
if (!prev.has(el)) return new Set(prev).add(el)
const next = new Set(prev)
next.delete(el)
return next
})
}, `${name}.toggle`),
has: (ctx: Ctx, el: T) => ctx.get(target).has(el),
isSubsetOf: (ctx: Ctx, set: Set<T>) =>
(ctx.get(target) as ProposalSet<T>).isSubsetOf(set),
isSupersetOf: (ctx: Ctx, set: Set<T>) =>
(ctx.get(target) as ProposalSet<T>).isSupersetOf(set),
isDisjointFrom: (ctx: Ctx, set: Set<T>) =>
(ctx.get(target) as ProposalSet<T>).isDisjointFrom(set),
})),
)

0 comments on commit a8ae20f

Please sign in to comment.