22 * Copyright (c) 2020-2026 LabKey Corporation. All rights reserved. No portion of this work may be reproduced
33 * in any form or by any electronic or mechanical means without written permission from LabKey Corporation.
44 */
5- import { applyLineageOptions , generateNodesAndEdges , LineageIO , LineageNode , LineageResult } from './models' ;
5+ import { applyLineageOptions , generateNodesAndEdges , Lineage , LineageIO , LineageNode , LineageResult } from './models' ;
66import { DEFAULT_LINEAGE_OPTIONS } from './constants' ;
7- import { LineageFilter } from './types' ;
7+ import { LineageFilter , LineageOptions } from './types' ;
88
99describe ( 'lineage model' , ( ) => {
1010 describe ( 'applyLineageOptions' , ( ) => {
@@ -33,6 +33,7 @@ describe('lineage model', () => {
3333 describe ( 'LineageIO.applyConfig' , ( ) => {
3434 const lineageObj = {
3535 container : 'container' ,
36+ containerPath : '/container' ,
3637 created : '2022-01-20' ,
3738 createdBy : 'me' ,
3839 modified : '2022-01-21' ,
@@ -235,13 +236,13 @@ describe('lineage model', () => {
235236 const parentLsid = 'parent-lsid' ;
236237
237238 const childNode = LineageNode . create ( childLsid , {
238- parents : [ { lsid : parentLsid , name : '&4[0' } ] ,
239- name : '&4[0_1001'
239+ parents : [ { lsid : parentLsid } ] ,
240+ name : '&4[0_1001' ,
240241 } ) ;
241242
242243 const parentNode = LineageNode . create ( parentLsid , {
243- children : [ { lsid : childLsid , name : '&4[0_1001' } ] ,
244- name : '&4[0'
244+ children : [ { lsid : childLsid } ] ,
245+ name : '&4[0' ,
245246 } ) ;
246247
247248 const result = LineageResult . create ( {
@@ -262,5 +263,87 @@ describe('lineage model', () => {
262263 expect ( nodes [ childNode . lsid ] . level ) . toEqual ( 0 ) ;
263264 expect ( nodes [ childNode . lsid ] . label ) . toEqual ( '&4[0_1001' ) ;
264265 } ) ;
266+
267+ it ( 'GH Issue #1256: Lineage graph can become disconnected with single aliquot and multiple derivatives' , ( ) => {
268+ // Parent sample with 2 derived samples and 1 aliquot including derivation runs
269+ const result = LineageResult . create ( {
270+ nodes : {
271+ 'aliquot-lsid' : {
272+ cpasType : 'sample-type-lsid' ,
273+ materialLineageType : 'Aliquot' ,
274+ type : 'Sample' ,
275+ lsid : 'aliquot-lsid' ,
276+ name : 'Aliquot-1' ,
277+ expType : 'Material' ,
278+ parents : [ { lsid : 'aliquot-run-lsid' } ] ,
279+ } ,
280+ 'aliquot-run-lsid' : {
281+ cpasType : 'urn:lsid:labkey.org:Protocol:SampleAliquotProtocol' ,
282+ type : 'Run' ,
283+ lsid : 'aliquot-run-lsid' ,
284+ children : [ { lsid : 'aliquot-lsid' } ] ,
285+ name : 'Create aliquot from Parent-1' ,
286+ expType : 'ExperimentRun' ,
287+ parents : [ { lsid : 'parent-lsid' } ] ,
288+ } ,
289+ 'derived-one-lsid' : {
290+ cpasType : 'sample-type-lsid' ,
291+ materialLineageType : 'Derivative' ,
292+ type : 'Sample' ,
293+ lsid : 'derived-one-lsid' ,
294+ name : 'Derived-1' ,
295+ expType : 'Material' ,
296+ parents : [ { lsid : 'derivation-run-lsid' } ] ,
297+ } ,
298+ 'derived-two-lsid' : {
299+ cpasType : 'sample-type-lsid' ,
300+ materialLineageType : 'Derivative' ,
301+ type : 'Sample' ,
302+ lsid : 'derived-two-lsid' ,
303+ name : 'Derived-2' ,
304+ expType : 'Material' ,
305+ parents : [ { lsid : 'derivation-run-lsid' } ] ,
306+ } ,
307+ 'derivation-run-lsid' : {
308+ cpasType : 'urn:lsid:labkey.org:Protocol:SampleDerivationProtocol' ,
309+ type : 'Run' ,
310+ lsid : 'derivation-run-lsid' ,
311+ children : [ { lsid : 'derived-two-lsid' } , { lsid : 'derived-one-lsid' } ] ,
312+ name : 'Derive 2 samples from Parent-1' ,
313+ expType : 'ExperimentRun' ,
314+ parents : [ { lsid : 'parent-lsid' } ] ,
315+ } ,
316+ 'parent-lsid' : {
317+ cpasType : 'sample-type-lsid' ,
318+ materialLineageType : 'RootMaterial' ,
319+ type : 'Sample' ,
320+ lsid : 'parent-lsid' ,
321+ children : [ { lsid : 'aliquot-run-lsid' } , { lsid : 'derivation-run-lsid' } ] ,
322+ name : 'Parent-1' ,
323+ expType : 'Material' ,
324+ } ,
325+ } ,
326+ seed : 'parent-lsid' ,
327+ } ) ;
328+
329+ const options : LineageOptions = {
330+ filters : [ new LineageFilter ( 'type' , [ 'Sample' ] ) ] ,
331+ } ;
332+
333+ const lineage = new Lineage ( { result } ) ;
334+ const nodesAndEdges = generateNodesAndEdges ( lineage . filterResult ( options ) , options ) ;
335+
336+ // Runs have been filtered out
337+ const expectedNodes = new Set ( [ 'aliquot-lsid' , 'derived-one-lsid' , 'derived-two-lsid' , 'parent-lsid' ] ) ;
338+ expect ( new Set ( Object . keys ( nodesAndEdges . nodes ) ) ) . toEqual ( expectedNodes ) ;
339+
340+ // Previously, this would have only two edges where the edge between the parent and aliquot was missing
341+ const expectedEdges = new Set ( [
342+ 'parent-lsid||aliquot-lsid' ,
343+ 'parent-lsid||derived-one-lsid' ,
344+ 'parent-lsid||derived-two-lsid' ,
345+ ] ) ;
346+ expect ( new Set ( Object . keys ( nodesAndEdges . edges ) ) ) . toEqual ( expectedEdges ) ;
347+ } ) ;
265348 } ) ;
266349} ) ;
0 commit comments