How can I check that a specific $string
(f.e. 123
) only occurs within a specific HTML element but not outside or anywhere else using PHP/Codeception acceptance tests?
Example which would be fine:
<html><body>foobar 234<div id="original">123</div></body></html>
Example which should fail #1 (text occurrence):
<html><body>foobar 123<div id="original">123</div></body></html>
Example which should fail #2 (link occurrence):
<html>
<body>
foobar
<div id="original">123</div>
<a href="/link/123">Link</a>
</body>
</html>
What I've tried on tests other than that specific page:
$I->seeInPageSource($alias);
$I->dontSeeInPageSource($original);
Now I would need something like
$I->seeInPageSourceElement($original, '#original');
$I->dontSeeInPageSourceExceptElement($original, '#original');
// could be implemented like this:
$pageSourceWithoutElement = str_replace(
$I->grabPageSourceElement('#original'),
'',
$I->grabPageSource()
);
$I->assertNotContains($original, $pageSourceWithoutElement);
Reason: I have two versions, where one version is alias for another (called "original"). I want to make sure only the alias is used everywhere except on the "show original" page, where the alias defition is shown.
I found a solution:
Not the perfect solution, but it works.
public function dontSeeInPageSourceExceptElement($text, $excludeSelector)
{
$I = $this;
// check for positive occurrence in exclude selector (optional)
// $I->see($text, $excludeSelector);
// detach the selected element
// Problem: append() just re-attaches the element, but this might not be the right position
$I->executeJs(
sprintf(
// s = subject, p = parent, bs = backup of subject
"var s = $(%s), p = s.parent(), bs = s.detach(); " .
"setTimeout(function() { p.append(bs); }, 2000);",
json_encode($excludeSelector)
)
);
// check for negative occurrence now
$I->dontSeeInPageSource($text);
// wait 2 seconds (re-attach timeout)
$I->wait(2);
}