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

Zoisite - Jessica #111

Open
wants to merge 55 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9f1f307
Install blinker, update req, get tests to fail, setup pseudo for rout…
Yiskah-S May 7, 2023
8bae664
Wave 1 finish tests
Yiskah-S May 7, 2023
24b4649
Fix error in task __init__
Yiskah-S May 7, 2023
8ab85f5
Update init file
Yiskah-S May 7, 2023
027f85c
Wave 1 post
Yiskah-S May 7, 2023
760f751
Post refactored with helper function
Yiskah-S May 7, 2023
3401e24
wave 1 GET all tasks
Yiskah-S May 7, 2023
e178d82
Make test file more clear to work with
Yiskah-S May 7, 2023
ebd9099
Wave 1 finish get, 400, 404, helper functions for those
Yiskah-S May 7, 2023
701a605
Wave 1 update task
Yiskah-S May 7, 2023
2e247b0
Fix 400 tests messages
Yiskah-S May 7, 2023
a308743
Wave 1 completed
Yiskah-S May 7, 2023
f66ec25
Wave 2
Yiskah-S May 7, 2023
0bf3230
Halway through wave 3
Yiskah-S May 8, 2023
2850bf3
wave 3
Yiskah-S May 8, 2023
a7a4e36
fixed tests
Yiskah-S May 8, 2023
d6b86ee
wave 5
Yiskah-S May 9, 2023
fd2d664
Fix wave 5 tests
Yiskah-S May 9, 2023
44d07b9
testig if it was a venv issue
Yiskah-S May 9, 2023
afb8746
Refactored into files
Yiskah-S May 11, 2023
bc23c70
wave 4
Yiskah-S May 11, 2023
9e76ca5
refactor
Yiskah-S May 11, 2023
aac180f
refactor main paths
Yiskah-S May 11, 2023
aeee95c
Finished refactor for wave 1 and 5
Yiskah-S May 11, 2023
5fcbb3a
wave 2
Yiskah-S May 11, 2023
8e9d915
wave 2 refactored and tests and functionality added
Yiskah-S May 12, 2023
2fe3ae1
wave 1, 2, 3, 5 refactored fully
Yiskah-S May 12, 2023
edb818d
wave 4
Yiskah-S May 12, 2023
2428d90
Wave 6
Yiskah-S May 12, 2023
560254e
wave 6 refactored
Yiskah-S May 12, 2023
1342834
Polishing and minor changes
Yiskah-S May 12, 2023
888593b
Add additional tests
Yiskah-S May 12, 2023
594cf30
minor clean up
Yiskah-S May 12, 2023
39fa058
fix tests
Yiskah-S May 12, 2023
87aacc6
Fixed Postman
Yiskah-S May 12, 2023
64190e2
Render setup
Yiskah-S May 12, 2023
323be5b
fixed init file
Yiskah-S May 14, 2023
430613d
new db migrate
Yiskah-S May 14, 2023
5813ecb
fix
Yiskah-S May 14, 2023
31d5941
omg
Yiskah-S May 14, 2023
ff9a4be
try again to get Render to work
Yiskah-S May 16, 2023
8291d75
fix requirements
Yiskah-S May 16, 2023
5e31dd0
Upgraded software
Yiskah-S May 16, 2023
e96c3a3
Changed requirements again
Yiskah-S May 16, 2023
13f568b
Change requirements
Yiskah-S May 16, 2023
a25a20c
req
Yiskah-S May 16, 2023
89a0d72
req
Yiskah-S May 16, 2023
fbaac96
db upgrade
Yiskah-S May 16, 2023
59d0de6
test jsonify
Yiskah-S May 17, 2023
55dd1b3
add jsonify
Yiskah-S May 17, 2023
98817fb
fix typo
Yiskah-S May 17, 2023
0334941
fix bracket error
Yiskah-S May 17, 2023
0dc5c41
rollback some stuff
Yiskah-S May 17, 2023
81afc19
try get
Yiskah-S May 17, 2023
41eef03
clean up code
Yiskah-S May 17, 2023
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
19 changes: 19 additions & 0 deletions ada-project-docs/optional-enhancements.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
### Edge Cases

Many waves are missing many edge case considerations. Consider different edge cases in each wave, make decisions for what should happen, and then implement it!

As inspiration, here are some beginning edge cases to consider:

What should happen if...

- when creating a task, the value of `completed_at` is a string that is not a datetime?
- when updating a task, the value of `completed_at` is a string that is not a datetime?
- when getting all tasks, and using query params, the value of `sort` is not "desc" or "asc"?

For each of these, consider what the HTTP response should be.

How would you write tests for it? How would you implement it?

Your decisions should not break the other tests.


# Optional Enhancements

## Goal
Expand Down
19 changes: 19 additions & 0 deletions ada-project-docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,23 @@ Review the [code coverage exercise](https://github.com/adaGold/code-coverage-exe

`pytest --cov=app --cov-report html --cov-report term`

There is not a specific code coverage percentage required for this project. Creating a code coverage report allows us to continue practicing the skill of reading the code coverage report and using it as part of our development workflow.


## Tests

We will need to complete part – or all – of some of the tests for this project. If a test is incomplete, it will raise an `Exception`. You should comment out the `Exception` when implementing the test.

You may wish to review details about how to run tests [here](https://github.com/AdaGold/viewing-party#details-about-how-to-run-tests).

Recall that it is always a good idea to search the file for any `@pytest.mark.skip` decorators you may have missed before moving to the next wave.

### Code Coverage

Code coverage is a term used to describe how much application code is executed when a particular test suite is run. It is a good practice to check our code coverage in order to understand how much of our code is exercised by tests vs how much is still untested. A test suite with a high percentage of coverage is likely to be tested more thoroughly and have fewer bugs. A code coverage tool can partner with our testing suite to give us a report illustrating the coverage of our tests.

Review the [code coverage exercise](https://github.com/adaGold/code-coverage-exercise) on how to use `pytest-cov` to generate a code coverage report. We will need to change the directory where the application code is located from `student` to `app`.

`pytest --cov=app --cov-report html --cov-report term`

There is not a specific code coverage percentage required for this project. Creating a code coverage report allows us to continue practicing the skill of reading the code coverage report and using it as part of our development workflow.
1 change: 1 addition & 0 deletions ada-project-docs/wave_01.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,4 @@ If the HTTP request is missing `completed_at`, we should also get this response:
"details": "Invalid data"
}
```

53 changes: 53 additions & 0 deletions ada-project-docs/wave_04.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
- What is the responsibility of this endpoint? send a message to a channel
- What is the URL and HTTP method for this endpoint? The URL for this endpoint is https://slack.com/api/chat.postMessage and the HTTP method is POST.
- What are the _two_ _required_ arguments for this endpoint? toke and channel
- How does this endpoint relate to the Slackbot API key (token) we just created? token

{
"ok": true,
"channel": "C0561UUDX4K",
"ts": "1683767884.147159",
"message": {
"bot_id": "B057X96T14G",
"type": "message",
"text": "Hello world",
"user": "U057A363EFN",
"ts": "1683767884.147159",
"app_id": "A056T21RBC7",
"blocks": [
{
"type": "rich_text",
"block_id": "uEBB7",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Hello world"
}
]
}
]
}
],
"team": "T04L0DA7XB6",
"bot_profile": {
"id": "B057X96T14G",
"app_id": "A056T21RBC7",
"name": "Y's Bot",
"icons": {
"image_36": "https://a.slack-edge.com/80588/img/plugins/app/bot_36.png",
"image_48": "https://a.slack-edge.com/80588/img/plugins/app/bot_48.png",
"image_72": "https://a.slack-edge.com/80588/img/plugins/app/service_72.png"
},
"deleted": false,
"updated": 1683766418,
"team_id": "T04L0DA7XB6"
}
}
}

# Wave 4: Using an External Web API

## Goal
Expand Down Expand Up @@ -194,3 +244,6 @@ Send `PATCH` requests to `localhost:5000/tasks/<book_id>/mark_complete` (use the
![](assets/postman_patch.png)

![](assets/slack_notification_feature.png)



3 changes: 3 additions & 0 deletions ada-project-docs/wave_05.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,6 @@ and get this response:
```

so that I know I did not create a Goal that is saved in the database.



148 changes: 148 additions & 0 deletions ada-project-docs/wave_06.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,154 @@ then I get this response:

`404 Not Found`

You may choose the response body.

Make sure to complete the tests for non-existing tasks to check that the correct response body is returned.
__________



# Wave 6: Establishing a One-to-Many Relationship

## Goal

Our users want to associate tasks and goals. Specifically, our users want to designate that there are many tasks that serve one goal.

This wave focuses on creating a one-to-many relationship between goals and tasks, where a goal has-many tasks, and a task belongs to one goal.

When we have many tasks and many goals, users will want to conveniently gather all of the tasks associated with one goal. Our API should serve this information with a new route, `/goals/<goal_id>/tasks`.

## Requirements

First, we should update our models so that the relationship is saved in our database.

Secondly, we should create our new route, `/goals/<goal_id>/tasks`, so that our API gives back the right information.

### Tips

- Use independent research to discover how to set up a one-to-many relationship in Flask.
- Remember to run `flask db migrate` and `flask db upgrade` whenever there is a change to the model.
- Pay attention to the exact shape of the expected JSON. Double-check nested data structures and the names of the keys for any mispellings.
- Use the tests in `tests/test_wave_06.py` to guide your implementation.
- Some tests use a fixture named `one_task_belongs_to_one_goal` that is defined in `tests/conftest.py`. This fixture saves a task and a goal to the test database, and uses SQLAlchemy to associate the goal and task together.

### Updates to the Goal Model

Use independent research to discover how to set up a one-to-many relationship in Flask.

The Goal model should have a _relationship_ with the model Task.

After learning the strategy for creating a one-to-many relationship, in the Goal model, we recommend:

- Setting the `lazy` value to `True`

### Updates to the Task Model

Use independent research to discover how to set up a one-to-many relationship in Flask.

The Task model should belong to one `Goal`.

After learning the strategy for creating a one-to-many relationship, in the Task model, we recommend:

- Setting the foreign key to `goal`'s primary key column
- Setting the `nullable` to `True`

Remember to run `flask db migrate` and `flask db upgrade` whenever there is a change to the model.

### Sending a List of Task IDs to a Goal

Given:

- a goal that has the ID `1`
- three tasks with the IDs `1`, `2`, and `3`

When I send a `POST` request to `/goals/1/tasks` with this request body:

```json
{
"task_ids": [1, 2, 3]
}
```

Then the three `Task`s belong to the `Goal` and it gets updated in the database, and we get back a `200 OK` with the following response body:

```json
{
"id": 1,
"task_ids": [1, 2, 3]
}
```

### Getting Tasks of One Goal

Given a goal that has:

- An id `333`
- A `title` attribute with the value `"Build a habit of going outside daily"`

and a task that has:

- An id `999`
- A `title` attribute with the value `"Go on my daily walk 🏞"`
- A `description` attribute with the value `"Notice something new every day"`
- A `completed_at` attribute with a `null` value
- It belongs to the Goal with ID 333

when I send a `GET` request to `/goals/333/tasks`,

then I get this response:

`200 OK`

```json
{
"id": 333,
"title": "Build a habit of going outside daily",
"tasks": [
{
"id": 999,
"goal_id": 333,
"title": "Go on my daily walk 🏞",
"description": "Notice something new every day",
"is_complete": false
}
]
}
```

### Getting Tasks of One Goal: No Matching Tasks

Given a goal that has:

- An id `333`
- A `title` attribute with the value `"Build a habit of going outside daily"`

and no tasks that belong to this goal,

when I send a `GET` request to `/goals/333/tasks`,

then I get this response:

`200 OK`

```json
{
"id": 333,
"title": "Build a habit of going outside daily",
"tasks": []
}
```

### Getting Tasks of One Goal: No Matching Goal

Given that no goals exist,

when I send a `GET` request to `/goals/1/tasks`,

then I get this response:

`404 Not Found`

You may choose the response body.

Make sure to complete the tests for non-existing tasks to check that the correct response body is returned.
28 changes: 28 additions & 0 deletions ada-project-docs/wave_07.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,31 @@ Be sure to grab the URL of your deployed app. It will be submitted at the time o
- Use the Render logs
- Research error messages
- Rubber duck and ask for help

_________


# Wave 7: Deployment

## Goal

Our goal is to make our project accessible online!

## Requirements

Deploy this project to Render.

Then, add some Task records and Goal records to the production database.

Be sure to grab the URL of your deployed app. It will be submitted at the time of project submission.

### Tips

- When unexpected issues come up, employ all of your debugging skills:
- Write down what step/command just created the issue
- Write down how you observe the issue
- Attempt to recreate the issue locally
- Use Postman, the browser, and the debugger tools
- Use the Render logs
- Research error messages
- Rubber duck and ask for help
14 changes: 10 additions & 4 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
import os
from dotenv import load_dotenv
from flask import Flask
import os


db = SQLAlchemy()
Expand All @@ -15,8 +15,10 @@ def create_app(test_config=None):
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

if test_config is None:
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
"SQLALCHEMY_DATABASE_URI")
# app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get("SQLALCHEMY_DATABASE_URI")
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get("RENDER_DATABASE_URI")


else:
app.config["TESTING"] = True
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
Expand All @@ -30,5 +32,9 @@ def create_app(test_config=None):
migrate.init_app(app, db)

# Register Blueprints here
from app.routes.task_routes import tasks_bp
app.register_blueprint(tasks_bp)
from app.routes.goal_routes import goals_bp
app.register_blueprint(goals_bp)

return app
24 changes: 22 additions & 2 deletions app/models/goal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
from app import db


class Goal(db.Model):
goal_id = db.Column(db.Integer, primary_key=True)
__tablename__ = 'goals'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a reminder that we should have an empty init.py within our model directory as well!


goal_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String, nullable=False)
tasks = db.relationship("Task", back_populates="goal")


def to_json(self, tasks=False):
goal_dict = {
"id": self.goal_id,
"title": self.title,
}
if tasks:
goal_dict["tasks"] = [task.to_json() for task in self.tasks]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use of a list comprehension here!

return goal_dict

@classmethod
def from_json(cls, request_body):
return cls(
title=request_body["title"]
)

Loading