forked from ScreenPyHQ/screenpy_playwright
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ScreenPyHQ#9 from ScreenPyHQ/add-attribute-question
Add Attribute Question.
- Loading branch information
Showing
9 changed files
with
174 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
"""Questions that can be asked using the Abilities in ScreenPy: Playwright.""" | ||
|
||
from .attribute import Attribute | ||
from .number import Number | ||
from .text import Text | ||
|
||
__all__ = [ | ||
"Attribute", | ||
"Number", | ||
"Text", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
"""Get the value of an HTML attribute on a Target.""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
from screenpy import UnableToAnswer | ||
|
||
if TYPE_CHECKING: | ||
from screenpy import Actor | ||
from typing_extensions import Self | ||
|
||
from ..target import Target | ||
|
||
|
||
class Attribute: | ||
"""Ask about the value of an HTML attribute on a Target. | ||
Abilities Required: | ||
:class:`~screenpy_playwright.abilities.BrowseTheWebSynchronously` | ||
Examples: | ||
the_actor.should( | ||
See.the( | ||
Attribute("aria-label").of_the(LOGIN_LINK), | ||
ContainsTheText("Log in to the application.") | ||
) | ||
) | ||
the_actor.attempts_to( | ||
MakeNote.of_the(Attribute("href").of_the(LOGIN_LINK).as_( | ||
"login link" | ||
), | ||
) | ||
""" | ||
|
||
target: Target | None | ||
|
||
def __init__(self, attribute: str) -> None: | ||
self.attribute = attribute | ||
self.target = None | ||
|
||
def describe(self) -> str: | ||
"""Describe the Question in present tense.""" | ||
return f'The "{self.attribute}" attribute of the {self.target}.' | ||
|
||
def of_the(self, target: Target) -> Self: | ||
"""Supply the Target to get the attribute from. | ||
Args: | ||
target: the Target to get the attribute from. | ||
""" | ||
self.target = target | ||
return self | ||
|
||
def answered_by(self, the_actor: Actor) -> str | None: | ||
"""Ask the Actor to get the value of the attribute. | ||
Args: | ||
the_actor: the Actor who will answer this Question. | ||
Returns: | ||
str | None: the value of the attribute. | ||
""" | ||
if self.target is None: | ||
msg = "No Target was provided! Supply one with .of_the()." | ||
raise UnableToAnswer(msg) | ||
|
||
return self.target.found_by(the_actor).get_attribute(self.attribute) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,99 @@ | ||
from screenpy import Actor, Answerable, Describable | ||
"""Tests for the Questions an Actor can ask using ScreenPy Playwright.""" | ||
|
||
from screenpy_playwright import Number, Text | ||
from unittest import mock | ||
|
||
from .useful_mocks import get_mocked_target_and_element | ||
import pytest | ||
from screenpy import Actor, Answerable, Describable, UnableToAnswer | ||
|
||
from screenpy_playwright import Attribute, BrowseTheWebSynchronously, Number, Text | ||
|
||
class TestNumber: | ||
from .useful_mocks import get_mock_target_class, get_mocked_target_and_locator | ||
|
||
FakeTarget = get_mock_target_class() | ||
TARGET = FakeTarget() | ||
|
||
|
||
class TestAttribute: | ||
def test_can_be_instantiated(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
a1 = Attribute("") | ||
a2 = Attribute("").of_the(TARGET) | ||
|
||
assert isinstance(a1, Attribute) | ||
assert isinstance(a2, Attribute) | ||
|
||
def test_implements_protocol(self) -> None: | ||
a = Attribute("") | ||
|
||
assert isinstance(a, Answerable) | ||
assert isinstance(a, Describable) | ||
|
||
def test_raises_error_if_no_target(self, Tester: Actor) -> None: | ||
with pytest.raises(UnableToAnswer): | ||
Attribute("").answered_by(Tester) | ||
|
||
def test_ask_for_attribute(self, Tester: Actor) -> None: | ||
attr = "foo" | ||
value = "bar" | ||
target, locator = get_mocked_target_and_locator() | ||
locator.get_attribute.return_value = value | ||
mocked_btws = Tester.ability_to(BrowseTheWebSynchronously) | ||
mocked_btws.current_page = mock.Mock() | ||
|
||
n = Number.of(target) | ||
assert Attribute(attr).of_the(target).answered_by(Tester) == value | ||
target.found_by.assert_called_once_with(Tester) | ||
locator.get_attribute.assert_called_once_with(attr) | ||
|
||
def test_describe(self) -> None: | ||
assert Attribute("foo").describe() == 'The "foo" attribute of the None.' | ||
|
||
|
||
class TestNumber: | ||
def test_can_be_instantiated(self) -> None: | ||
n = Number.of(TARGET) | ||
|
||
assert isinstance(n, Number) | ||
|
||
def test_implements_protocol(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
|
||
n = Number(target) | ||
n = Number(TARGET) | ||
|
||
assert isinstance(n, Answerable) | ||
assert isinstance(n, Describable) | ||
|
||
def test_describe(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
target = FakeTarget() | ||
target._description = "Somebody once told me" | ||
|
||
assert Number.of(target).describe() == f"The number of {target}." | ||
|
||
def test_ask_number(self, Tester: Actor) -> None: | ||
target, element = get_mocked_target_and_element() | ||
target, locator = get_mocked_target_and_locator() | ||
num_elements = 10 | ||
element.count.return_value = num_elements | ||
locator.count.return_value = num_elements | ||
|
||
assert Number.of(target).answered_by(Tester) == num_elements | ||
|
||
|
||
class TestText: | ||
def test_can_be_instantiated(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
|
||
t = Text.of_the(target) | ||
t = Text.of_the(TARGET) | ||
|
||
assert isinstance(t, Text) | ||
|
||
def test_implements_protocol(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
|
||
t = Text(target) | ||
t = Text(TARGET) | ||
|
||
assert isinstance(t, Answerable) | ||
assert isinstance(t, Describable) | ||
|
||
def test_describe(self) -> None: | ||
target, _ = get_mocked_target_and_element() | ||
target = FakeTarget() | ||
target._description = "the world is gonna roll me" | ||
|
||
assert Text.of_the(target).describe() == f"The text from the {target}." | ||
|
||
def test_ask_text(self, Tester: Actor) -> None: | ||
target, element = get_mocked_target_and_element() | ||
target, locator = get_mocked_target_and_locator() | ||
words = "Number 1, the larch." | ||
element.text_content.return_value = words | ||
locator.text_content.return_value = words | ||
|
||
assert Text.of_the(target).answered_by(Tester) == words |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters