@@ -831,6 +831,134 @@ describe('OrgFile', function()
831831 end )
832832 end )
833833
834+ describe (' get_headlines_shallow' , function ()
835+ it (' should get all headlines with correct structure' , function ()
836+ local file = load_file_sync ({
837+ ' * TODO Headline 1' ,
838+ ' ** [#A] Priority Headline :tag1:tag2:' ,
839+ ' *** DONE Archived Headline :ARCHIVE:' ,
840+ ' * Plain Headline' ,
841+ })
842+
843+ local headlines = file :get_headlines_shallow ()
844+
845+ assert .are .same (4 , # headlines )
846+
847+ -- Verify data structure
848+ local headline = headlines [1 ]
849+ assert .is .not_nil (headline .title )
850+ assert .is .not_nil (headline .level )
851+ assert .is .not_nil (headline .line_number )
852+ assert .is .not_nil (headline .all_tags )
853+ assert .is .not_nil (headline .is_archived )
854+
855+ -- Verify specific values
856+ assert .are .same (' Headline 1' , headlines [1 ].title )
857+ assert .are .same (1 , headlines [1 ].level )
858+ assert .are .same (1 , headlines [1 ].line_number )
859+ assert .are .same ({}, headlines [1 ].all_tags )
860+ assert .is .False (headlines [1 ].is_archived )
861+
862+ assert .are .same (' Priority Headline' , headlines [2 ].title )
863+ assert .are .same (2 , headlines [2 ].level )
864+ assert .are .same ({ ' tag1' , ' tag2' }, headlines [2 ].all_tags )
865+
866+ assert .are .same (' Archived Headline' , headlines [3 ].title )
867+ assert .are .same ({ ' ARCHIVE' }, headlines [3 ].all_tags )
868+ assert .is .True (headlines [3 ].is_archived )
869+ end )
870+
871+ it (' should return same count as get_headlines for regular files' , function ()
872+ local file = load_file_sync ({
873+ ' * TODO Headline 1' ,
874+ ' * TODO Headline 2' ,
875+ ' ** Headline 2.1' ,
876+ ' *** Headline 2.1.1' ,
877+ ' * DONE Headline 3' ,
878+ })
879+
880+ local shallow = file :get_headlines_shallow ()
881+ local heavy = file :get_headlines ()
882+
883+ assert .are .same (# heavy , # shallow )
884+ end )
885+
886+ -- Parameterized archive tests
887+ local archive_test_cases = {
888+ {
889+ name = ' regular file without archived option' ,
890+ filename = nil , -- will use .org
891+ opts = {},
892+ content = { ' * Headline' , ' * Archived :ARCHIVE:' },
893+ expected_count = 2 ,
894+ },
895+ {
896+ name = ' archive file without archived option' ,
897+ filename = ' test.org_archive' ,
898+ opts = {},
899+ content = { ' * Headline' , ' * Archived :ARCHIVE:' },
900+ expected_count = 0 ,
901+ },
902+ {
903+ name = ' archive file with archived=true' ,
904+ filename = ' test.org_archive' ,
905+ opts = { archived = true },
906+ content = { ' * Headline' , ' * Archived :ARCHIVE:' },
907+ expected_count = 2 ,
908+ },
909+ }
910+
911+ for _ , case in ipairs (archive_test_cases ) do
912+ it (' should handle archives: ' .. case .name , function ()
913+ local filename = case .filename and (vim .fn .tempname () .. case .filename ) or nil
914+ local file = load_file_sync (case .content , filename )
915+ local headlines = file :get_headlines_shallow (case .opts )
916+ assert .are .same (case .expected_count , # headlines )
917+ end )
918+ end
919+
920+ it (' should respect max_depth filtering' , function ()
921+ local file = load_file_sync ({
922+ ' * Level 1' ,
923+ ' ** Level 2' ,
924+ ' *** Level 3' ,
925+ ' **** Level 4' ,
926+ })
927+
928+ local all_headlines = file :get_headlines_shallow ()
929+ local depth_2 = file :get_headlines_shallow ({ max_depth = 2 })
930+
931+ assert .are .same (4 , # all_headlines )
932+ assert .are .same (2 , # depth_2 )
933+ end )
934+
935+ it (' should match get_headlines filtering behavior' , function ()
936+ local content = {
937+ ' * TODO Headline 1' ,
938+ ' ** Headline 1.1' ,
939+ ' *** TODO Headline 1.1.1 :ARCHIVE:' ,
940+ ' **** Headline 1.1.1.1' ,
941+ ' * DONE Headline 2' ,
942+ }
943+ local file = load_file_sync (content )
944+
945+ -- Compare filtering with different options
946+ local shallow_all = file :get_headlines_shallow ()
947+ local heavy_all = file :get_headlines ()
948+ assert .are .same (# heavy_all , # shallow_all )
949+
950+ local shallow_archived = file :get_headlines_shallow ({ archived = true })
951+ local heavy_archived = file :get_headlines_including_archived ()
952+ assert .are .same (# heavy_archived , # shallow_archived )
953+ end )
954+
955+ it (' should handle empty files gracefully' , function ()
956+ local file = load_file_sync ({})
957+ local headlines = file :get_headlines_shallow ()
958+ assert .are .same (0 , # headlines )
959+ end )
960+ end )
961+
834962 describe (' get_todos' , function ()
835963 local has_correct_type = function (todos )
836964 assert .are .same (' TODO' , todos .todo_keywords [1 ].type )
0 commit comments