diff --git a/lib/GPH/PHPMD.pm b/lib/GPH/PHPMD.pm
index 33fd174..0f13b28 100644
--- a/lib/GPH/PHPMD.pm
+++ b/lib/GPH/PHPMD.pm
@@ -45,33 +45,33 @@ sub new {
#
# Returns: ruleset.xml config file string
sub getConfig {
- my $self = shift;
+ my $self = shift;
- my $ruleset = $self->{generator}->buildElement('ruleset', undef, undef, (
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' => 'http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd',
- 'xsi:noNamespaceSchemaLocation' => 'http://pmd.sf.net/ruleset_xml_schema.xsd',
- 'name' => "$self->{owner} PHPMD rule set",
- ));
+ my $ruleset = $self->{generator}->buildElement((name => 'ruleset', attributes => {
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd',
+ 'xsi:noNamespaceSchemaLocation' => 'http://pmd.sf.net/ruleset_xml_schema.xsd',
+ 'name' => "$self->{owner} PHPMD rule set",
+ }));
- $ruleset->setNamespace('http://pmd.sf.net/ruleset/1.0.0');
+ $ruleset->setNamespace('http://pmd.sf.net/ruleset/1.0.0');
- my $rule = $self->{generator}->buildElement('rule', undef, $ruleset, (
- 'ref' => 'rulesets/codesize.xml/CyclomaticComplexity'
- ));
+ my $rule = $self->{generator}->buildElement((name => 'rule', parent => $ruleset, attributes => {
+ 'ref' => 'rulesets/codesize.xml/CyclomaticComplexity'
+ }));
- my $properties = $self->{generator}->buildElement('properties', undef, $rule);
+ my $properties = $self->{generator}->buildElement((name => 'properties', parent => $rule));
- $self->{generator}->buildElement('property', undef, $properties, (
- 'name' => 'reportLevel',
- 'value' => $self->{cycloLevel}
- ));
+ $self->{generator}->buildElement((name => 'property', parent => $properties, attributes => {
+ 'name' => 'reportLevel',
+ 'value' => $self->{cycloLevel}
+ }));
- my $dom = $self->{generator}->getDom();
+ my $dom = $self->{generator}->getDom();
- $dom->setDocumentElement($ruleset);
+ $dom->setDocumentElement($ruleset);
- return ($dom->toString(1));
+ return ($dom->toString(1));
}
1;
\ No newline at end of file
diff --git a/lib/GPH/Psalm.pm b/lib/GPH/Psalm.pm
index c3439c7..14ccbf6 100644
--- a/lib/GPH/Psalm.pm
+++ b/lib/GPH/Psalm.pm
@@ -61,7 +61,7 @@ sub new {
sub getConfig {
my $self = shift;
- my $psalm = $self->{generator}->buildElement('psalm', undef, undef, (
+ my $psalm = $self->{generator}->buildElement((name => 'psalm', attributes => {
'resolveFromConfigFile' => 'true',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd',
@@ -69,35 +69,35 @@ sub getConfig {
'cacheDirectory' => $self->{cacheDir},
'errorBaseline' => $self->{baseline},
'findUnusedBaselineEntry' => $self->{baselineCheck},
- ));
+ }));
$psalm->setNamespace('https://getpsalm.org/schema/config');
- my $projectFiles = $self->{generator}->buildElement('projectFiles', undef, $psalm);
+ my $projectFiles = $self->{generator}->buildElement((name => 'projectFiles', parent => $psalm));
foreach my $path (@{$self->{paths}}) {
- $self->{generator}->buildElement('directory', undef, $projectFiles, (
+ $self->{generator}->buildElement((name => 'directory', parent => $projectFiles, attributes => {
'name' => $path,
- ));
+ }));
}
if (defined $self->{ignoredDirectories}) {
- my $ignoreFiles = $self->{generator}->buildElement('ignoreFiles', undef, $projectFiles);
+ my $ignoreFiles = $self->{generator}->buildElement((name => 'ignoreFiles', parent => $projectFiles));
foreach my $path (@{$self->{ignoredDirectories}}) {
- $self->{generator}->buildElement('directory', undef, $ignoreFiles, (
+ $self->{generator}->buildElement((name => 'directory', parent => $ignoreFiles, attributes => {
'name' => $path,
- ));
+ }));
}
}
if (defined $self->{plugins}) {
- my $plugins = $self->{generator}->buildElement('plugins', undef, $psalm);
+ my $plugins = $self->{generator}->buildElement((name => 'plugins', parent => $psalm));
foreach my $plugin (@{$self->{plugins}}) {
- $self->{generator}->buildElement('pluginClass', undef, $plugins, (
+ $self->{generator}->buildElement((name => 'pluginClass', parent => $plugins, attributes => {
'class' => $plugin,
- ));
+ }));
}
}
diff --git a/lib/GPH/XMLHelper.pm b/lib/GPH/XMLHelper.pm
index 2f2c4d9..49803ba 100644
--- a/lib/GPH/XMLHelper.pm
+++ b/lib/GPH/XMLHelper.pm
@@ -5,6 +5,7 @@
#
# Revisions: 2023-09-03 - created
# 2024-02-10 - namespaced module, bugfixes and unit tests
+# 2024-02-12 - constructor now requires named arguments
#------------------------------------------------------------------------------
package GPH::XMLHelper;
@@ -33,32 +34,36 @@ sub new {
#------------------------------------------------------------------------------
# Build element
#
-# Inputs: 0) string: name of the element
-# 1) mixed: value of the element
-# 2) LibXML::Element object: parent element
-# 3) list: element attributes
+# Inputs: name => (string) name of the element
+# value => (string) value of the element
+# parent => (LibXML::Element object) parent element
+# attributes => (hash) element attributes
#
# Returns: LibXML::Element object
sub buildElement {
- my ($self, $name, $value, $parent, %attributes) = @_;
+ my ($self, %args) = @_;
- my $element = $self->{dom}->createElement($name);
+ (exists($args{name})) or die "$!";
- foreach my $key (sort keys %attributes) {
- if (defined $attributes{$key}) {
- $element->{$key} = $attributes{$key};
+ my $element = $self->{dom}->createElement($args{name});
+
+ if (exists($args{attributes})) {
+ foreach my $key (sort keys %{$args{attributes}}) {
+ if (defined $args{attributes}{$key}) {
+ $element->{$key} = $args{attributes}{$key};
+ }
+ }
}
- }
- if (defined $value) {
- $element->appendText($value);
- }
+ if (defined $args{value}) {
+ $element->appendText($args{value});
+ }
- if (defined $parent) {
- $parent->appendChild($element);
- }
+ if (defined $args{parent}) {
+ $args{parent}->appendChild($element);
+ }
- return $element;
+ return $element;
}
#------------------------------------------------------------------------------
diff --git a/t/unit/GPH/XMLHelper.t b/t/unit/GPH/XMLHelper.t
new file mode 100644
index 0000000..ac8a819
--- /dev/null
+++ b/t/unit/GPH/XMLHelper.t
@@ -0,0 +1,137 @@
+#!/usr/bin/perl
+package t::unit::GPH::XMLHelper;
+
+use strict;
+use warnings;
+
+use Test2::V0 -target => 'GPH::XMLHelper';
+use Test2::Tools::Spec;
+use Data::Dumper;
+
+local $SIG{__WARN__} = sub {};
+
+describe "class `$CLASS`" => sub {
+ tests 'it can be instantiated' => sub {
+ can_ok($CLASS, 'new');
+ };
+
+ tests "mandatory element options" => sub {
+ my $object = $CLASS->new();
+
+ ok(dies {$object->buildElement((attributes => {}))}, 'died with missing name') or note($@);
+ ok(lives {$object->buildElement((name => 'foo'))}, 'lives with mandatory options') or note($@);
+ };
+
+ tests 'object validation' => sub {
+ my ($object, $exception, $warnings);
+ $exception = dies {
+ $warnings = warns {
+ $object = $CLASS->new();
+ };
+ };
+
+ is($exception, undef, 'no exception thrown');
+ is($warnings, 0, 'no warnings generated');
+ is(
+ $object,
+ object {
+ field dom => object {
+ prop blessed => 'XML::LibXML::Document';
+ };
+ },
+ 'object as expected',
+ Dumper($object)
+ );
+
+ };
+};
+
+describe 'test element' => sub {
+ my (%args, $element, $expected_xml);
+
+ case 'name value attributes' => sub {
+ %args = (
+ name => 'foo',
+ value => 'bar',
+ attributes => {
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
+ }
+ );
+ $expected_xml = 'bar';
+ };
+
+ case 'name' => sub {
+ %args = (
+ name => 'foo',
+ );
+ $expected_xml = '';
+ };
+
+ case 'name value' => sub {
+ %args = (
+ name => 'foo',
+ value => 'bar',
+ );
+ $expected_xml = 'bar';
+ };
+
+ tests 'element generation' => sub {
+ my ($object, $exception, $warnings);
+ $exception = dies {
+ $warnings = warns {
+ $object = $CLASS->new();
+ $element = $object->buildElement(%args);
+ };
+ };
+
+ is($exception, undef, 'no exception thrown');
+ is($warnings, 0, 'no warnings generated');
+
+ is(
+ $element->toString(),
+ $expected_xml,
+ 'element as expected',
+ Dumper($element)
+ );
+ };
+};
+
+describe 'test paren element' => sub {
+ my ($object, $dom, $element, $exception, $warnings);
+
+ $exception = dies {
+ $warnings = warns {
+ $object = $CLASS->new();
+ $element = $object->buildElement((
+ name => 'foo',
+ attributes => {
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
+ }
+ ));
+
+ $object->buildElement((
+ name => 'bar',
+ parent => $element,
+ value => 'baz',
+ ));
+
+ $dom = $object->getDom();
+ $dom->setDocumentElement($element);
+ };
+ };
+
+ is($exception, undef, 'no exception thrown');
+ is($warnings, 0, 'no warnings generated');
+
+ is(
+ $dom->toString(),
+ '
+baz
+',
+ 'parent child element as expected',
+ Dumper($dom->toString())
+ )
+};
+
+done_testing();
+