diff --git a/.gitignore b/.gitignore index 764b603..3237ee9 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ venv app.db microblog.log* .env +.idea/ \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 19bf6f0..eb2bdb1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -33,12 +33,12 @@ pipeline { post { success { echo 'Pipeline has completed' - discordSend description: '', footer: '', image: '', link: 'http://3.238.108.178:8080/', result: '', scmWebUrl: '', thumbnail: '', title: + discordSend description: '', footer: '', image: '', link: 'http://3.220.122.102:8080/', result: '', scmWebUrl: '', thumbnail: '', title: 'Pipeline has completed ✅', webhookURL: 'https://discord.com/api/webhooks/1075879011667955872/Nk0gmKZkrISEs-hru-HjtzzgezWweABCdPsOKGIzkmj5xMcqKC3m1-dx7GZSu0yURAOo' } failure { echo 'Something has failed!' - discordSend description: 'Pipeline has failed!', footer: '', image: '', link: 'http://3.238.108.178:8080/', result: '', scmWebUrl: '', thumbnail: '', title: + discordSend description: 'Pipeline has failed!', footer: '', image: '', link: 'http://3.220.122.102:8080/', result: '', scmWebUrl: '', thumbnail: '', title: 'Pipeline failure ❌', webhookURL: 'https://discord.com/api/webhooks/1075879011667955872/Nk0gmKZkrISEs-hru-HjtzzgezWweABCdPsOKGIzkmj5xMcqKC3m1-dx7GZSu0yURAOo' } } diff --git a/README.md b/README.md index 82e3e48..c0567b3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,32 @@ # Welcome to Microblog! This is an example application featured in my [Flask Mega-Tutorial](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world). See the tutorial for instructions on how to work with it. + +# How to run behave tutorial + +*NOTE* behave steps in the .feature file MUST unicode match those in the 'steps' file + +e.g. in the *.feature file there is a Gherkin line like +'the task 'Buy groceries' with estimate '2' should be added to the todo list' + +then in the accompanying *step.py file it must follow the exact unicode in the behave decorator +Like this -> '@then("the task '{title}' with estimate '{estimate}' should be added to the todo list")' + + +Also step files must follow the regex *step.py + +1. Running all behave features + +run " behave tests/features/add-task.feature " + +# How to run unit tests + +unit tests must follow the "test*.py" regex to be picked up + +1. Individual tests + +run " python ./ests/unit/test_example.py " + +2. Run all unit tests + +run " python -m unittest discover -s ./tests/unit " \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt index eb4d95f..3269b02 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,6 +44,9 @@ requests==2.25.1 requests-toolbelt==0.9.1 rq==1.9.0 selenium==4.4.1 +selenium +behave +webdriver_manager six==1.16.0 sniffio==1.3.0 sortedcontainers==2.4.0 diff --git a/selenium.py b/selenium.py deleted file mode 100644 index a363491..0000000 --- a/selenium.py +++ /dev/null @@ -1,4 +0,0 @@ -from selenium import webdriver - -driver = webdriver.chrome() -driver.get("http://www.python.org") diff --git a/tests/features/add-task.feature b/tests/features/add-task.feature new file mode 100644 index 0000000..3e1c284 --- /dev/null +++ b/tests/features/add-task.feature @@ -0,0 +1,17 @@ +Feature: Add tasks to todo list + As a user + I want to be able to add tasks to my todo list + So thats I can keep track of my work + + Scenario: User visits the todo list page + Given the user is on the todo list page + Then the page should have a text field to enter the title of the task + And the page should have a text field to enter the estimate of hours needed to complete the task + And the page should have a button to add the task + + Scenario: Add a new task to the todo list + Given I am on the todo list page + When I enter 'Buy groceries' in the title field + And I enter '2' in the estimate field + And I click the 'Add' button + Then the task 'Buy groceries' with estimate '2' should be added to the todo list \ No newline at end of file diff --git a/tests/features/steps/add-task-steps.py b/tests/features/steps/add-task-steps.py new file mode 100644 index 0000000..4fa5cf2 --- /dev/null +++ b/tests/features/steps/add-task-steps.py @@ -0,0 +1,54 @@ +from behave import given, when, then +from webdriver_manager.chrome import ChromeDriverManager +from selenium import webdriver +from selenium.webdriver.chrome.service import Service as ChromeService +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.options import Options + +#THESE ARE EXAMPLES FILES. +#Todo delete these once we set a standard with our own tests + +@given("I am on the todo list page") +def open_browser(context): + + # Implementation of headless from https://stackoverflow.com/questions/46920243/how-to-configure-chromedriver-to-initiate-chrome-browser-in-headless-mode-throug + # Stackoverflow post desribes what is goin on with options to enable headless chrome + + options = Options() + options.add_argument("--headless") # Runs Chrome in headless mode. + options.add_argument('--no-sandbox') # Bypass OS security model + options.add_argument('start-maximized') #to maximize viewport this should still be headless + options.add_argument('disable-infobars') + options.add_argument("--disable-extensions") + context.driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install())) + context.driver.implicitly_wait(5) + context.driver.get("http://127.0.0.1:5000/") + + +@when("I enter '{title}' in the title field") +def step_impl(context, title): + title_field = context.driver.find_element(By.NAME, "title") + title_field.send_keys(title) + + +@when("I enter '{estimate}' in the estimate field") +def step_impl(context, estimate): + estimate_field = context.driver.find_element(By.NAME, "estimate") + estimate_field.send_keys(estimate) + + +@when("I click the 'Add' button") +def step_impl(context): + add_button = context.driver.find_element(By.XPATH, "//button[contains(text(),'Add')]") + add_button.click() + context.driver.implicitly_wait(5) + + +@then("the task '{title}' with estimate '{estimate}' should be added to the todo list") +def step_impl(context, title, estimate): + dump_text = context.driver.page_source + print(dump_text) + assert ("Buy groceries | 2" in dump_text) is True + + + diff --git a/tests/features/steps/check-ui-steps.py b/tests/features/steps/check-ui-steps.py new file mode 100644 index 0000000..1f07681 --- /dev/null +++ b/tests/features/steps/check-ui-steps.py @@ -0,0 +1,39 @@ +from behave import given, when, then +from webdriver_manager.chrome import ChromeDriverManager +from selenium import webdriver +from selenium.webdriver.chrome.service import Service as ChromeService +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.options import Options + +#THESE ARE EXAMPLES FILES. +#Todo delete these once we set a standard with our own tests + +@given("the user is on the todo list page") +def open_browser(context): + options = Options() + options.add_argument("--headless") # Runs Chrome in headless mode. + options.add_argument('--no-sandbox') # Bypass OS security model + options.add_argument('start-maximized') #to maximize viewport this should still be headless + options.add_argument('disable-infobars') + options.add_argument("--disable-extensions") + context.driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install())) + context.driver.implicitly_wait(5) + context.driver.get("http://127.0.0.1:5000/") + + +@then("the page should have a text field to enter the title of the task") +def check_task_title_textbox(context): + status = context.driver.find_element(By.NAME, "title").is_displayed() + assert status is True + + +@then("the page should have a text field to enter the estimate of hours needed to complete the task") +def check_task_estimate_textbox(context): + status = context.driver.find_element(By.NAME, "estimate").is_displayed() + assert status is True + + +@then("the page should have a button to add the task") +def check_task_add_button(context): + status = context.driver.find_element(By.XPATH, "//button[contains(text(),'Add')]").is_displayed() + assert status is True diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests.py b/tests/unit/test_example.py old mode 100755 new mode 100644 similarity index 99% rename from tests.py rename to tests/unit/test_example.py index 52111b1..fb9827f --- a/tests.py +++ b/tests/unit/test_example.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +import sys +sys.path.append('./') + from datetime import datetime, timedelta import unittest from app import create_app, db