@@ -2330,4 +2330,142 @@ def set(_context, changes) end
23302330 described_class . register_transport ( schema )
23312331 end
23322332 end
2333+
2334+ describe 'finish method for class tag inheritance' , :agent_test do
2335+ let ( :definition ) do
2336+ {
2337+ name : 'tag_test' ,
2338+ desc : 'a test resource for tag inheritance' ,
2339+ attributes : {
2340+ name : {
2341+ type : 'String' ,
2342+ behaviour : :namevar ,
2343+ desc : 'the title'
2344+ } ,
2345+ ensure : {
2346+ type : 'Enum[present, absent]' ,
2347+ desc : 'the ensure value'
2348+ }
2349+ }
2350+ }
2351+ end
2352+ let ( :provider_class ) do
2353+ Class . new do
2354+ def get ( _context )
2355+ [ ]
2356+ end
2357+
2358+ def set ( _context , _changes ) ; end
2359+ end
2360+ end
2361+ let ( :type ) { Puppet ::Type . type ( :tag_test ) }
2362+ let ( :catalog ) { Puppet ::Resource ::Catalog . new }
2363+
2364+ before do
2365+ described_class . register_type ( definition )
2366+ stub_const ( 'Puppet::Provider::TagTest' , Module . new )
2367+ stub_const ( 'Puppet::Provider::TagTest::TagTest' , provider_class )
2368+ end
2369+
2370+ context 'when resource has pathbuilder with class names' do
2371+ let ( :instance ) { type . new ( name : 'test_resource' , ensure : 'present' ) }
2372+
2373+ before do
2374+ instance . catalog = catalog
2375+ allow ( instance ) . to receive ( :respond_to? ) . with ( :pathbuilder ) . and_return ( true )
2376+ allow ( instance ) . to receive ( :pathbuilder ) . and_return ( [ 'Stage[main]' , 'Test::MyClass' , 'Test::AnotherClass' , 'TagTest[test_resource]' ] )
2377+ end
2378+
2379+ it 'tags the resource with class names from pathbuilder' do
2380+ instance . finish
2381+ expect ( instance . tags . to_a ) . to include ( 'test::myclass' , 'test::anotherclass' , 'test' , 'anotherclass' , 'myclass' )
2382+ end
2383+
2384+ it 'does not tag resources that have brackets' do
2385+ instance . finish
2386+ expect ( instance . tags . to_a ) . not_to include ( 'stage[main]' )
2387+ expect ( instance . tags . to_a ) . not_to include ( 'tagtest[test_resource]' )
2388+ end
2389+ end
2390+
2391+ context 'when resource has pathbuilder with only resources (no classes)' do
2392+ let ( :instance ) { type . new ( name : 'test_resource2' , ensure : 'present' ) }
2393+
2394+ before do
2395+ instance . catalog = catalog
2396+ allow ( instance ) . to receive ( :respond_to? ) . with ( :pathbuilder ) . and_return ( true )
2397+ allow ( instance ) . to receive ( :pathbuilder ) . and_return ( [ 'Stage[main]' , 'TagTest[test_resource2]' ] )
2398+ end
2399+
2400+ it 'does not tag any classes' do
2401+ initial_tags = instance . tags . to_a
2402+ instance . finish
2403+ # Should only have the default tags, no class tags added
2404+ expect ( instance . tags . to_a - initial_tags ) . to be_empty
2405+ end
2406+ end
2407+
2408+ context 'when resource does not have pathbuilder' do
2409+ let ( :instance ) { type . new ( name : 'test_resource3' , ensure : 'present' ) }
2410+
2411+ before do
2412+ instance . catalog = catalog
2413+ allow ( instance ) . to receive ( :respond_to? ) . with ( :pathbuilder ) . and_return ( false )
2414+ end
2415+
2416+ it 'does not error' do
2417+ expect { instance . finish } . not_to raise_error
2418+ end
2419+ end
2420+
2421+ context 'when resource does not have a catalog' do
2422+ let ( :instance ) { type . new ( name : 'test_resource4' , ensure : 'present' ) }
2423+
2424+ before do
2425+ instance . catalog = nil
2426+ end
2427+
2428+ it 'returns early without processing' do
2429+ expect ( instance ) . not_to receive ( :pathbuilder )
2430+ instance . finish
2431+ end
2432+ end
2433+
2434+ context 'when pathbuilder returns mixed case class names' do
2435+ let ( :instance ) { type . new ( name : 'test_resource5' , ensure : 'present' ) }
2436+
2437+ before do
2438+ instance . catalog = catalog
2439+ allow ( instance ) . to receive ( :respond_to? ) . with ( :pathbuilder ) . and_return ( true )
2440+ allow ( instance ) . to receive ( :pathbuilder ) . and_return ( [ 'MyModule::MyClass' , 'AnotherModule' ] )
2441+ end
2442+
2443+ it 'normalizes class names to lowercase when tagging' do
2444+ instance . finish
2445+ # Puppet's tag() method automatically lowercases
2446+ expect ( instance . tags . to_a ) . to include ( 'mymodule::myclass' , 'anothermodule' , 'mymodule' , 'myclass' )
2447+ end
2448+ end
2449+
2450+ context 'when pathbuilder returns nested classes' do
2451+ let ( :instance ) { type . new ( name : 'test_resource6' , ensure : 'present' ) }
2452+
2453+ before do
2454+ instance . catalog = catalog
2455+ allow ( instance ) . to receive ( :respond_to? ) . with ( :pathbuilder ) . and_return ( true )
2456+ allow ( instance ) . to receive ( :pathbuilder ) . and_return ( [
2457+ 'Stage[main]' ,
2458+ 'Profiles::Base' ,
2459+ 'Profiles::Web' ,
2460+ 'Profiles::Web::Apache' ,
2461+ 'TagTest[test_resource6]'
2462+ ] )
2463+ end
2464+
2465+ it 'tags all classes in the containment hierarchy' do
2466+ instance . finish
2467+ expect ( instance . tags . to_a ) . to include ( 'profiles::base' , 'profiles::web' , 'profiles::web::apache' , 'profiles' , 'web' , 'base' , 'apache' )
2468+ end
2469+ end
2470+ end
23332471end
0 commit comments