Data-Hash-Diff-Smart

 view release on metacpan or  search on metacpan

t/function.t  view on Meta::CPAN

	subtest 'compare option: comparator exception is captured' => sub {
		my $r = diff(
			{x => 1},
			{x => 2},
			compare => { '/x' => sub { die "boom\n" } },
		);
		is($r->[0]{op}, 'change', 'comparator exception still records a change');
		like($r->[0]{error}, qr/boom/, 'error field contains exception message');
	};

	subtest 'cycle detection: does not loop infinitely' => sub {
		my $a = {x => 1};
		$a->{self} = $a;
		my $b = {x => 1};
		$b->{self} = $b;

		my $r;
		lives_ok(sub { $r = diff($a, $b) }, 'cycle detection: no infinite loop');
		isa_ok($r, 'ARRAY', 'result is still an arrayref after cycle');
	};

};

# ===========================================================================
# SECTION 2: diff_text()
# ===========================================================================

subtest 'diff_text()' => sub {

	subtest 'returns a string' => sub {
		my $t = diff_text({a => 1}, {a => 2});
		ok(defined $t,        'returns defined value');
		ok(!ref($t),          'returns a plain string');
		like($t, qr/\S/,      'non-empty for changed structures');
	};

	subtest 'no changes produces empty or whitespace-only output' => sub {
		my $t = diff_text({a => 1}, {a => 1});
		ok(defined $t, 'defined for identical structures');
		# Either empty string or whitespace is acceptable
		ok(!length($t) || $t =~ /^\s*$/, 'empty/whitespace for no changes');
	};

	subtest 'output mentions changed path' => sub {
		my $t = diff_text({user => {name => 'Alice'}}, {user => {name => 'Bob'}});
		like($t, qr/name|user/i, 'output references the changed field');
	};

};

# ===========================================================================
# SECTION 3: diff_json()
# ===========================================================================

subtest 'diff_json()' => sub {

	subtest 'returns valid JSON string' => sub {
		require JSON::MaybeXS;
		my $j = diff_json({a => 1}, {a => 2});
		ok(defined $j, 'returns a defined value');
		my $decoded = eval { JSON::MaybeXS::decode_json($j) };
		ok(!$@,        'output is valid JSON');
		isa_ok($decoded, 'ARRAY', 'decoded JSON is an array');
	};

	subtest 'JSON contains op field' => sub {
		require JSON::MaybeXS;
		my $j = diff_json({a => 1}, {a => 2});
		my $decoded = JSON::MaybeXS::decode_json($j);
		is($decoded->[0]{op}, 'change', 'first entry has op=change');
	};

	subtest 'JSON for identical structures' => sub {
		require JSON::MaybeXS;
		my $j = diff_json({a => 1}, {a => 1});
		my $decoded = JSON::MaybeXS::decode_json($j);
		is_deeply($decoded, [], 'empty JSON array for no changes');
	};

};

# ===========================================================================
# SECTION 4: diff_yaml()
# ===========================================================================

subtest 'diff_yaml()' => sub {

	subtest 'returns a YAML string' => sub {
		my $y = diff_yaml({a => 1}, {a => 2});
		ok(defined $y,     'returns a defined value');
		ok(!ref($y),       'returns a plain string');
		like($y, qr/\S/,   'non-empty for changed structures');
	};

	subtest 'YAML contains op key' => sub {
		my $y = diff_yaml({a => 1}, {a => 2});
		like($y, qr/op.*change|change.*op/s, 'YAML output mentions op: change');
	};

	subtest 'YAML for identical structures' => sub {
		my $y = diff_yaml({a => 1}, {a => 1});
		# An empty sequence in YAML is '--- []\n' or '--- \n- \n' etc.
		unlike($y, qr/op:/, 'no op entry in YAML for no changes');
	};

};

# ===========================================================================
# SECTION 5: diff_test2()
# ===========================================================================

subtest 'diff_test2()' => sub {

	subtest 'returns a string for changed structures' => sub {
		my $t = diff_test2({a => 1}, {a => 2});
		ok(defined $t, 'returns defined value');
		ok(!ref($t),   'returns a string');
		like($t, qr/\S/, 'non-empty for changes');
	};

	subtest 'returns something defined for identical structures' => sub {
		my $t = diff_test2({a => 1}, {a => 1});
		ok(defined $t, 'returns defined for identical structures');
	};

};

# ===========================================================================
# SECTION 5b: Renderer::Test2 - white-box unit tests
#
# We call the renderer directly with hand-crafted change lists so each
# branch of render() is exercised in isolation, independent of the diff
# engine.
# ===========================================================================

BEGIN { require Data::Hash::Diff::Smart::Renderer::Test2 }



( run in 1.165 second using v1.01-cache-2.11-cpan-df04353d9ac )