Skip to content

Commit baa6ec8

Browse files
authored
chore: add todomvc example (#1523)
1 parent 5066b70 commit baa6ec8

14 files changed

+538
-1
lines changed

.github/workflows/ci.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,22 @@ jobs:
193193
run: conda install conda-build conda-verify
194194
- name: Build
195195
run: conda build .
196+
197+
test_examples:
198+
name: Examples
199+
runs-on: ubuntu-22.04
200+
defaults:
201+
run:
202+
working-directory: examples/todomvc/
203+
steps:
204+
- uses: actions/checkout@v3
205+
- name: Set up Python
206+
uses: actions/setup-python@v4
207+
with:
208+
python-version: '3.10'
209+
- name: Install dependencies & browsers
210+
run: |
211+
pip install -r requirements.txt
212+
python -m playwright install --with-deps chromium
213+
- name: Common Tests
214+
run: pytest

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ repos:
2323
hooks:
2424
- id: mypy
2525
additional_dependencies: [types-pyOpenSSL==21.0.3]
26+
exclude: examples/
2627
- repo: https://github.com/pycqa/flake8
2728
rev: 5.0.4
2829
hooks:

examples/todomvc/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest-playwright==0.3.0

examples/todomvc/tests/__init__.py

Whitespace-only changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from typing import Generator
2+
3+
import pytest
4+
5+
from playwright.sync_api import Page, expect
6+
7+
from .utils import TODO_ITEMS, create_default_todos
8+
9+
10+
@pytest.fixture(autouse=True)
11+
def run_around_tests(page: Page) -> Generator[None, None, None]:
12+
# setup before a test
13+
page.goto("https://demo.playwright.dev/todomvc")
14+
create_default_todos(page)
15+
# run the actual test
16+
yield
17+
# run any cleanup code
18+
19+
20+
def test_should_display_the_correct_text(page: Page) -> None:
21+
page.locator(".todo-list li .toggle").first.check()
22+
expect(page.locator(".clear-completed")).to_have_text("Clear completed")
23+
24+
25+
def test_should_clear_completed_items_when_clicked(page: Page) -> None:
26+
todo_items = page.locator(".todo-list li")
27+
todo_items.nth(1).locator(".toggle").check()
28+
page.locator(".clear-completed").click()
29+
expect(todo_items).to_have_count(2)
30+
expect(todo_items).to_have_text([TODO_ITEMS[0], TODO_ITEMS[2]])
31+
32+
33+
def test_should_be_hidden_when_there_are_no_items_that_are_completed(
34+
page: Page,
35+
) -> None:
36+
page.locator(".todo-list li .toggle").first.check()
37+
page.locator(".clear-completed").click()
38+
expect(page.locator(".clear-completed")).to_be_hidden()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from typing import Generator
2+
3+
import pytest
4+
5+
from playwright.sync_api import Page, expect
6+
7+
from .utils import TODO_ITEMS, assert_number_of_todos_in_local_storage
8+
9+
10+
@pytest.fixture(autouse=True)
11+
def run_around_tests(page: Page) -> Generator[None, None, None]:
12+
# setup before a test
13+
page.goto("https://demo.playwright.dev/todomvc")
14+
# run the actual test
15+
yield
16+
# run any cleanup code
17+
18+
19+
def test_should_display_the_current_number_of_todo_items(page: Page) -> None:
20+
page.locator(".new-todo").fill(TODO_ITEMS[0])
21+
page.locator(".new-todo").press("Enter")
22+
expect(page.locator(".todo-count")).to_contain_text("1")
23+
24+
page.locator(".new-todo").fill(TODO_ITEMS[1])
25+
page.locator(".new-todo").press("Enter")
26+
expect(page.locator(".todo-count")).to_contain_text("2")
27+
28+
assert_number_of_todos_in_local_storage(page, 2)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from typing import Generator
2+
3+
import pytest
4+
5+
from playwright.sync_api import Page, expect
6+
7+
from .utils import (
8+
TODO_ITEMS,
9+
assert_number_of_todos_in_local_storage,
10+
check_todos_in_local_storage,
11+
create_default_todos,
12+
)
13+
14+
15+
@pytest.fixture(autouse=True)
16+
def run_around_tests(page: Page) -> Generator[None, None, None]:
17+
# setup before a test
18+
page.goto("https://demo.playwright.dev/todomvc")
19+
create_default_todos(page)
20+
assert_number_of_todos_in_local_storage(page, 3)
21+
# run the actual test
22+
yield
23+
# run any cleanup code
24+
25+
26+
def test_should_hide_other_controls_when_editing(page: Page) -> None:
27+
todo_item = page.locator(".todo-list li").nth(1)
28+
todo_item.dblclick()
29+
expect(todo_item.locator(".toggle")).not_to_be_visible()
30+
expect(todo_item.locator("label")).not_to_be_visible()
31+
assert_number_of_todos_in_local_storage(page, 3)
32+
33+
34+
def test_should_save_edits_on_blur(page: Page) -> None:
35+
todo_items = page.locator(".todo-list li")
36+
todo_items.nth(1).dblclick()
37+
todo_items.nth(1).locator(".edit").fill("buy some sausages")
38+
todo_items.nth(1).locator(".edit").dispatch_event("blur")
39+
40+
expect(todo_items).to_have_text(
41+
[
42+
TODO_ITEMS[0],
43+
"buy some sausages",
44+
TODO_ITEMS[2],
45+
]
46+
)
47+
check_todos_in_local_storage(page, "buy some sausages")
48+
49+
50+
def test_should_trim_entered_text(page: Page) -> None:
51+
todo_items = page.locator(".todo-list li")
52+
todo_items.nth(1).dblclick()
53+
todo_items.nth(1).locator(".edit").fill(" buy some sausages ")
54+
todo_items.nth(1).locator(".edit").press("Enter")
55+
56+
expect(todo_items).to_have_text(
57+
[
58+
TODO_ITEMS[0],
59+
"buy some sausages",
60+
TODO_ITEMS[2],
61+
]
62+
)
63+
check_todos_in_local_storage(page, "buy some sausages")
64+
65+
66+
def test_should_remove_the_item_if_an_empty_text_string_was_entered(page: Page) -> None:
67+
todo_items = page.locator(".todo-list li")
68+
todo_items.nth(1).dblclick()
69+
todo_items.nth(1).locator(".edit").fill("")
70+
todo_items.nth(1).locator(".edit").press("Enter")
71+
72+
expect(todo_items).to_have_text(
73+
[
74+
TODO_ITEMS[0],
75+
TODO_ITEMS[2],
76+
]
77+
)
78+
79+
80+
def test_should_cancel_edits_on_escape(page: Page) -> None:
81+
todo_items = page.locator(".todo-list li")
82+
todo_items.nth(1).dblclick()
83+
todo_items.nth(1).locator(".edit").press("Escape")
84+
expect(todo_items).to_have_text(TODO_ITEMS)

examples/todomvc/tests/test_item.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from typing import Generator
2+
3+
import pytest
4+
5+
from playwright.sync_api import Page, expect
6+
7+
from .utils import (
8+
TODO_ITEMS,
9+
check_number_of_completed_todos_in_local_storage,
10+
check_todos_in_local_storage,
11+
create_default_todos,
12+
)
13+
14+
15+
@pytest.fixture(autouse=True)
16+
def run_around_tests(page: Page) -> Generator[None, None, None]:
17+
# setup before a test
18+
page.goto("https://demo.playwright.dev/todomvc")
19+
# run the actual test
20+
yield
21+
# run any cleanup code
22+
23+
24+
def test_should_allow_me_to_mark_items_as_completed(page: Page) -> None:
25+
# Create two items.
26+
for item in TODO_ITEMS[:2]:
27+
page.locator(".new-todo").fill(item)
28+
page.locator(".new-todo").press("Enter")
29+
30+
# Check first item.
31+
firstTodo = page.locator(".todo-list li").nth(0)
32+
firstTodo.locator(".toggle").check()
33+
expect(firstTodo).to_have_class("completed")
34+
35+
# Check second item.
36+
secondTodo = page.locator(".todo-list li").nth(1)
37+
expect(secondTodo).not_to_have_class("completed")
38+
secondTodo.locator(".toggle").check()
39+
40+
# Assert completed class.
41+
expect(firstTodo).to_have_class("completed")
42+
expect(secondTodo).to_have_class("completed")
43+
44+
45+
def test_should_allow_me_to_un_mark_items_as_completed(page: Page) -> None:
46+
# Create two items.
47+
for item in TODO_ITEMS[:2]:
48+
page.locator(".new-todo").fill(item)
49+
page.locator(".new-todo").press("Enter")
50+
51+
firstTodo = page.locator(".todo-list li").nth(0)
52+
secondTodo = page.locator(".todo-list li").nth(1)
53+
firstTodo.locator(".toggle").check()
54+
expect(firstTodo).to_have_class("completed")
55+
expect(secondTodo).not_to_have_class("completed")
56+
check_number_of_completed_todos_in_local_storage(page, 1)
57+
58+
firstTodo.locator(".toggle").uncheck()
59+
expect(firstTodo).not_to_have_class("completed")
60+
expect(secondTodo).not_to_have_class("completed")
61+
check_number_of_completed_todos_in_local_storage(page, 0)
62+
63+
64+
def test_should_allow_me_to_edit_an_item(page: Page) -> None:
65+
create_default_todos(page)
66+
67+
todo_items = page.locator(".todo-list li")
68+
secondTodo = todo_items.nth(1)
69+
secondTodo.dblclick()
70+
expect(secondTodo.locator(".edit")).to_have_value(TODO_ITEMS[1])
71+
secondTodo.locator(".edit").fill("buy some sausages")
72+
secondTodo.locator(".edit").press("Enter")
73+
74+
# Explicitly assert the new text value.
75+
expect(todo_items).to_have_text([TODO_ITEMS[0], "buy some sausages", TODO_ITEMS[2]])
76+
check_todos_in_local_storage(page, "buy some sausages")
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from typing import Generator
2+
3+
import pytest
4+
5+
from playwright.sync_api import Page, expect
6+
7+
from .utils import (
8+
assert_number_of_todos_in_local_storage,
9+
check_number_of_completed_todos_in_local_storage,
10+
create_default_todos,
11+
)
12+
13+
14+
@pytest.fixture(autouse=True)
15+
def run_around_tests(page: Page) -> Generator[None, None, None]:
16+
# setup before a test
17+
page.goto("https://demo.playwright.dev/todomvc")
18+
# run the actual test
19+
yield
20+
# run any cleanup code
21+
22+
23+
def test_should_allow_me_to_mark_all_items_as_completed(page: Page) -> None:
24+
create_default_todos(page)
25+
assert_number_of_todos_in_local_storage(page, 3)
26+
# Complete all todos.
27+
page.locator(".toggle-all").check()
28+
29+
# Ensure all todos have 'completed' class.
30+
expect(page.locator(".todo-list li")).to_have_class(
31+
["completed", "completed", "completed"]
32+
)
33+
check_number_of_completed_todos_in_local_storage(page, 3)
34+
assert_number_of_todos_in_local_storage(page, 3)
35+
36+
37+
def test_should_allow_me_to_clear_the_complete_state_of_all_items(page: Page) -> None:
38+
create_default_todos(page)
39+
assert_number_of_todos_in_local_storage(page, 3)
40+
# Check and then immediately uncheck.
41+
page.locator(".toggle-all").check()
42+
page.locator(".toggle-all").uncheck()
43+
44+
# Should be no completed classes.
45+
expect(page.locator(".todo-list li")).to_have_class(["", "", ""])
46+
assert_number_of_todos_in_local_storage(page, 3)
47+
48+
49+
def test_complete_all_checkbox_should_update_state_when_items_are_completed_or_cleared(
50+
page: Page,
51+
) -> None:
52+
create_default_todos(page)
53+
assert_number_of_todos_in_local_storage(page, 3)
54+
toggleAll = page.locator(".toggle-all")
55+
toggleAll.check()
56+
expect(toggleAll).to_be_checked()
57+
check_number_of_completed_todos_in_local_storage(page, 3)
58+
59+
# Uncheck first todo.
60+
firstTodo = page.locator(".todo-list li").nth(0)
61+
firstTodo.locator(".toggle").uncheck()
62+
63+
# Reuse toggleAll locator and make sure its not checked.
64+
expect(toggleAll).not_to_be_checked()
65+
66+
firstTodo.locator(".toggle").check()
67+
check_number_of_completed_todos_in_local_storage(page, 3)
68+
69+
# Assert the toggle all is checked again.
70+
expect(toggleAll).to_be_checked()
71+
assert_number_of_todos_in_local_storage(page, 3)

0 commit comments

Comments
 (0)