@morscherlab/mint-sdk 1.1.14 → 1.1.16
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.
- package/dist/{SettingsModal-Brvcqz4a.js → SettingsModal-DoS2fzyz.js} +3 -3
- package/dist/{SettingsModal-Brvcqz4a.js.map → SettingsModal-DoS2fzyz.js.map} +1 -1
- package/dist/components/index.js +3 -3
- package/dist/{components-DIciVip2.js → components-CW3hE1T3.js} +7 -7
- package/dist/{components-DIciVip2.js.map → components-CW3hE1T3.js.map} +1 -1
- package/dist/composables/index.js +5 -5
- package/dist/{composables-CPv3k1Yh.js → composables-CkXDe7nm.js} +3 -3
- package/dist/{composables-CPv3k1Yh.js.map → composables-CkXDe7nm.js.map} +1 -1
- package/dist/index.js +7 -7
- package/dist/install.js +3 -3
- package/dist/styles.css +20 -4
- package/dist/templates/index.js +2 -2
- package/dist/{templates-Dyyjr6wD.js → templates-CovvRZ-9.js} +2 -2
- package/dist/{templates-Dyyjr6wD.js.map → templates-CovvRZ-9.js.map} +1 -1
- package/dist/{useControlSchema-B6-PO0F6.js → useControlSchema-BhoJzWzx.js} +6 -2
- package/dist/useControlSchema-BhoJzWzx.js.map +1 -0
- package/dist/{useFormBuilder-Pgb9Td6h.js → useFormBuilder-DiEcDis2.js} +2 -2
- package/dist/{useFormBuilder-Pgb9Td6h.js.map → useFormBuilder-DiEcDis2.js.map} +1 -1
- package/dist/{useProtocolTemplates-CYCnwGtY.js → useProtocolTemplates-DHwSveE6.js} +3 -3
- package/dist/{useProtocolTemplates-CYCnwGtY.js.map → useProtocolTemplates-DHwSveE6.js.map} +1 -1
- package/package.json +1 -1
- package/src/__tests__/components/SampleSelector.test.ts +32 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +58 -0
- package/src/composables/useGeneratedAnalysis.ts +5 -1
- package/src/styles/components/smart-group.css +5 -1
- package/dist/useControlSchema-B6-PO0F6.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morscherlab/mint-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.16",
|
|
4
4
|
"description": "MINT Platform SDK — Vue 3 components, composables, and types for plugin development. MINT = Mass-spec INtegrated Toolkit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
1
3
|
import { flushPromises, mount } from '@vue/test-utils'
|
|
2
4
|
import { createPinia } from 'pinia'
|
|
3
5
|
import { describe, expect, it, vi } from 'vitest'
|
|
@@ -279,6 +281,36 @@ describe('AutoGroupModal multi-schema auto workflow', () => {
|
|
|
279
281
|
|
|
280
282
|
expect(wrapper.find('.sg-foot .mint-button--primary').attributes('disabled')).toBeUndefined()
|
|
281
283
|
})
|
|
284
|
+
|
|
285
|
+
it('should scroll the token field list when many fields exceed the modal height', () => {
|
|
286
|
+
const styles = readFileSync(
|
|
287
|
+
resolve(process.cwd(), 'src/styles/components/smart-group.css'),
|
|
288
|
+
'utf8',
|
|
289
|
+
)
|
|
290
|
+
const mainPanelStyles = styles.match(/\.sg-body__main\s*\{([^}]*)\}/)?.[1]
|
|
291
|
+
|
|
292
|
+
expect(mainPanelStyles).toContain('overflow-y: auto')
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('should let the token field panel shrink within the fixed modal body', () => {
|
|
296
|
+
const styles = readFileSync(
|
|
297
|
+
resolve(process.cwd(), 'src/styles/components/smart-group.css'),
|
|
298
|
+
'utf8',
|
|
299
|
+
)
|
|
300
|
+
const mainPanelStyles = styles.match(/\.sg-body__main\s*\{([^}]*)\}/)?.[1]
|
|
301
|
+
|
|
302
|
+
expect(mainPanelStyles).toContain('min-height: 0')
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('should scroll the group preview when generated groups exceed the modal height', () => {
|
|
306
|
+
const styles = readFileSync(
|
|
307
|
+
resolve(process.cwd(), 'src/styles/components/smart-group.css'),
|
|
308
|
+
'utf8',
|
|
309
|
+
)
|
|
310
|
+
const sidePanelStyles = styles.match(/\.sg-body__side\s*\{([^}]*)\}/)?.[1]
|
|
311
|
+
|
|
312
|
+
expect(sidePanelStyles).toMatch(/min-height:\s*0;[\s\S]*overflow-y:\s*auto;/)
|
|
313
|
+
})
|
|
282
314
|
})
|
|
283
315
|
|
|
284
316
|
describe('SampleSelector — QC overlay regression', () => {
|
|
@@ -1489,6 +1489,64 @@ describe('useGeneratedAnalysis', () => {
|
|
|
1489
1489
|
}
|
|
1490
1490
|
})
|
|
1491
1491
|
|
|
1492
|
+
it('should keep polling when a stale list response overlaps an active job lookup', async () => {
|
|
1493
|
+
vi.useFakeTimers()
|
|
1494
|
+
const queued = activeJob('live-job')
|
|
1495
|
+
const running = activeJob('live-job', 'running')
|
|
1496
|
+
const completed = completedJob('live-job')
|
|
1497
|
+
const jobRequest = deferred<Response>()
|
|
1498
|
+
const staleRefresh = deferred<Response>()
|
|
1499
|
+
const transport = vi.fn<GeneratedAnalysisTransport>()
|
|
1500
|
+
.mockResolvedValueOnce(response(manifest))
|
|
1501
|
+
.mockResolvedValueOnce(response({ sessions: [] }))
|
|
1502
|
+
.mockResolvedValueOnce(response({
|
|
1503
|
+
id: 'session-1', tab_id: 'tab-1', created_at: '', last_seen_at: '', active_job_ids: [],
|
|
1504
|
+
}))
|
|
1505
|
+
.mockResolvedValueOnce(response({ jobs: [queued] }))
|
|
1506
|
+
.mockReturnValueOnce(jobRequest.promise)
|
|
1507
|
+
.mockReturnValueOnce(staleRefresh.promise)
|
|
1508
|
+
.mockResolvedValueOnce(response({ jobs: [completed] }))
|
|
1509
|
+
const scope = effectScope()
|
|
1510
|
+
const generated = scope.run(() => useGeneratedAnalysis({
|
|
1511
|
+
baseUrl: '/api/demo',
|
|
1512
|
+
transport,
|
|
1513
|
+
storage: memoryStorage(),
|
|
1514
|
+
createId: () => 'tab-1',
|
|
1515
|
+
pollInterval: 10,
|
|
1516
|
+
stream: false,
|
|
1517
|
+
}))!
|
|
1518
|
+
let waiting: Promise<GeneratedAnalysisJob> | undefined
|
|
1519
|
+
|
|
1520
|
+
try {
|
|
1521
|
+
await generated.initialize()
|
|
1522
|
+
waiting = generated.waitForJob('live-job')
|
|
1523
|
+
void waiting.catch(() => undefined)
|
|
1524
|
+
|
|
1525
|
+
vi.advanceTimersByTime(10)
|
|
1526
|
+
await vi.waitFor(() => {
|
|
1527
|
+
if (transport.mock.calls.length !== 6) throw new Error('Concurrent job requests did not start')
|
|
1528
|
+
})
|
|
1529
|
+
jobRequest.resolve(response(running))
|
|
1530
|
+
await vi.waitFor(() => {
|
|
1531
|
+
if (generated.jobs.value[0]?.status !== 'running') throw new Error('Job lookup did not resolve')
|
|
1532
|
+
})
|
|
1533
|
+
staleRefresh.resolve(response({ jobs: [running] }))
|
|
1534
|
+
await vi.advanceTimersByTimeAsync(10)
|
|
1535
|
+
await vi.waitFor(() => {
|
|
1536
|
+
if (transport.mock.calls.length !== 7) throw new Error('Next list poll was not scheduled')
|
|
1537
|
+
})
|
|
1538
|
+
|
|
1539
|
+
await expect(waiting).resolves.toMatchObject({
|
|
1540
|
+
job_id: 'live-job',
|
|
1541
|
+
status: 'completed',
|
|
1542
|
+
})
|
|
1543
|
+
} finally {
|
|
1544
|
+
scope.stop()
|
|
1545
|
+
await waiting?.catch(() => undefined)
|
|
1546
|
+
vi.useRealTimers()
|
|
1547
|
+
}
|
|
1548
|
+
})
|
|
1549
|
+
|
|
1492
1550
|
it('does not regress a terminal job when a stale snapshot arrives without a concurrent update', async () => {
|
|
1493
1551
|
const completed = completedJob('terminal-job')
|
|
1494
1552
|
const staleQueued = activeJob('terminal-job')
|
|
@@ -459,7 +459,11 @@ function createPluginJobs(
|
|
|
459
459
|
const revision = jobsRevision
|
|
460
460
|
const pending = request<{ jobs: GeneratedAnalysisJobInput[] }>('/jobs', { method: 'GET' })
|
|
461
461
|
.then((payload) => {
|
|
462
|
-
if (disposed
|
|
462
|
+
if (disposed) return jobs.value
|
|
463
|
+
if (revision !== jobsRevision) {
|
|
464
|
+
if (jobs.value.some(job => ACTIVE_STATUSES.has(job.status))) schedulePoll()
|
|
465
|
+
return jobs.value
|
|
466
|
+
}
|
|
463
467
|
replaceJobs(payload.jobs)
|
|
464
468
|
error.value = null
|
|
465
469
|
if (!paused && !streamConnected && jobs.value.some(job => ACTIVE_STATUSES.has(job.status))) {
|
|
@@ -93,7 +93,9 @@
|
|
|
93
93
|
.sg-body__main {
|
|
94
94
|
padding: 1rem 1.25rem;
|
|
95
95
|
min-width: 0;
|
|
96
|
-
|
|
96
|
+
min-height: 0;
|
|
97
|
+
overflow-x: hidden;
|
|
98
|
+
overflow-y: auto;
|
|
97
99
|
display: flex; flex-direction: column; gap: 0.75rem;
|
|
98
100
|
}
|
|
99
101
|
.sg-body__side {
|
|
@@ -102,6 +104,8 @@
|
|
|
102
104
|
padding: 1.125rem 1.25rem;
|
|
103
105
|
display: flex; flex-direction: column;
|
|
104
106
|
min-width: 0;
|
|
107
|
+
min-height: 0;
|
|
108
|
+
overflow-y: auto;
|
|
105
109
|
gap: 0.75rem;
|
|
106
110
|
}
|
|
107
111
|
|