react-msaview 6.2.0 → 6.2.2

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.
@@ -0,0 +1,120 @@
1
+ // reset() returns the view to the import form, and the next file loads into
2
+ // the same model instance. It applies a default snapshot filtered to
3
+ // preservedOnReset, so anything file-derived that survived would be a hole in
4
+ // that list — the last test enumerates the snapshot keys to keep the list and
5
+ // the model's properties from drifting apart as properties are added. The
6
+ // stakes: node ids are path-derived (node-0-0-1), so a stale collapsed or
7
+ // showOnly id names a real node in the next tree and folds it.
8
+ import { getSnapshot } from '@jbrowse/mobx-state-tree'
9
+ import { describe, expect, test } from 'vitest'
10
+
11
+ import MSAModelF, { preservedOnReset } from './model.ts'
12
+
13
+ const firstFile = {
14
+ msa: '>a\nACGT\n>b\nACGT\n>c\nACGT\n>d\nACGT',
15
+ tree: '((a,b),(c,d));',
16
+ }
17
+ const secondFile = {
18
+ msa: '>e\nTTTT\n>f\nTTTT\n>g\nTTTT\n>h\nTTTT',
19
+ tree: '((e,f),(g,h));',
20
+ }
21
+
22
+ function makeModel() {
23
+ const model = MSAModelF().create({ type: 'MsaView', data: firstFile })
24
+ model.setWidth(800)
25
+ return model
26
+ }
27
+
28
+ function internalNodeId(model: ReturnType<typeof makeModel>) {
29
+ return model.leaves[0]!.parent!.data.id
30
+ }
31
+
32
+ describe('reset', () => {
33
+ test('a collapsed clade does not fold the next loaded tree', () => {
34
+ const model = makeModel()
35
+ model.toggleCollapsed(internalNodeId(model))
36
+ expect(model.leaves.length).toBe(3)
37
+
38
+ model.reset()
39
+ model.setData(secondFile)
40
+ expect(model.collapsed.length).toBe(0)
41
+ expect(model.leaves.map(l => l.data.name).toSorted()).toEqual([
42
+ 'e',
43
+ 'f',
44
+ 'g',
45
+ 'h',
46
+ ])
47
+ })
48
+
49
+ test('showOnly does not restrict the next loaded tree', () => {
50
+ const model = makeModel()
51
+ model.setShowOnly(internalNodeId(model))
52
+ expect(model.leaves.length).toBe(2)
53
+
54
+ model.reset()
55
+ model.setData(secondFile)
56
+ expect(model.showOnly).toBe(undefined)
57
+ expect(model.leaves.length).toBe(4)
58
+ })
59
+
60
+ test('clears file-derived volatiles', () => {
61
+ const model = makeModel()
62
+ model.setMousePos(2, 1)
63
+ model.setMouseClickPos(3, 0)
64
+ model.setHighlightedColumns([1, 2])
65
+ model.setHoveredTreeNode(internalNodeId(model))
66
+
67
+ model.reset()
68
+ expect(model.mouseCol).toBe(undefined)
69
+ expect(model.mouseClickCol).toBe(undefined)
70
+ expect(model.highlightedColumns).toBe(undefined)
71
+ expect(model.hoveredTreeNode).toBe(undefined)
72
+ expect(model.error).toBe(undefined)
73
+ expect(model.annotations).toEqual([])
74
+ })
75
+
76
+ test('display preferences survive', () => {
77
+ const model = makeModel()
78
+ model.setColorSchemeName('clustalx')
79
+ model.setDrawNodeBubbles(false)
80
+ model.toggleTrack('conservation')
81
+
82
+ model.reset()
83
+ expect(model.colorSchemeName).toBe('clustalx')
84
+ expect(model.drawNodeBubbles).toBe(false)
85
+ expect(model.turnedOffTracks.get('conservation')).toBe(true)
86
+ })
87
+
88
+ test('every property off preservedOnReset matches a fresh model', () => {
89
+ const model = makeModel()
90
+ model.toggleCollapsed(internalNodeId(model))
91
+ model.setShowOnly(internalNodeId(model))
92
+ model.drawRelativeTo('a')
93
+ model.setFilter('PF00001', true)
94
+ model.setScrollX(-100)
95
+ model.setScrollY(-50)
96
+ model.zoomIn()
97
+ model.setCurrentAlignment(1)
98
+ model.setMSAFilehandle({
99
+ uri: 'http://x/msa.fa',
100
+ locationType: 'UriLocation',
101
+ })
102
+ model.setTreeFilehandle({
103
+ uri: 'http://x/t.nh',
104
+ locationType: 'UriLocation',
105
+ })
106
+ model.setTreeMetadataFilehandle({
107
+ uri: 'http://x/m.json',
108
+ locationType: 'UriLocation',
109
+ })
110
+ model.setMSAFormat('fasta')
111
+
112
+ model.reset()
113
+ const fresh = MSAModelF().create({ type: 'MsaView' })
114
+ const strip = (snap: object) =>
115
+ Object.fromEntries(
116
+ Object.entries(snap).filter(([key]) => !preservedOnReset.has(key)),
117
+ )
118
+ expect(strip(getSnapshot(model))).toEqual(strip(getSnapshot(fresh)))
119
+ })
120
+ })
@@ -0,0 +1,61 @@
1
+ import { expect, test } from 'vitest'
2
+
3
+ import stateModelFactory from './model.ts'
4
+
5
+ const MsaView = stateModelFactory()
6
+
7
+ function loaded() {
8
+ const model = MsaView.create({
9
+ type: 'MsaView',
10
+ data: { msa: '>a\nAC\n>b\nAC\n>c\nAC\n>d\nAC', tree: '((a,b),(c,d));' },
11
+ })
12
+ model.setWidth(1000)
13
+ return model
14
+ }
15
+
16
+ test('reset returns to the import form', () => {
17
+ const model = loaded()
18
+ expect(model.dataInitialized).toBe(true)
19
+ model.reset()
20
+ expect(model.dataInitialized).toBe(false)
21
+ })
22
+
23
+ // generateNodeIds derives ids from the path, so 'node-0-0-1' is the root's
24
+ // first child in EVERY tree. Carrying collapsed/showOnly across a reset opens
25
+ // the next file collapsed, or focused on a subtree, with nothing on screen
26
+ // saying why
27
+ test('reset drops view state that names the old data', () => {
28
+ const model = loaded()
29
+ const innerNode = model.hierarchy.children![0]!.data.id
30
+ model.toggleCollapsed(innerNode)
31
+ model.setShowOnly(innerNode)
32
+ model.drawRelativeTo('a')
33
+ model.setHighlightedColumns([0, 1])
34
+ model.setMousePos(1, 1)
35
+ model.setMouseClickPos(1, 1)
36
+ model.setHoveredTreeNode(innerNode)
37
+
38
+ model.reset()
39
+
40
+ expect([...model.collapsed]).toEqual([])
41
+ expect(model.showOnly).toBeUndefined()
42
+ expect(model.relativeTo).toBeUndefined()
43
+ expect(model.highlightedColumns).toBeUndefined()
44
+ expect(model.mouseCol).toBeUndefined()
45
+ expect(model.mouseClickCol).toBeUndefined()
46
+ expect(model.hoveredTreeNode).toBeUndefined()
47
+ })
48
+
49
+ test('a file opened after a reset is not collapsed by the previous one', () => {
50
+ const model = loaded()
51
+ model.toggleCollapsed(model.hierarchy.children![0]!.data.id)
52
+ expect(model.numRows).toBeLessThan(4)
53
+
54
+ model.reset()
55
+ model.setData({
56
+ msa: '>x\nGT\n>y\nGT\n>z\nGT\n>w\nGT',
57
+ tree: '((x,y),(z,w));',
58
+ })
59
+ expect(model.numRows).toBe(4)
60
+ expect(model.rowNames).toEqual(['x', 'y', 'z', 'w'])
61
+ })
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '6.2.0'
1
+ export const version = '6.2.2'