@jbrowse/plugin-sequence 2.3.1 → 2.3.3

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.
Files changed (28) hide show
  1. package/dist/DivSequenceRenderer/components/DivSequenceRendering.d.ts +8 -10
  2. package/dist/DivSequenceRenderer/components/DivSequenceRendering.js +1 -1
  3. package/dist/DivSequenceRenderer/components/DivSequenceRendering.js.map +1 -1
  4. package/dist/LinearReferenceSequenceDisplay/model.d.ts +42 -7
  5. package/dist/LinearReferenceSequenceDisplay/model.js +65 -23
  6. package/dist/LinearReferenceSequenceDisplay/model.js.map +1 -1
  7. package/dist/SequenceSearchAdapter/SequenceSearchAdapter.js +2 -1
  8. package/dist/SequenceSearchAdapter/SequenceSearchAdapter.js.map +1 -1
  9. package/esm/DivSequenceRenderer/components/DivSequenceRendering.d.ts +8 -10
  10. package/esm/DivSequenceRenderer/components/DivSequenceRendering.js +1 -1
  11. package/esm/DivSequenceRenderer/components/DivSequenceRendering.js.map +1 -1
  12. package/esm/LinearReferenceSequenceDisplay/model.d.ts +42 -7
  13. package/esm/LinearReferenceSequenceDisplay/model.js +66 -24
  14. package/esm/LinearReferenceSequenceDisplay/model.js.map +1 -1
  15. package/esm/SequenceSearchAdapter/SequenceSearchAdapter.js +2 -1
  16. package/esm/SequenceSearchAdapter/SequenceSearchAdapter.js.map +1 -1
  17. package/package.json +3 -3
  18. package/src/DivSequenceRenderer/components/DivSequenceRendering.test.tsx +161 -0
  19. package/src/DivSequenceRenderer/components/DivSequenceRendering.tsx +16 -19
  20. package/src/DivSequenceRenderer/components/__snapshots__/DivSequenceRendering.test.tsx.snap +1426 -0
  21. package/src/IndexedFastaAdapter/IndexedFastaAdapter.test.ts +4 -3
  22. package/src/LinearReferenceSequenceDisplay/model.ts +69 -25
  23. package/src/SequenceSearchAdapter/SequenceSearchAdapter.ts +2 -1
  24. package/src/TwoBitAdapter/TwoBitAdapter.test.ts +4 -3
  25. package/src/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
  26. package/src/{index.test.js → index.test.ts} +5 -10
  27. package/src/DivSequenceRenderer/components/DivSequenceRendering.test.js +0 -211
  28. package/src/DivSequenceRenderer/components/__snapshots__/DivSequenceRendering.test.js.snap +0 -67
@@ -1,4 +1,5 @@
1
1
  import { toArray } from 'rxjs/operators'
2
+ import { firstValueFrom } from 'rxjs'
2
3
  import Adapter from './IndexedFastaAdapter'
3
4
  import configSchema from './configSchema'
4
5
 
@@ -26,7 +27,7 @@ test('adapter can fetch sequence from volvox.fa', async () => {
26
27
  end: 20000,
27
28
  })
28
29
 
29
- const featuresArray = await features.pipe(toArray()).toPromise()
30
+ const featuresArray = await firstValueFrom(features.pipe(toArray()))
30
31
  expect(featuresArray).toMatchSnapshot()
31
32
 
32
33
  const features2 = adapter.getFeatures({
@@ -35,7 +36,7 @@ test('adapter can fetch sequence from volvox.fa', async () => {
35
36
  end: 55000,
36
37
  })
37
38
 
38
- const featuresArray2 = await features2.pipe(toArray()).toPromise()
39
+ const featuresArray2 = await firstValueFrom(features2.pipe(toArray()))
39
40
  expect(featuresArray2[0].get('end')).toBe(50001)
40
41
 
41
42
  const features3 = adapter.getFeatures({
@@ -47,6 +48,6 @@ test('adapter can fetch sequence from volvox.fa', async () => {
47
48
  const data = await adapter.getHeader()
48
49
  expect(data?.trim()).toBe('hello world')
49
50
 
50
- const featuresArray3 = await features3.pipe(toArray()).toPromise()
51
+ const featuresArray3 = await firstValueFrom(features3.pipe(toArray()))
51
52
  expect(featuresArray3).toMatchSnapshot()
52
53
  })
@@ -1,4 +1,4 @@
1
- import { types } from 'mobx-state-tree'
1
+ import { addDisposer, types } from 'mobx-state-tree'
2
2
  import {
3
3
  BaseLinearDisplay,
4
4
  LinearGenomeViewModel,
@@ -8,24 +8,46 @@ import {
8
8
  ConfigurationReference,
9
9
  } from '@jbrowse/core/configuration'
10
10
  import { getContainingView } from '@jbrowse/core/util'
11
+ import { autorun } from 'mobx'
11
12
 
13
+ /**
14
+ * #stateModel LinearReferenceSequenceDisplay
15
+ * base model `BaseLinearDisplay`
16
+ */
12
17
  export function modelFactory(configSchema: AnyConfigurationSchemaType) {
13
18
  return types
14
19
  .compose(
15
20
  'LinearReferenceSequenceDisplay',
16
21
  BaseLinearDisplay,
17
22
  types.model({
23
+ /**
24
+ * #property
25
+ */
18
26
  type: types.literal('LinearReferenceSequenceDisplay'),
27
+ /**
28
+ * #property
29
+ */
19
30
  configuration: ConfigurationReference(configSchema),
20
- showForward: types.optional(types.boolean, true),
21
- showReverse: types.optional(types.boolean, true),
22
- showTranslation: types.optional(types.boolean, true),
23
- height: 180,
31
+ /**
32
+ * #property
33
+ */
34
+ showForward: true,
35
+ /**
36
+ * #property
37
+ */
38
+ showReverse: true,
39
+ /**
40
+ * #property
41
+ */
42
+ showTranslation: true,
24
43
  }),
25
44
  )
26
45
  .views(self => {
27
46
  const { renderProps: superRenderProps } = self
28
47
  return {
48
+ /**
49
+ * #method
50
+ */
29
51
  renderProps() {
30
52
  const { showForward, showReverse, showTranslation } = self
31
53
  return {
@@ -37,56 +59,78 @@ export function modelFactory(configSchema: AnyConfigurationSchemaType) {
37
59
  showTranslation,
38
60
  }
39
61
  },
40
- regionCannotBeRendered(/* region */) {
41
- const view = getContainingView(self) as LinearGenomeViewModel
42
- if (view && view.bpPerPx >= 1) {
43
- return 'Zoom in to see sequence'
44
- }
45
- return undefined
46
- },
47
-
48
- get rendererTypeName() {
49
- return self.configuration.renderer.type
50
- },
51
62
  }
52
63
  })
64
+ .views(self => ({
65
+ /**
66
+ * #method
67
+ */
68
+ regionCannotBeRendered(/* region */) {
69
+ const view = getContainingView(self) as LinearGenomeViewModel
70
+ return view?.bpPerPx >= 1 ? 'Zoom in to see sequence' : undefined
71
+ },
72
+ /**
73
+ * #getter
74
+ */
75
+ get rendererTypeName() {
76
+ return self.configuration.renderer.type
77
+ },
78
+ }))
53
79
  .actions(self => ({
80
+ /**
81
+ * #action
82
+ */
54
83
  toggleShowForward() {
55
84
  self.showForward = !self.showForward
56
85
  },
86
+ /**
87
+ * #action
88
+ */
57
89
  toggleShowReverse() {
58
90
  self.showReverse = !self.showReverse
59
91
  },
92
+ /**
93
+ * #action
94
+ */
60
95
  toggleShowTranslation() {
61
96
  self.showTranslation = !self.showTranslation
62
97
  },
98
+ afterAttach() {
99
+ // auto-adjust height depending on settings
100
+ addDisposer(
101
+ self,
102
+ autorun(() => {
103
+ const t = self.showTranslation ? 100 : 0
104
+ const r = self.showReverse ? 20 : 0
105
+ const s = self.showForward ? 20 : 0
106
+ self.setHeight(t + r + s)
107
+ }),
108
+ )
109
+ },
63
110
  }))
64
111
  .views(self => ({
112
+ /**
113
+ * #method
114
+ */
65
115
  trackMenuItems() {
66
116
  return [
67
117
  {
68
118
  label: 'Show forward',
69
119
  type: 'checkbox',
70
120
  checked: self.showForward,
71
- onClick: () => {
72
- self.toggleShowForward()
73
- },
121
+ onClick: () => self.toggleShowForward(),
74
122
  },
75
123
  {
76
124
  label: 'Show reverse',
77
125
  type: 'checkbox',
78
126
  checked: self.showReverse,
79
- onClick: () => {
80
- self.toggleShowReverse()
81
- },
127
+ onClick: () => self.toggleShowReverse(),
82
128
  },
83
129
  {
84
130
  label: 'Show translation',
85
131
  type: 'checkbox',
86
132
  checked: self.showTranslation,
87
- onClick: () => {
88
- self.toggleShowTranslation()
89
- },
133
+ onClick: () => self.toggleShowTranslation(),
90
134
  },
91
135
  ]
92
136
  },
@@ -11,6 +11,7 @@ import {
11
11
  doesIntersect2,
12
12
  } from '@jbrowse/core/util'
13
13
  import { toArray } from 'rxjs/operators'
14
+ import { firstValueFrom } from 'rxjs'
14
15
 
15
16
  export default class extends BaseFeatureDataAdapter {
16
17
  public async configure() {
@@ -47,7 +48,7 @@ export default class extends BaseFeatureDataAdapter {
47
48
  },
48
49
  opts,
49
50
  )
50
- const feats = await ret.pipe(toArray()).toPromise()
51
+ const feats = await firstValueFrom(ret.pipe(toArray()))
51
52
  const residues: string = feats[0]?.get('seq') || ''
52
53
  const search = this.getConf('search')
53
54
  const searchForward = this.getConf('searchForward')
@@ -1,4 +1,5 @@
1
1
  import { toArray } from 'rxjs/operators'
2
+ import { firstValueFrom } from 'rxjs'
2
3
  import Adapter from './TwoBitAdapter'
3
4
  import configSchema from './configSchema'
4
5
 
@@ -18,7 +19,7 @@ test('adapter can fetch features from volvox.2bit', async () => {
18
19
  end: 20000,
19
20
  })
20
21
 
21
- const featuresArray = await features.pipe(toArray()).toPromise()
22
+ const featuresArray = await firstValueFrom(features.pipe(toArray()))
22
23
  expect(featuresArray).toMatchSnapshot()
23
24
 
24
25
  const features2 = adapter.getFeatures({
@@ -27,7 +28,7 @@ test('adapter can fetch features from volvox.2bit', async () => {
27
28
  end: 55000,
28
29
  })
29
30
 
30
- const featuresArray2 = await features2.pipe(toArray()).toPromise()
31
+ const featuresArray2 = await firstValueFrom(features2.pipe(toArray()))
31
32
  expect(featuresArray2[0].get('end')).toBe(50001)
32
33
 
33
34
  const features3 = adapter.getFeatures({
@@ -36,7 +37,7 @@ test('adapter can fetch features from volvox.2bit', async () => {
36
37
  end: 20000,
37
38
  })
38
39
 
39
- const featuresArray3 = await features3.pipe(toArray()).toPromise()
40
+ const featuresArray3 = await firstValueFrom(features3.pipe(toArray()))
40
41
  expect(featuresArray3).toMatchSnapshot()
41
42
  })
42
43
 
@@ -3,7 +3,6 @@ import { getSnapshot } from 'mobx-state-tree'
3
3
  import ThisPlugin from '.'
4
4
 
5
5
  test('plugin in a stock JBrowse', () => {
6
- console.warn = jest.fn()
7
6
  const pluginManager = new PluginManager([new ThisPlugin()])
8
7
  pluginManager.createPluggableElements()
9
8
  pluginManager.configure()
@@ -12,14 +11,10 @@ test('plugin in a stock JBrowse', () => {
12
11
  )
13
12
 
14
13
  const TwoBitAdapter = pluginManager.getAdapterType('TwoBitAdapter')
15
- const config = TwoBitAdapter.configSchema.create({ type: 'TwoBitAdapter' })
16
- expect(getSnapshot(config)).toMatchSnapshot()
14
+ const cfg = TwoBitAdapter.configSchema.create({ type: 'TwoBitAdapter' })
15
+ expect(getSnapshot(cfg)).toMatchSnapshot()
17
16
 
18
- const IndexedFastaAdapter = pluginManager.getAdapterType(
19
- 'IndexedFastaAdapter',
20
- )
21
- const config2 = IndexedFastaAdapter.configSchema.create({
22
- type: 'IndexedFastaAdapter',
23
- })
24
- expect(getSnapshot(config2)).toMatchSnapshot()
17
+ const FastaAdapter = pluginManager.getAdapterType('IndexedFastaAdapter')
18
+ const cfg2 = FastaAdapter.configSchema.create({ type: 'IndexedFastaAdapter' })
19
+ expect(getSnapshot(cfg2)).toMatchSnapshot()
25
20
  })
@@ -1,211 +0,0 @@
1
- import React from 'react'
2
- import { render } from '@testing-library/react'
3
- import { createJBrowseTheme } from '@jbrowse/core/ui'
4
- import PrecomputedLayout from '@jbrowse/core/util/layouts/PrecomputedLayout'
5
- import SimpleFeature from '@jbrowse/core/util/simpleFeature'
6
- import { ThemeProvider } from '@mui/material'
7
- import DivSequenceRendering from './DivSequenceRendering'
8
- import DivRenderingConfigSchema from '../configSchema'
9
-
10
- function Rendering(props) {
11
- return (
12
- <ThemeProvider theme={createJBrowseTheme()}>
13
- <DivSequenceRendering {...props} />
14
- </ThemeProvider>
15
- )
16
- }
17
-
18
- class ErrorCatcher extends React.Component {
19
- constructor(props) {
20
- super(props)
21
- this.state = { hasError: false, errorText: '' }
22
- }
23
-
24
- static getDerivedStateFromError(error) {
25
- // Update state so the next render will show the fallback UI.
26
- return { hasError: true, errorText: String(error) }
27
- }
28
-
29
- render() {
30
- const { hasError, errorText } = this.state
31
- if (hasError) {
32
- // You can render any custom fallback UI
33
- return <h1 className="error">{errorText}</h1>
34
- }
35
- const { children } = this.props
36
- return children
37
- }
38
- }
39
-
40
- describe('<DivSequenceRendering />', () => {
41
- // This just keeps our testing logs clean by not displaying `console.error`s
42
- // from errors we intentionally throw in our tests. Hopefully React will
43
- // someday provide a way for error boundaries to prevent error logging so we
44
- // won't have to do this: https://github.com/facebook/react/issues/15069
45
- const originalError = console.error
46
- beforeAll(() => {
47
- console.error = (...args) => {
48
- if (
49
- args[0].includes(
50
- 'feature one did not contain a valid `seq` attribute',
51
- ) ||
52
- args[0].includes(
53
- 'The above error occurred in the <SequenceDivs> component',
54
- )
55
- ) {
56
- return
57
- }
58
- originalError.call(console, ...args)
59
- }
60
- })
61
-
62
- afterAll(() => {
63
- console.error = originalError
64
- })
65
-
66
- it('renders with no features', () => {
67
- const { container } = render(
68
- <Rendering
69
- width={500}
70
- height={500}
71
- regions={[{ refName: 'zonk', start: 0, end: 300 }]}
72
- layout={new PrecomputedLayout({ rectangles: {}, totalHeight: 20 })}
73
- config={DivRenderingConfigSchema.create()}
74
- bpPerPx={3}
75
- />,
76
- )
77
-
78
- expect(container).toMatchSnapshot()
79
- })
80
-
81
- it('renders with one, zoomed way out', () => {
82
- const { container } = render(
83
- <Rendering
84
- width={500}
85
- height={500}
86
- regions={[{ refName: 'zonk', start: 0, end: 1000 }]}
87
- features={
88
- new Map([
89
- [
90
- 'one',
91
- new SimpleFeature({
92
- uniqueId: 'one',
93
- start: 1,
94
- end: 3,
95
- seq: 'AB',
96
- }),
97
- ],
98
- ])
99
- }
100
- config={DivRenderingConfigSchema.create({})}
101
- bpPerPx={3}
102
- />,
103
- )
104
-
105
- expect(container).toMatchSnapshot()
106
- })
107
-
108
- it('renders with one feature with no seq, zoomed in, should throw', () => {
109
- const { container } = render(
110
- <ErrorCatcher>
111
- <Rendering
112
- width={500}
113
- height={500}
114
- regions={[{ refName: 'zonk', start: 0, end: 1000 }]}
115
- features={
116
- new Map([
117
- ['one', new SimpleFeature({ uniqueId: 'one', start: 1, end: 3 })],
118
- ])
119
- }
120
- config={DivRenderingConfigSchema.create({})}
121
- bpPerPx={0.05}
122
- />
123
- </ErrorCatcher>,
124
- )
125
-
126
- expect(container).toMatchSnapshot()
127
- })
128
-
129
- it('renders with one feature with an incorrect seq, zoomed in, should throw', () => {
130
- const { container } = render(
131
- <ErrorCatcher>
132
- <Rendering
133
- width={500}
134
- height={500}
135
- regions={[{ refName: 'zonk', start: 0, end: 1000 }]}
136
- features={
137
- new Map([
138
- [
139
- 'one',
140
- new SimpleFeature({
141
- uniqueId: 'one',
142
- start: 1,
143
- end: 3,
144
- seq: 'ABC',
145
- }),
146
- ],
147
- ])
148
- }
149
- config={DivRenderingConfigSchema.create({})}
150
- bpPerPx={0.05}
151
- />
152
- </ErrorCatcher>,
153
- )
154
-
155
- expect(container).toMatchSnapshot()
156
- })
157
-
158
- it('renders with one feature with a correct seq, zoomed in, should render nicely', () => {
159
- const { container } = render(
160
- <Rendering
161
- width={500}
162
- height={500}
163
- regions={[{ refName: 'zonk', start: 0, end: 1000 }]}
164
- features={
165
- new Map([
166
- [
167
- 'one',
168
- new SimpleFeature({
169
- uniqueId: 'one',
170
- start: 1,
171
- end: 10,
172
- seq: 'ABCDEFGHI',
173
- }),
174
- ],
175
- ])
176
- }
177
- config={DivRenderingConfigSchema.create({})}
178
- bpPerPx={0.05}
179
- />,
180
- )
181
-
182
- expect(container).toMatchSnapshot()
183
- })
184
-
185
- it('renders with one feature reversed with a correct seq, zoomed in, should render nicely', () => {
186
- const { container } = render(
187
- <Rendering
188
- width={500}
189
- height={500}
190
- regions={[{ refName: 'zonk', start: 0, end: 1000, reversed: true }]}
191
- features={
192
- new Map([
193
- [
194
- 'one',
195
- new SimpleFeature({
196
- uniqueId: 'one',
197
- start: 1,
198
- end: 10,
199
- seq: 'ABCDEFGHI',
200
- }),
201
- ],
202
- ])
203
- }
204
- config={DivRenderingConfigSchema.create({})}
205
- bpPerPx={0.05}
206
- />,
207
- )
208
-
209
- expect(container).toMatchSnapshot()
210
- })
211
- })
@@ -1,67 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`<DivSequenceRendering /> renders with no features 1`] = `
4
- <div>
5
- <svg
6
- data-testid="sequence_track"
7
- height="200"
8
- style="width: 100px; height: 200px;"
9
- width="100"
10
- />
11
- </div>
12
- `;
13
-
14
- exports[`<DivSequenceRendering /> renders with one feature reversed with a correct seq, zoomed in, should render nicely 1`] = `
15
- <div>
16
- <svg
17
- data-testid="sequence_track"
18
- height="200"
19
- style="width: 20000px; height: 200px;"
20
- width="20000"
21
- />
22
- </div>
23
- `;
24
-
25
- exports[`<DivSequenceRendering /> renders with one feature with a correct seq, zoomed in, should render nicely 1`] = `
26
- <div>
27
- <svg
28
- data-testid="sequence_track"
29
- height="200"
30
- style="width: 20000px; height: 200px;"
31
- width="20000"
32
- />
33
- </div>
34
- `;
35
-
36
- exports[`<DivSequenceRendering /> renders with one feature with an incorrect seq, zoomed in, should throw 1`] = `
37
- <div>
38
- <svg
39
- data-testid="sequence_track"
40
- height="200"
41
- style="width: 20000px; height: 200px;"
42
- width="20000"
43
- />
44
- </div>
45
- `;
46
-
47
- exports[`<DivSequenceRendering /> renders with one feature with no seq, zoomed in, should throw 1`] = `
48
- <div>
49
- <svg
50
- data-testid="sequence_track"
51
- height="200"
52
- style="width: 20000px; height: 200px;"
53
- width="20000"
54
- />
55
- </div>
56
- `;
57
-
58
- exports[`<DivSequenceRendering /> renders with one, zoomed way out 1`] = `
59
- <div>
60
- <svg
61
- data-testid="sequence_track"
62
- height="200"
63
- style="width: 333.3333333333333px; height: 200px;"
64
- width="333.3333333333333"
65
- />
66
- </div>
67
- `;