-
-
Notifications
You must be signed in to change notification settings - Fork 69
add qmlbot #476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add qmlbot #476
Changes from all commits
0bc9a18
e3dcc0b
edd7257
24062d3
ccd6ce5
d55a3bb
dbc99ad
457f37f
ee69119
9383323
a8fa68c
59d5d7e
ac3a9bb
dd70ad8
716f4b8
02e9771
f2d0438
442e4b2
dca9399
bb9cb06
e472f83
ddd7cc9
355c377
e3dd1fc
4f783e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,3 +16,6 @@ src/pytest_qt.egg-info | |
|
|
||
| # auto-generated by setuptools_scm | ||
| /src/pytestqt/_version.py | ||
|
|
||
| # pycharm | ||
| .idea | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ pytest-qt | |
| virtual_methods | ||
| modeltester | ||
| qapplication | ||
| qmlbot | ||
| note_dialogs | ||
| debugging | ||
| troubleshooting | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| ========= | ||
| qmlbot | ||
| ========= | ||
|
|
||
| Fixture that helps interacting with QML. | ||
|
|
||
| Example - load qml from string: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| def test_say_hello(qmlbot): | ||
| qml = """ | ||
| import QtQuick 2.0 | ||
|
|
||
| Rectangle{ | ||
| objectName: "sample"; | ||
| property string hello: "world" | ||
| } | ||
| """ | ||
| item = qmlbot.loads(qml) | ||
| assert item.property("hello") == "world" | ||
|
|
||
|
|
||
| Example - load qml from file: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| from pathlib import Path | ||
|
|
||
|
|
||
| def test_say_hello(qmlbot): | ||
| item = qmlbot.load(Path("sayhello.qml")) | ||
| assert item.property("hello") == "world" | ||
|
|
||
| Note: if your components depends on any instances or ``@QmlElement``'s you need | ||
| to make sure it is acknowledge by ``qmlbot.engine`` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,8 @@ | ||
| # _version is automatically generated by setuptools_scm | ||
| from pytestqt._version import version | ||
|
|
||
| from .qml.qmlbot import QmlBot | ||
|
|
||
| __version__ = version | ||
|
|
||
| __all__ = ["QmlBot", "__version__"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import QtQuick 2.15 | ||
nrbnlulu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import QtQuick.Window 2.15 | ||
|
|
||
| Window { | ||
| id: root | ||
| width: 500 | ||
| height: 400 | ||
| visible: true | ||
|
|
||
|
|
||
| Item { | ||
| anchors.fill: parent | ||
| Loader { | ||
| objectName: "contentloader" | ||
| source: "" | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import os | ||
| from pathlib import Path | ||
| from typing import Any | ||
|
|
||
| from pytestqt.qt_compat import qt_api | ||
|
|
||
|
|
||
| class QmlBot: | ||
nrbnlulu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| def __init__(self) -> None: | ||
| self.engine = qt_api.QtQml.QQmlApplicationEngine() | ||
| main = Path(__file__).parent / "botloader.qml" | ||
| self.engine.load(os.fspath(main)) | ||
|
|
||
| @property | ||
| def _loader(self) -> Any: | ||
| self._root = self.engine.rootObjects()[ | ||
| 0 | ||
| ] # self is needed for it not to be collected by the gc | ||
| return self._root.findChild(qt_api.QtQuick.QQuickItem, "contentloader") | ||
|
|
||
| def load(self, path: Path) -> Any: | ||
| """ | ||
| :returns: `QQuickItem` - the initialized component | ||
| """ | ||
| self._loader.setProperty( | ||
| "source", qt_api.QtCore.QUrl(path.resolve(True).as_uri()) | ||
| ) | ||
| return self._loader.property("item") | ||
|
|
||
| def loads(self, content: str) -> Any: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI decided to drop the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, that is not the same. qml files can import other qml files based on relative path.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I follow, what does the fact that "qml files can import other qml files" relates to being able to load a qml file passing a Feel free to add it back, I removed because it seemed redundant and it the test was failing, but if it is not redundant we can revisit this.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you could though pass the pass in the url here
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In QML you can every file encapsulates a import QtQuick
MyApp{}and if i.e import QtQuick
import "impl"
MyApp{}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh on CI it is showing the same error I got locally:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are you on windows?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. 👍 |
||
| """ | ||
| :returns: `QQuickItem` - the initialized component | ||
| """ | ||
| self._comp = qt_api.QtQml.QQmlComponent( | ||
| self.engine | ||
| ) # needed for it not to be collected by the gc | ||
| self._comp.setData(content.encode("utf-8"), qt_api.QtCore.QUrl()) | ||
| if self._comp.status() != qt_api.QtQml.QQmlComponent.Status.Ready: | ||
| raise RuntimeError( | ||
| f"component {self._comp} is not Ready:\n" | ||
| f"STATUS: {self._comp.status()}\n" | ||
| f"HINT: make sure there are no wrong spaces.\n" | ||
| f"ERRORS: {self._comp.errors()}" | ||
| ) | ||
| self._loader.setProperty("source", "") | ||
| self._loader.setProperty("sourceComponent", self._comp) | ||
| return self._loader.property("item") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import QtQuick 2.0 | ||
|
|
||
| Rectangle{ | ||
| objectName: "sample"; | ||
| property string hello: "world" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| from pathlib import Path | ||
| from textwrap import dedent | ||
|
|
||
| import pytest | ||
|
|
||
| from pytestqt import QmlBot | ||
|
|
||
|
|
||
| def test_load_from_string_wrong_syntax(qmlbot: QmlBot) -> None: | ||
| qml = "import QtQuick 2.0 Rectangle{" | ||
| with pytest.raises(RuntimeError): | ||
| qmlbot.loads(qml) | ||
|
|
||
|
|
||
| def test_load_from_string(qmlbot: QmlBot) -> None: | ||
| text = "that's a template!" | ||
| qml = dedent( | ||
| """ | ||
| import QtQuick 2.0 | ||
|
|
||
| Rectangle{ | ||
| objectName: "sample"; | ||
| property string hello: "%s" | ||
| } | ||
| """ | ||
| % text | ||
| ) | ||
| item = qmlbot.loads(qml) | ||
| assert item.property("hello") == text | ||
|
|
||
|
|
||
| def test_load_from_file(qmlbot: QmlBot) -> None: | ||
| item = qmlbot.load(Path(__file__).parent / "sample.qml") | ||
| assert item.property("hello") == "world" |
Uh oh!
There was an error while loading. Please reload this page.