@@ -592,19 +592,51 @@ describe('javalab2 sourceConverter', () => {
592592 expect ( image . type ) . toBe ( ProjectFileType . STARTER ) ;
593593 } ) ;
594594
595- it ( 'flatToMultiFile passes flagged through and omits absent url/flagged ' , ( ) => {
595+ it ( 'flatToMultiFile types locked starter-asset files LOCKED_STARTER ' , ( ) => {
596596 const mf = flatToMultiFile ( {
597- 'Main.java' : flatFile ( 'class Main {}' , 0 ) ,
598- 'cat.png' : { ...assetEntry , flagged : true } ,
597+ 'cat.png' : {
598+ text : '' ,
599+ isVisible : true ,
600+ url : '/level_starter_assets/My%20Level/uuid/uuid-1.png' ,
601+ locked : true ,
602+ } ,
599603 } ) ;
600604 const image = Object . values ( mf . files ) . find ( f => f . name === 'cat.png' ) ! ;
601- expect ( image . flagged ) . toBe ( true ) ;
605+ expect ( image . type ) . toBe ( ProjectFileType . LOCKED_STARTER ) ;
606+ } ) ;
607+
608+ it ( 'round-trips a locked starter asset through multiFile -> flat -> multiFile' , ( ) => {
609+ const source : MultiFileSource = {
610+ folders : { } ,
611+ files : {
612+ '0' : {
613+ id : '0' ,
614+ name : 'cat.png' ,
615+ contents : '' ,
616+ folderId : DEFAULT_FOLDER_ID ,
617+ type : ProjectFileType . LOCKED_STARTER ,
618+ url : '/level_starter_assets/My%20Level/uuid/uuid-1.png' ,
619+ } ,
620+ } ,
621+ openFiles : [ ] ,
622+ } ;
623+ const flat = multiFileToFlat ( source ) ;
624+ expect ( flat [ 'cat.png' ] . locked ) . toBe ( true ) ;
625+ const round = flatToMultiFile ( flat ) ;
626+ const image = Object . values ( round . files ) . find ( f => f . name === 'cat.png' ) ! ;
627+ expect ( image . type ) . toBe ( ProjectFileType . LOCKED_STARTER ) ;
628+ } ) ;
629+
630+ it ( 'flatToMultiFile omits absent url' , ( ) => {
631+ const mf = flatToMultiFile ( {
632+ 'Main.java' : flatFile ( 'class Main {}' , 0 ) ,
633+ 'cat.png' : { ...assetEntry } ,
634+ } ) ;
602635 const main = Object . values ( mf . files ) . find ( f => f . name === 'Main.java' ) ! ;
603636 expect ( 'url' in main ) . toBe ( false ) ;
604- expect ( 'flagged' in main ) . toBe ( false ) ;
605637 } ) ;
606638
607- it ( 'multiFileToFlat emits url and flagged when present' , ( ) => {
639+ it ( 'multiFileToFlat emits url when present' , ( ) => {
608640 const source : MultiFileSource = {
609641 folders : { } ,
610642 files : {
@@ -614,7 +646,6 @@ describe('javalab2 sourceConverter', () => {
614646 contents : '' ,
615647 folderId : 'root' ,
616648 url : assetEntry . url ,
617- flagged : true ,
618649 } ,
619650 '1' : {
620651 id : '1' ,
@@ -628,10 +659,8 @@ describe('javalab2 sourceConverter', () => {
628659 } ;
629660 const flat = multiFileToFlat ( source ) ;
630661 expect ( flat [ 'cat.png' ] . url ) . toBe ( assetEntry . url ) ;
631- expect ( flat [ 'cat.png' ] . flagged ) . toBe ( true ) ;
632662 expect ( flat [ 'cat.png' ] . isVisible ) . toBe ( true ) ;
633663 expect ( 'url' in flat [ 'Main.java' ] ) . toBe ( false ) ;
634- expect ( 'flagged' in flat [ 'Main.java' ] ) . toBe ( false ) ;
635664 } ) ;
636665
637666 it ( 'round-trips an open image tab through flat -> multiFile -> flat' , ( ) => {
@@ -662,6 +691,56 @@ describe('javalab2 sourceConverter', () => {
662691 } ) ;
663692 } ) ;
664693
694+ describe ( 'locked starter files' , ( ) => {
695+ it ( 'flatToMultiFile types locked visible files LOCKED_STARTER' , ( ) => {
696+ const mf = flatToMultiFile ( {
697+ 'Locked.java' : { ...flatFile ( 'class Locked {}' , 0 ) , locked : true } ,
698+ 'Main.java' : flatFile ( 'class Main {}' , 1 ) ,
699+ } ) ;
700+ const locked = Object . values ( mf . files ) . find (
701+ f => f . name === 'Locked.java'
702+ ) ! ;
703+ const main = Object . values ( mf . files ) . find ( f => f . name === 'Main.java' ) ! ;
704+ expect ( locked . type ) . toBe ( ProjectFileType . LOCKED_STARTER ) ;
705+ expect ( main . type ) . toBe ( ProjectFileType . STARTER ) ;
706+ } ) ;
707+
708+ it ( 'multiFileToFlat sets locked on LOCKED_STARTER files only' , ( ) => {
709+ const source : MultiFileSource = {
710+ folders : { } ,
711+ files : {
712+ '0' : {
713+ id : '0' ,
714+ name : 'Locked.java' ,
715+ contents : 'class Locked {}' ,
716+ folderId : DEFAULT_FOLDER_ID ,
717+ type : ProjectFileType . LOCKED_STARTER ,
718+ } ,
719+ '1' : {
720+ id : '1' ,
721+ name : 'Main.java' ,
722+ contents : 'class Main {}' ,
723+ folderId : DEFAULT_FOLDER_ID ,
724+ type : ProjectFileType . STARTER ,
725+ } ,
726+ } ,
727+ openFiles : [ '0' , '1' ] ,
728+ } ;
729+ const flat = multiFileToFlat ( source ) ;
730+ expect ( flat [ 'Locked.java' ] . locked ) . toBe ( true ) ;
731+ expect ( flat [ 'Locked.java' ] . isVisible ) . toBe ( true ) ;
732+ expect ( 'locked' in flat [ 'Main.java' ] ) . toBe ( false ) ;
733+ } ) ;
734+
735+ it ( 'round-trips a locked file through flat -> multiFile -> flat' , ( ) => {
736+ const original : JavalabFlatSource = {
737+ 'Locked.java' : { ...flatFile ( 'class Locked {}' , 0 ) , locked : true } ,
738+ } ;
739+ const round = multiFileToFlat ( flatToMultiFile ( original ) ) ;
740+ expect ( round [ 'Locked.java' ] . locked ) . toBe ( true ) ;
741+ } ) ;
742+ } ) ;
743+
665744 describe ( 'start + validation round trip' , ( ) => {
666745 // What Javalab2View actually does in start mode: merge validation
667746 // into start, hand to codebridge as MultiFileSource, then on save
0 commit comments