diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e69de29bb diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..fbf9358b0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,14 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.c text +*.h text + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..ac4a657d4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.8.2-alpine + +WORKDIR /src/app/ + +COPY ./requirements.txt . + +RUN ["pip", "install", "-r", "./requirements.txt"] + +COPY . . + +RUN addgroup -S projects && adduser -S -H projects -G projects +RUN chown -R projects:projects /src/app +USER projects diff --git a/README.md b/README.md index d9cca4f37..798fcf313 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Once that completes, also run this command from the same folder. Windows ``` -\venv\Scripts\activate.bat +venv\Scripts\activate.bat ``` macOS & Linux @@ -46,4 +46,4 @@ Every time you want to check your work locally you can type that command, and it ### Previewing Your Work -You can preview your work by running `flask run` in the root of your fork and then visit`http://localhost:5000` in your browser. \ No newline at end of file +You can preview your work by running `flask run` in the root of your fork and then visit`http://localhost:5000` in your browser. diff --git a/jobs/app.py b/jobs/app.py index e69de29bb..d653336da 100644 --- a/jobs/app.py +++ b/jobs/app.py @@ -0,0 +1,37 @@ +from flask import Flask, render_template, g +import sqlite3 + +PATH = 'db/jobs.sqlite' +app = Flask(__name__) # __name__ determines the root path of the app. + + +def open_connection(): + connection = getattr(g, '_connection', None) + if connection is None: + connection = g._connection = sqlite3.connect(PATH) + connection.row_factory = sqlite3.Row + return connection + + +def execute_sql(sql, values: tuple = (), commit: bool = False, single: bool = False): + connection = open_connection() + cursor = connection.execute(sql, values) + if commit: + results = connection.commit() + else: + results = cursor.fetchone() if single else cursor.fetchall() + cursor.close() + return results + + +@app.teardown_appcontext +def close_connection(exception=None): + connection = getattr(g, '_connection', None) + if connection is not None: + connection.close() + + +@app.route('/') +@app.route('/jobs') +def jobs(): + return render_template('index.html') diff --git a/jobs/templates/__init__.py b/jobs/templates/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/jobs/templates/index.html b/jobs/templates/index.html new file mode 100644 index 000000000..bf14680d3 --- /dev/null +++ b/jobs/templates/index.html @@ -0,0 +1,5 @@ +{% extends "layout.html" %} + +{% block content %} +
` tag with a class of `card_header_title`.
-- Add an `` tag with an `href` of `{{ url_for('job', job_id=job['id']) }}`.
-- The content should be `{{ job['title'] }}`.
+- Add an `` tag with an `href` of `{{ url_for('job', job_id=job['id']) }}`.
+- The content should be `{{ job['title'] }}`.
-### 4.5 - Show Job Macro Body
+## 4.5 - Show Job Macro Body
-@pytest.mark.show_job_macro_body Next find the ` ` tag.
+@pytest.mark.show_job_macro_body Next find the ` ` tag.
In ` ` tag add the following:
-- `` tag with an `href` of `{{ url_for('employer', employer_id=job['employer_id']) }}`. The content should be `{{ job['employer_name'] }}`.
+- `` tag with an `href` of `{{ url_for('employer', employer_id=job['employer_id']) }}`. The content should be `{{ job['employer_name'] }}`.
- Line break
-- ${{ job['salary'] }}
+- ${{ job['salary'] }}
- Line break
- {{ job['description'] }}
-### 4.6 - Show Jobs Macro Definition
+## 4.6 - Show Jobs Macro Definition
@pytest.mark.show_jobs_macro_definition In `_macros.html` create a template macro using the `macro` tag call it `show_jobs`. `show_jobs` should take one parameter called `jobs`. Don't forgot to end the macro.
-### 4.7 - Show Jobs Macro For Loop
+## 4.7 - Show Jobs Macro For Loop
@pytest.mark.show_jobs_macro_for_loop Still in `_macros.html` and in the body of the `show_jobs` macro add the following HTML:
- Add a ` ` with the content {{ employer['description'] }}
-### 6.3 - Employer Template All Jobs
+## 6.3 - Employer Template All Jobs
@pytest.mark.employer_template_all_jobs Below the `` with the copied HTML structure.
-### 4.11 - Display All Jobs
+## 4.11 - Display All Jobs
@pytest.mark.display_all_jobs In the `index.html` template above the `{% endblock %}` add a call to the `show_jobs` macro passing in the argument `jobs`.
-### 4.12 - Gather All Jobs
+## 4.12 - Gather All Jobs
-@pytest.mark.app_jobs_route_jobs In `app.py` locate the `jobs` function.
+@pytest.mark.app_jobs_route_jobs In `app.py` locate the `jobs` function.
Above the `render_template` function, call the `execute_sql` function:
-- Pass in the SQL statement: `'SELECT job.id, job.title, job.description, job.salary, employer.id as employer_id, employer.name as employer_name FROM job JOIN employer ON employer.id = job.employer_id'`.
-- Assign the results of the call to a variable called `jobs`.
+- Pass in the SQL statement: `'SELECT job.id, job.title, job.description, job.salary, employer.id as employer_id, employer.name as employer_name FROM job JOIN employer ON employer.id = job.employer_id'`.
+- Assign the results of the call to a variable called `jobs`.
- In the `render_template` function, pass a keyword argument of `jobs=jobs`.
-### Preview Module 4
+**Preview**
At this point you can see all jobs on the homepage:
- Open a terminal at the root of the project
-- Run the command `flask run`.
-- Open a browser and navigate to the URL: `http://localhost:5000`.
+- Run the command `flask run`.
+- Open a browser and navigate to the URL: `http://localhost:5000`.
**Note: Appending `/jobs` should display the same page.**
-## Module 05 - Display Individual Jobs
+# Module 05 - Display Individual Jobs
-### 5.1 - Job Template
+## 5.1 - Job Template
-@pytest.mark.app_job_template We need a template to display an individual job. Create a new file called `job.html` in the `template` folder.
+@pytest.mark.app_job_template We need a template to display an individual job. Create a new file called `job.html` in the `template` folder.
-In the file use an `extends` template tag to inherit `layout.html`.
+In the file use an `extends` template tag to inherit `layout.html`.
After the `extends` tag add a template `block` called `content`. In the block call the `show_job` macro passing in `job`. **Note: Use the `{{}}` for the macro call.**
-### 5.2 - Job Route Function
+## 5.2 - Job Route Function
@pytest.mark.app_job_route In `app.py` create a function called `job`. In the body return a call to the `render_template` function passing in the newly created `job.html` template.
-### 5.3 - Job Route Decorator
+## 5.3 - Job Route Decorator
-@pytest.mark.app_job_route_decorator We only need one job from the database, we will use the `execute_sql` function passing in a query with a where clause. In the where clause we will need a `job_id`. We are going to get this from the URL.
+@pytest.mark.app_job_route_decorator We only need one job from the database, we will use the `execute_sql` function passing in a query with a where clause. In the where clause we will need a `job_id`. We are going to get this from the URL.
-Still in `app.py`, add a route decorator with the URL path `/job/
` Jobs header in `employer.html` add a call to the `show_jobs` macro passing in `jobs`.
-### 6.4 - Employer Template Reviews
+## 6.4 - Employer Template Reviews
-@pytest.mark.employer_template_reviews Still in `employer.html` find the review `
`, remove the comment surrounding the empty `{% %}` template tag. To this tag add a `for in` loop to loop through all `reviews`. Add the `endfor` directive to the second empty `{% %}` template tag, don't forget to the remove the comment.
+@pytest.mark.employer_template_reviews Still in `employer.html` find the review `
`, remove the comment surrounding the empty `{% %}` template tag. To this tag add a `for in` loop to loop through all `reviews`. Add the `endfor` directive to the second empty `{% %}` template tag, don't forget to the remove the comment.
-### 6.5 - Employer Template Review Stars
+## 6.5 - Employer Template Review Stars
@pytest.mark.employer_template_review_stars Still `employer.html` in the `
` in the `index.html` template does not contain the contents 'Jobs'."
- assert template_find('index', 'h1', limit=1)[0].text == 'Jobs', "The `
` in the `index.html` template does not contain the contents 'Jobs'."
+ template_dir = os.path.isdir("jobs/templates")
+ assert template_dir, "The `templates` folder has not been created."
+
+ index_exists = template_exists("index")
+ assert (
+ index_exists
+ ), "The `index.html` template does not exist in the `templates` folder."
+
+ h1_exists = template_find("index", "h1", limit=1)
+ assert (
+ h1_exists
+ ), "The `
` in the `index.html` template does not contain the contents 'Jobs'."
+
+ h1_jobs = template_find("index", "h1", limit=1)[0].text == "Jobs"
+ assert (
+ h1_jobs
+ ), "The `
` in the `index.html` template does not contain the contents 'Jobs'."
+
@pytest.mark.test_app_index_route_function_module1
def test_app_index_route_function_module1():
- assert 'app' in dir(app), 'Have you created an instance of the `Flask` class called `app`?'
- assert 'jobs' in dir(app), 'Have you created the `jobs` function?'
- result = [item for item in get_functions(app.jobs) if item.startswith('render_template:index.html')]
- assert len(result) == 1, 'Have you called the `render_template` function.'
+ flask_app = "app" in dir(app)
+ assert flask_app, "Have you created an instance of the `Flask` class called `app`?"
+
+ jobs_function = "jobs" in dir(app)
+ assert jobs_function, "Have you created the `jobs` function?"
+
+ result = [
+ item
+ for item in get_functions(app.jobs)
+ if item.startswith("render_template:index.html")
+ ]
+ result_len = len(result) == 1
+ assert result_len, "Have you called the `render_template` function."
+
+ return_values = get_functions_returns(app.jobs)[0]
+ return_exists = (
+ return_values["value/args/s"] == "index.html"
+ and return_values["value/func/id"] == "render_template"
+ )
+ assert return_exists, "Did you return the `render_template` call?"
+
@pytest.mark.test_app_route_decoractors_module1
def test_app_route_decoractors_module1():
- assert 'app' in dir(app), 'Have you created an instance of the `Flask` class called `app`?'
- assert template_exists('index'), 'The `index.html` template does not exist in the `templates` folder.'
- assert 'jobs' in dir(app), 'Have you created the `jobs` function?'
+ flask_app = "app" in dir(app)
+ assert flask_app, "Have you created an instance of the `Flask` class called `app`?"
+
+ index_exists = template_exists("index")
+ assert (
+ index_exists
+ ), "The `index.html` template does not exist in the `templates` folder."
+
+ jobs_function = "jobs" in dir(app)
+ assert jobs_function, "Have you created the `jobs` function?"
rules = list_routes(app.app)
+ root_route = "jobs:GET,HEAD,OPTIONS:/" in rules
+ assert root_route, "Have you decorated the `jobs` function with the `/` route?"
- assert 'jobs:GET,HEAD,OPTIONS:/' in rules, 'Have you decorated the `jobs` function with the `/` route?'
- assert 'jobs:GET,HEAD,OPTIONS:/jobs' in rules, 'Have you decorated the `jobs` function with the `/jobs` route?'
+ jobs_route = "jobs:GET,HEAD,OPTIONS:/jobs" in rules
+ assert jobs_route, "Have you decorated the `jobs` function with the `/jobs` route?"
diff --git a/tests/test_module2.py b/tests/test_module2.py
index fe9d7f0ba..a1a5eeae3 100644
--- a/tests/test_module2.py
+++ b/tests/test_module2.py
@@ -3,33 +3,68 @@
from jobs import app
from .utils import *
-calls = template_functions('layout', 'url_for')
+calls = template_functions("layout", "url_for")
+
@pytest.mark.test_layout_template_module2
def test_layout_template_module2():
- assert template_exists('layout'), 'The `layout.html` template does not exist in the `templates` folder.'
+ layout_exists = template_exists("layout")
+ assert (
+ layout_exists
+ ), "The `layout.html` template does not exist in the `templates` folder."
+
@pytest.mark.test_add_bulma_css_framework_module2
def test_add_bulma_css_framework_module2():
- assert template_exists('layout'), 'The `layout.html` template does not exist in the `templates` folder.'
- assert 'static:filename:css/bulma.min.css' in calls, 'Looks like `bulma.min.css` is not linked in `layout.html`.'
+ layout_exists = template_exists("layout")
+ assert (
+ layout_exists
+ ), "The `layout.html` template does not exist in the `templates` folder."
+
+ css_exists = "static:filename:css/bulma.min.css" in calls
+ assert css_exists, "Looks like `bulma.min.css` is not linked in `layout.html`."
+
@pytest.mark.test_add_custom_css_module2
def test_add_custom_css_module2():
- assert template_exists('layout'), 'The `layout.html` template does not exist in the `templates` folder.'
- assert 'static:filename:css/app.css' in calls, 'Looks like `app.css` is not linked in `layout.html`.'
+ layout_exists = template_exists("layout")
+ assert (
+ layout_exists
+ ), "The `layout.html` template does not exist in the `templates` folder."
+
+ css_exists = "static:filename:css/app.css" in calls
+ assert css_exists, "Looks like `app.css` is not linked in `layout.html`."
+
@pytest.mark.test_add_fontawesome_module2
def test_add_fontawesome_module2():
- assert template_exists('layout'), 'The `layout.html` template does not exist in the `templates` folder.'
+ layout_exists = template_exists("layout")
+ assert (
+ layout_exists
+ ), "The `layout.html` template does not exist in the `templates` folder."
+
attr = {
- 'href': 'https://use.fontawesome.com/releases/v5.2.0/css/all.css',
- 'rel': 'stylesheet'
+ "href": "https://use.fontawesome.com/releases/v5.2.0/css/all.css",
+ "rel": "stylesheet",
}
- assert template_soup('layout').find('link', attr), 'Looks like FontAwesome is not linked in `layout.html`.'
+ layout_link_exists = template_soup("layout").find("link", attr)
+ assert layout_link_exists, "Looks like FontAwesome is not linked in `layout.html`."
+
@pytest.mark.test_extend_base_template_module2
def test_extend_base_template_module2():
- assert template_exists('index'), 'The `index.html` template does not exist in the `templates` folder.'
- assert template_exists('layout'), 'The `layout.html` template does not exist in the `templates` folder.'
- assert 'layout.html' in template_extends('index'), 'The `index.html` template does not extend `layout.html`.'
+ index_exists = template_exists("index")
+ assert (
+ index_exists
+ ), "The `index.html` template does not exist in the `templates` folder."
+
+ layout_exists = template_exists("layout")
+ assert (
+ layout_exists
+ ), "The `layout.html` template does not exist in the `templates` folder."
+
+ index_extends = "layout.html" in template_extends("index")
+ assert index_extends, "The `index.html` template does not extend `layout.html`."
+
+ content_block = "content" in template_block("index")
+ assert content_block, "Have you added a template `block` called `content`?"
diff --git a/tests/test_module3.py b/tests/test_module3.py
index d64986d31..e0cc62461 100644
--- a/tests/test_module3.py
+++ b/tests/test_module3.py
@@ -4,82 +4,197 @@
from jobs import app
from .utils import *
+
@pytest.mark.test_app_import_sqlite_module3
def test_app_import_sqlite_module3():
- assert 'sqlite3' in dir(app), 'Have you imported `sqlite`?'
+ sqlite_import = "sqlite3" in dir(app)
+ assert sqlite_import, "Have you imported `sqlite`?"
+
@pytest.mark.test_app_import_g_module3
def test_app_import_g_module3():
- assert 'g' in dir(app), 'Have you imported the `g` class from `flask`?'
+ g_import = "g" in dir(app)
+ assert g_import, "Have you imported the `g` class from `flask`?"
+
@pytest.mark.test_app_db_path_module3
def test_app_db_path_module3():
- assert 'PATH' in dir(app), 'Have you created a constant called `PATH`.'
- assert app.PATH == 'db/jobs.sqlite', 'Have you created a constant called `PATH`?'
+ assert "PATH" in dir(app), "Have you created a constant called `PATH`?"
+ assert app.PATH == "db/jobs.sqlite", "Have you created a constant called `PATH`?"
+
@pytest.mark.test_app_open_connection_get_attribute_module3
def test_app_open_connection_get_attribute_module3():
- assert 'open_connection' in dir(app), 'Have you defined a function named `open_connection`.'
- assert 'getattr:g:_connection:None' in get_functions(app.open_connection), 'Have you used the `getattr` function to get the global `_connection`?'
+
+ open_connection = "open_connection" in dir(app)
+ assert open_connection, "Have you defined a function named `open_connection`?"
+
+ result = [
+ item
+ for item in get_functions(app.open_connection)
+ if item.startswith("getattr:g:_connection")
+ ]
+ result_len = len(result) == 1
+ assert (
+ result_len
+ ), "Have you used the `getattr` function to get the global `_connection`?"
+
@pytest.mark.test_app_open_connection_connection_module3
def test_app_open_connection_connection_module3():
- assert 'g' in dir(app), 'Have you imported the `g` class from `flask`?'
- assert 'app' in dir(app), 'Have you created an instance of the `Flask` class called `app`?'
- assert 'open_connection' in dir(app), 'Have you defined a function named `open_connection`.'
+ g_import = "g" in dir(app)
+ assert g_import, "Have you imported the `g` class from `flask`?"
+
+ flask_app = "app" in dir(app)
+ assert flask_app, "Have you created an instance of the `Flask` class called `app`?"
+
+ open_connection = "open_connection" in dir(app)
+ assert open_connection, "Have you defined a function named `open_connection`?"
+
with app.app.app_context():
app.open_connection()
- assert hasattr(app.g, '_connection'), 'Did you assign the `_connection` attribute to `g`?'
- _, _, db_name = app.g._connection.execute('PRAGMA database_list').fetchone()
- assert os.path.join(os.getcwd(), 'db', 'jobs.sqlite') == db_name, 'Did you pass the `connect` function the `PATH` constant?'
+
+ connection_exists = hasattr(app.g, "_connection")
+ assert connection_exists, "Did you assign the `_connection` attribute to `g`?"
+
+ _, _, db_name = app.g._connection.execute("PRAGMA database_list").fetchone()
+ db_exists = os.path.join(os.getcwd(), "db", "jobs.sqlite") == db_name
+ assert db_exists, "Did you pass the `connect` function the `PATH` constant?"
+
@pytest.mark.test_app_open_connection_row_factory_module3
def test_app_open_connection_row_factory_module3():
- assert 'g' in dir(app), 'Have you imported the `g` class from `flask`?'
- assert 'app' in dir(app), 'Have you created an instance of the `Flask` class called `app`?'
- assert 'open_connection' in dir(app), 'Have you defined a function named `open_connection`.'
+ g_import = "g" in dir(app)
+ assert g_import, "Have you imported the `g` class from `flask`?"
+
+ flask_app = "app" in dir(app)
+ assert flask_app, "Have you created an instance of the `Flask` class called `app`?"
+
+ open_connection = "open_connection" in dir(app)
+ assert open_connection, "Have you defined a function named `open_connection`?"
+
with app.app.app_context():
db = app.open_connection()
- assert isinstance(db, app.sqlite3.Connection), 'Are you returning the database connection?'
- assert id(db.row_factory) == id(app.sqlite3.Row), 'Have you set the database `row_factory` to the sqlite3.Row class?'
+ return_connection = isinstance(db, app.sqlite3.Connection)
+ assert return_connection, "Are you returning the database connection?"
+
+ row_factory = id(db.row_factory) == id(app.sqlite3.Row)
+ assert (
+ row_factory
+ ), "Have you set the database `row_factory` to the sqlite3.Row class?"
+
@pytest.mark.test_app_execute_sql_module3
def test_app_execute_sql_module3():
- assert 'app' in dir(app), 'Have you created an instance of the `Flask` class called `app`?'
- assert 'execute_sql' in dir(app), 'Have you defined a function named `execute_sql`.'
- assert 'open_connection' in get_functions(app.execute_sql), 'Have you called the `open_connection` function in `execute_sql`?'
+ flask_app = "app" in dir(app)
+ assert flask_app, "Have you created an instance of the `Flask` class called `app`?"
+
+ execute_sql_function = "execute_sql" in dir(app)
+ assert execute_sql_function, "Have you defined a function named `execute_sql`?"
+
+ open_call = "open_connection" in get_functions(app.execute_sql)
+ assert open_call, "Have you called the `open_connection` function in `execute_sql`?"
+
@pytest.mark.test_app_execute_sql_parameters_module3
def test_app_execute_sql_parameters_module3():
- assert 'execute_sql' in dir(app), 'Have you defined a function named `execute_sql`.'
+ execute_sql_function = "execute_sql" in dir(app)
+ assert execute_sql_function, "Have you defined a function named `execute_sql`?"
+
parameters = inspect.getfullargspec(app.execute_sql)
- assert parameters.args[0] == 'sql' and parameters.args[1] == 'values' and parameters.args[2] == 'commit' and parameters.args[3] == 'single', 'Have you added the correct parameters to the `execute_sql` function parameters list?'
- assert parameters.defaults[0] == () and parameters.defaults[1] == False and parameters.defaults[2] == False, 'Do the `args` and `one` parameters have the correct defaults in the `execute_sql` function parameters list?'
+ arg_len = len(parameters.args) == 4
+ assert arg_len, "Have you added parameters to the `execute_sql` function?"
+
+ args = (
+ parameters.args[0] == "sql"
+ and parameters.args[1] == "values"
+ and parameters.args[2] == "commit"
+ and parameters.args[3] == "single"
+ )
+ assert (
+ args
+ ), "Have you added the correct parameters to the `execute_sql` function parameters list?"
+
+ defaults = (
+ parameters.defaults[0] == ()
+ and parameters.defaults[1] == False
+ and parameters.defaults[2] == False
+ )
+ assert (
+ defaults
+ ), "Do the `args` and `one` parameters have the correct defaults in the `execute_sql` function parameters list?"
+
@pytest.mark.test_app_execute_sql_execute_module3
def test_app_execute_sql_execute_module3():
- assert 'execute_sql' in dir(app), 'Have you defined a function named `execute_sql`.'
- assert 'execute:sql:values' in get_functions(app.execute_sql), 'Have you called the `execute` function in `execute_sql`?'
+ execute_sql_function = "execute_sql" in dir(app)
+ assert execute_sql_function, "Have you defined a function named `execute_sql`?"
+
+ execute_call = "execute:sql:values" in get_functions(app.execute_sql)
+ assert execute_call, "Have you called the `execute` function in `execute_sql`?"
+
@pytest.mark.test_app_execute_sql_results_module3
def test_app_execute_sql_results_module3():
- assert 'execute_sql' in dir(app), 'Have you defined a function named `execute_sql`.'
- assert 'fetchall' in get_functions(app.execute_sql), 'Have you called the `fetchall` function in `execute_sql`?'
- assert 'fetchone' in get_functions(app.execute_sql), 'Have you called the `fetchone` function in `execute_sql`?'
- assert 'commit' in get_functions(app.execute_sql), 'Have you called the `close` function in `execute_sql`?'
- assert 'close' in get_functions(app.execute_sql), 'Have you called the `close` function in `execute_sql`?'
+ execute_sql_function = "execute_sql" in dir(app)
+ assert execute_sql_function, "Have you defined a function named `execute_sql`?"
+
+ fetchall = "fetchall" in get_functions(app.execute_sql)
+ assert fetchall, "Have you called the `fetchall` function in `execute_sql`?"
+
+ fetchone = "fetchone" in get_functions(app.execute_sql)
+ assert fetchone, "Have you called the `fetchone` function in `execute_sql`?"
+
+ commit = "commit" in get_functions(app.execute_sql)
+ assert commit, "Have you called the `commit` function in `execute_sql`?"
+
+ close = "close" in get_functions(app.execute_sql)
+ assert close, "Have you called the `close` function in `execute_sql`?"
+
+ if_statement = len(get_statements(app.execute_sql)) >= 0
+ assert if_statement, "Have created an if statement in the `execute_sql` function?"
+
+ results_exists = "results" == get_statements(app.execute_sql)[0]["body/targets/id"]
+ assert (
+ results_exists
+ ), "Have you assigned the `results` variable to `connection.commit()`?"
+
with app.app.app_context():
- results = app.execute_sql('SELECT * FROM job', single=True)
- assert type(results) != list, 'Have you create an if statement to only return one result in `one` is true?'
+ results = type(app.execute_sql("SELECT * FROM job", single=True)) != list
+ assert (
+ results
+ ), "Have you create an if statement to only return one result in `one` is true?"
+
@pytest.mark.test_app_close_connection_module3
def test_app_close_connection_module3():
- assert 'close_connection' in dir(app), 'Have you defined a function named `close_connection`.'
- assert 'getattr:g:_connection:None' in get_functions(app.open_connection), 'Have you used the `getattr` function to get the global `_connection`?'
- assert 'close' in get_functions(app.execute_sql), 'Have you called the `close` function in `execute_sql`?'
+ close_connection = "close_connection" in dir(app)
+ assert close_connection, "Have you defined a function named `close_connection`?"
+
+ result = [
+ item
+ for item in get_functions(app.open_connection)
+ if item.startswith("getattr:g:_connection")
+ ]
+ result_len = len(result) == 1
+ assert (
+ result_len
+ ), "Have you used the `getattr` function to get the global `_connection`?"
+
+ close = "close" in get_functions(app.close_connection)
+ assert close, "Have you called the `close` function in `close_connection`?"
+
@pytest.mark.test_app_close_connection_decorator_module3
def test_app_close_connection_decorator_module3():
- assert 'close_connection' in dir(app), 'Have you defined a function named `close_connection`.'
- decorator = get_decorators(app.close_connection)['close_connection'][0][0]
- assert decorator == 'teardown_appcontext', 'Does `close_connection` have a `teardown_appcontext` decorator?'
\ No newline at end of file
+ close_connection = "close_connection" in dir(app)
+ assert close_connection, "Have you defined a function named `close_connection`?"
+
+ decorators = get_decorators(app.close_connection)["close_connection"]
+
+ decorators_len = len(decorators) == 1
+ assert decorators_len, "Have you added the correct decorator to `close_connection`?"
+
+ decorator = decorators[0][0]
+ teardown = decorator == "teardown_appcontext"
+ assert teardown, "Does `close_connection` have a `teardown_appcontext` decorator?"
diff --git a/tests/test_module4.py b/tests/test_module4.py
index 503d7d5b4..7887d41ca 100644
--- a/tests/test_module4.py
+++ b/tests/test_module4.py
@@ -4,77 +4,175 @@
from jobs import app
from .utils import *
+
@pytest.mark.test_template_macros_module4
def test_template_macros_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
@pytest.mark.test_show_job_macro_definition_module4
def test_show_job_macro_definition_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- assert 'show_job:job' in template_macros('_macros'), 'Have you created the `show_job` macro and added the correct parameter?'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
+ show_job = "show_job:job" in template_macros("_macros")
+ assert (
+ show_job
+ ), "Have you created the `show_job` macro and added the correct parameter?"
+
@pytest.mark.test_show_job_macro_html_module4
def test_show_job_macro_html_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- html = template_macro_soup('_macros', 'show_job')
- p = html.select('.card .card-header .card-header-title')
- div = html.select('.card-content .content')
- assert len(p) == 1 and len(div) == 1, 'Has the `HTML` from `templates.html` been copied to the `show_job` macro?'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
+ html = template_macro_soup("_macros", "show_job")
+ p = html.select(".card .card-header .card-header-title")
+ div = html.select(".card-content .content")
+
+ copied = len(p) == 1 and len(div) == 1
+ assert (
+ copied
+ ), "Has the `HTML` from `templates.html` been copied to the `show_job` macro?"
+
@pytest.mark.test_show_job_macro_header_module4
def test_show_job_macro_header_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- assert 'job:job_id:job:id' in template_functions('_macros', 'url_for'), 'Looks like the job title link `href` is incorrect.'
- assert 'job:title' in template_variables('_macros'), 'Looks like the job title link does not have content.'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
+ job_title = "job:title" in template_variables("_macros")
+ assert job_title, "Looks like the job title link does not have content."
+
@pytest.mark.test_show_job_macro_body_module4
def test_show_job_macro_body_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- assert 'employer:employer_id:job:employer_id' in template_functions('_macros', 'url_for'), 'Looks like the job title link `href` is incorrect.'
- assert 'job:employer_name' in template_variables('_macros'), 'Are you showing the employer name?'
- assert 'job:salary' in template_variables('_macros'), 'Are you showing the job salary?'
- assert 'job:description' in template_variables('_macros'), 'Are you showing the job description?'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
+ employer_name = "job:employer_name" in template_variables("_macros")
+ assert employer_name, "Are you showing the employer name?"
+
+ salary = "job:salary" in template_variables("_macros")
+ assert salary, "Are you showing the job salary?"
+
+ description = "job:description" in template_variables("_macros")
+ assert description, "Are you showing the job description?"
+
@pytest.mark.test_show_jobs_macro_definition_module4
def test_show_jobs_macro_definition_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- assert 'show_jobs:jobs' in template_macros('_macros'), 'Have you created the `show_jobs` macro and added the correct parameter?'
+ macros_exists = template_exists("_macros")
+ assert (
+ macros_exists
+ ), "The `_macros.html` template does not exist in the `templates` folder."
+
+ show_jobs = "show_jobs:jobs" in template_macros("_macros")
+ assert (
+ show_jobs
+ ), "Have you created the `show_jobs` macro and added the correct parameter?"
+
@pytest.mark.test_show_jobs_macro_for_loop_module4
def test_show_jobs_macro_for_loop_module4():
- assert template_exists('_macros'), 'The `_macros.html` template does not exist in the `templates` folder.'
- html = template_macro_soup('_macros', 'show_jobs')
- div = html.select('div.columns.is-multiline')
- assert len(div) == 1, 'Has a `