{"id":17109584,"url":"https://github.com/monken/p5-test-file-content","last_synced_at":"2025-03-23T21:41:32.703Z","repository":{"id":1332644,"uuid":"1278410","full_name":"monken/p5-test-file-content","owner":"monken","description":"Tests files for their content based on their file extension","archived":false,"fork":false,"pushed_at":"2011-01-21T22:51:25.000Z","size":96,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-29T05:13:36.605Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monken.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-01-21T13:38:06.000Z","updated_at":"2014-09-08T21:48:05.000Z","dependencies_parsed_at":"2022-08-16T13:10:20.203Z","dependency_job_id":null,"html_url":"https://github.com/monken/p5-test-file-content","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monken%2Fp5-test-file-content","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monken%2Fp5-test-file-content/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monken%2Fp5-test-file-content/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monken%2Fp5-test-file-content/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monken","download_url":"https://codeload.github.com/monken/p5-test-file-content/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245175323,"owners_count":20572781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T16:23:41.034Z","updated_at":"2025-03-23T21:41:32.683Z","avatar_url":"https://github.com/monken.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"package Test::File::Content;\nuse strict;\nuse warnings;\n# ABSTRACT: Tests files for their content based on their file extension\nuse Test::More ();\nuse Path::Class::File;\nuse File::Find ();\n\nuse Exporter qw(import);\nour @EXPORT = qw(content_like content_unlike);\n\nsub _parse_args {\n    my $type   = shift;\n    my $filter = shift;\n    if ( ref $filter eq 'HASH' ) {\n        while ( my ( $k, $v ) = each %$filter ) {\n            _parse_args( $type, $k, $v, @_ );\n        }\n    } elsif ( ref $filter eq 'ARRAY' ) {\n        for (@$filter) {\n            _parse_args( $type, $_, @_ );\n        }\n    } else {\n        if ( ref $filter eq 'Regexp' ) {\n            my $copy = $filter;\n            $filter = sub { return 1 if -d $_[0]; $_[0] =~ $copy };\n        } elsif ( !ref $filter ) {\n            my $copy = $filter;\n            $filter = sub { return 1 if -d $_[0]; $_[0] =~ /\\.\\Q$copy\\E/ };\n        }\n        my $rules = shift;\n        if ( ref $rules eq 'HASH' ) {\n            $rules = {\n                map {\n                    $_ =\u003e ( ref $rules-\u003e{$_} eq 'Regexp'\n                            ? $rules-\u003e{$_}\n                            : qr/\\Q$rules-\u003e{$_}\\E/sm )\n                  } keys %$rules };\n        } else {\n            $rules = [$rules] unless ( ref $rules eq 'ARRAY' );\n            $rules =\n              { map { $_ =\u003e ( ref $_ eq 'Regexp' ? $_ : qr/\\Q$_\\E/sm ) }\n                @$rules };\n        }\n        _check_files( $type, $filter, $rules, @_ );\n    }\n}\n\nsub content_like {\n    _parse_args( 'like', @_ );\n\n}\n\nsub content_unlike {\n    _parse_args( 'unlike', @_ );\n\n}\n\nsub _check_files {\n    my ( $type, $filter, $rules, @dirs ) = @_;\n    @dirs = ('.') unless(@dirs);\n    my @files;\n    my $tree = File::Find::find( sub { push(@files, $File::Find::name) if($filter-\u003e($File::Find::name)) }, @dirs );\n    @files = sort @files;\n    while ( my $file = shift @files ) {\n        next if -d $file;\n        $file = Path::Class::File-\u003enew($file);\n        my $content = $file-\u003eslurp;\n\n        my @failures;\n        while ( my ( $comment, $rule ) = each %$rules ) {\n            if ( $type eq 'unlike' ) {\n                while ( $content =~ /$rule/g ) {\n                    my $message =\n                        $comment\n                      . \" found in \"\n                      . $file\n                      . ' line '\n                      . _line_by_pos( $content, pos($content) );\n                    push( @failures, $message );\n                }\n            } elsif ( $content !~ /$rule/g ) {\n                push( @failures,\n                      'file ' . $file . ' does not contain ' . $comment );\n            }\n        }\n\n        Test::More::ok( !@failures, $file );\n        Test::More::diag( join( \"\\n\", @failures ) ) if (@failures);\n    }\n}\n\nsub _line_by_pos {\n    my ( $file, $pos ) = @_;\n    my $i = 1;\n    while ( $file =~ /\\n/g ) {\n        last if ( pos($file) \u003e $pos );\n        $i++;\n    }\n    return $i;\n}\n\n1;\n\n__END__\n\n=head1 SYNOPSIS\n\n use Test::File::Content;\n use Test::More;\n \n content_like( qr/\\.pm/, qr/^#\\s*ABSTRACT/, 'lib' );\n \n content_like( pm =\u003e '__PACKAGE__-\u003emeta-\u003emake_immutable', 'lib/MooseClasses' );\n \n content_unlike({\n     js =\u003e {\n         'console.log debug statement' =\u003e 'console.log',\n         'never use alert' =\u003e qr/[^\\.]alert\\(/,\n     },\n     tt =\u003e [\n        qr/\\[% DUMP/,\n     ],\n     pl =\u003e '\\$foo',\n }, qw(lib root/templates jslib));\n \n done_testing;\n\nExample output:\n\n not ok 1 - lib/MyLib.pm\n #   Failed test 'lib/MyLib.pm'\n # file lib/MyLib.pm does not contain (?-xism:^#\\s*ABSTRACT)\n ok 2 - lib/MooseClasses/Class.pm\n not ok 3 - jslib/test.js\n #   Failed test 'jslib/test.js'\n # console.log debug statement found in jslib/test.js line 1\n # console.log debug statement found in jslib/test.js line 2\n ok 4 - root/templates/test.tt\n 1..4\n\n=head1 DESCRIPTION\n\nWhen writing code, I tend to add a lot of debug statements like C\u003cwarn\u003e or C\u003cData::Dumper\u003e. \nOccasionally I name my variables C\u003c$foo\u003e and C\u003c$bar\u003e which is also quite a bad coding style.\nJavaScript files may contain C\u003cconsole.log()\u003e or C\u003calert()\u003e calls, which are equally bad.\n\nThis test can help to find statements like these and ensure that other statements are there.\n\n=head1 FUNCTIONS\n\nThe following functions are exported by default:\n\n=head2 content_like\n\n=head2 content_unlike\n\nB\u003cArguments:\u003e \\%config, @directories\n\nB\u003cArguments:\u003e $filter, $rule, @directories\n\nC\u003c%config\u003e consists of key value pairs where each key is a file extension (e.g. C\u003c.pm\u003e) and the\nvalue is a C\u003c$rule\u003e.\n\nC\u003c$filter\u003e can either be a string literal (like the key of C\u003c%config\u003e), an arrayref of extensions, \na regular expression or even a coderef. The coderef is passed the filename as argument and \nis expected to return a true value if the file should be looked at.\n\nC\u003c$rule\u003e can be a string literal, an arrayref of rules or a regular expression.\n\nC\u003c@directories\u003e contains a list of directories or files to look at.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonken%2Fp5-test-file-content","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonken%2Fp5-test-file-content","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonken%2Fp5-test-file-content/lists"}