Skip to content
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

Dev ivan #28

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions functional_tests/functional_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions

import time

from django.contrib.staticfiles.testing import StaticLiveServerTestCase


MAX_WAIT = 10


class NewVisitorTest(StaticLiveServerTestCase):

def setUp(self):
self.browser = webdriver.Firefox()

def tearDown(self):
self.browser.quit()

def wait_for_row_in_list_table(self, row_text):
start_time = time.time()
while True:
try:
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
self.assertIn(row_text, [row.text for row in rows])
return
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)

def test_can_start_a_list_and_retrieve_it_later(self):
# Edith has heard about a cool new online to-do app. She goes
# to check out its homepage
self.browser.get(self.live_server_url)

# She notices the page title and header mention to-do lists
self.assertIn('To-Do', self.browser.title)
header_text = self.browser.find_element_by_tag_name('h1').text
self.assertIn('To-Do', header_text)

# She is invited to enter a to-do item straight away
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertEqual(
inputbox.get_attribute('placeholder'),
'Enter a to-do item'
)

# She types "Buy peacock feathers" into a text box (Edith's hobby
# is tying fly-fishing lures)
inputbox.send_keys('Buy peacock feathers')

# When she hits enter, the page updates, and now the page lists
# "1: Buy peacock feathers" as an item in a to-do list table
inputbox.send_keys(Keys.ENTER)
WebDriverWait(self.browser, 10).until(
expected_conditions.text_to_be_present_in_element(
(By.ID, 'id_list_table'), 'Buy peacock feathers'))

self.wait_for_row_in_list_table('1: Buy peacock feathers')

# There is still a text box inviting her to add another item. She
# enters "Use peacock feathers to make a fly" (Edith is very
# methodical)
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Use peacock feathers to make a fly')
inputbox.send_keys(Keys.ENTER)

# The page updates again, and now shows both items on her list
self.wait_for_row_in_list_table(
'2: Use peacock feathers to make a fly'
)
self.wait_for_row_in_list_table('1: Buy peacock feathers')

# Edith wonders whether the site will remember her list. Then she sees
# that the site has generated a unique URL for her -- there is some
# explanatory text to that effect.

def test_multiple_users_can_start_lists_at_different_urls(self):
# Edith start a new todo list
self.browser.get(self.live_server_url)
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: Buy peacock feathers')

# She notices that her list has a unique URL
edith_list_url = self.browser.current_url
self.assertRegex(edith_list_url, '/lists/.+')

# Now a new user, Francis, comes along to the site.

# We use a new browser session to make sure that no information
# of Edith's is coming through from cookies etc
self.browser.quit()
self.browser = webdriver.Firefox()

# Francis visits the home page. There is no sign of Edith's
# list
self.browser.get(self.live_server_url)
page_text = self.browser.find_element_by_tag_name('body').text
self.assertNotIn('Buy peacock feathers', page_text)
self.assertNotIn('make a fly', page_text)

# Francis starts a new list by entering a new item. He
# is less interesting than Edith...
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Buy milk')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: Buy milk')

# Francis gets his own unique URL
francis_list_url = self.browser.current_url
self.assertRegex(francis_list_url, '/lists/.+')
self.assertNotEqual(francis_list_url, edith_list_url)

# Again, there is no trace of Edith's list
page_text = self.browser.find_element_by_tag_name('body').text
self.assertNotIn('Buy peacock feathers', page_text)
self.assertIn('Buy milk', page_text)

def test_layout_and_styling(self):
# Edith goes to the home page
self.browser.get(self.live_server_url)
self.browser.set_window_size(1024, 768)

# She notices the input box is nicely centered
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertAlmostEqual(
inputbox.location['x'] + inputbox.size['width'] / 2,
512,
delta=5
)

# She starts a new list and sees the input is nicely
# centered there too
inputbox.send_keys('testing')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: testing')
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertAlmostEqual(
inputbox.location['x'] + inputbox.size['width'] / 2,
512,
delta=5
)
Empty file added lists/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions lists/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin
from lists.models import Item, List

admin.site.register(Item)
admin.site.register(List)
6 changes: 6 additions & 0 deletions lists/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ListsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "lists"
27 changes: 27 additions & 0 deletions lists/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.1.3 on 2022-11-23 14:29

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []

operations = [
migrations.CreateModel(
name="Item",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
),
]
19 changes: 19 additions & 0 deletions lists/migrations/0002_item_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.1.3 on 2022-11-23 14:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("lists", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="item",
name="text",
field=models.TextField(default="test"),
preserve_default=False,
),
]
18 changes: 18 additions & 0 deletions lists/migrations/0003_alter_item_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.1.3 on 2022-11-23 14:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("lists", "0002_item_text"),
]

operations = [
migrations.AlterField(
model_name="item",
name="text",
field=models.TextField(blank=True),
),
]
42 changes: 42 additions & 0 deletions lists/migrations/0004_list_alter_item_text_item_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 4.1.3 on 2022-11-24 14:41

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("lists", "0003_alter_item_text"),
]

operations = [
migrations.CreateModel(
name="List",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
),
migrations.AlterField(
model_name="item",
name="text",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="item",
name="list",
field=models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="lists.list",
),
),
]
Empty file added lists/migrations/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions lists/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.db import models


class List(models.Model):
pass


class Item(models.Model):
text = models.TextField(default='')
list = models.ForeignKey(List, default=None, on_delete=models.CASCADE)
40 changes: 40 additions & 0 deletions lists/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>To-Do lists</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3 jumbotron">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
<input name="item_text" id="id_new_item"
class="form-control input-lg"
placeholder="Enter a to-do item"
/>
{% csrf_token %}
</form>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>

</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions lists/templates/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends 'base.html' %}

{% block header_text %}Start a new To-Do list{% endblock %}

{% block form_action %}/lists/new{% endblock %}
13 changes: 13 additions & 0 deletions lists/templates/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends 'base.html' %}

{% block header_text %}Your To-Do list{% endblock %}

{% block form_action %}/lists/{{ list.id }}/add_item{% endblock %}

{% block table %}
<table id="id_list_table" class="table">
{% for item in list.item_set.all %}
<tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr>
{% endfor %}
</table>
{% endblock %}
Loading