Skip to content

Individual Contribution Report 2 | Emre Sin

Emre SİN edited this page May 12, 2023 · 2 revisions

Member

Name: Emre Sin

Main git issues

Researching REST Countries API #175
Learning Flask API and Git #159
Implementing an UI for REST Countries API #185
Implementing the backend for REST Countries API #219
Implementing the Unit Tests for the REST Countries API #220
Adding Swagger Support to WorldCountries #231
Form an Individual Contribution Page #221

The name, route, description of utilized third party URIs

For the practice app I preferred to use REST Countries API

Name: REST Countries API
Route: https://restcountries.com/v3.1/name/{name}
Description: Used for getting information about all countries in the world. It has multiple fields for each country and it provides filtering functionality. In my project I decided to use only couple of fields of it and using its filtering by name functionality.

The name, route, description of the created API functions

    • Name: GetWorldCountries
    • Route: /worldcountries
    • Description: Retrieves a list of world countries from the database. This function queries the Country table in the database and returns the results as HTML rendered using the "worldcountries.html" template. The countries are passed to the template as entries. This page basically the main page of the functionality.
    • Name: PostWorldCountries
    • Route: /worldcountries
    • Description: Adds a new country to the database based on user input. This function handles a POST request and expects a form parameter called "country" containing the name of the country to be added. It makes a request to the "restcountries.com" API to fetch detailed information about the country. If the country is found, the relevant data such as name, official name, currencies, capital, region, and population are extracted from the API response. A new Country object is created with the extracted data and saved to the database. If the country is not found or there are any errors, an appropriate error message is displayed in the response. Finally, the updated list of countries is queried from the database and rendered using the "worldcountries.html" template along with any error messages.

Description of Unit Tests

def test_signup(client):
   client.post(
       "/signup",
       data=dict(
           username=TEST_USER, password=TEST_USERPASS, password_confirm=TEST_USERPASS
       ),
       follow_redirects=True,
   )
   user = User.query.filter_by(username=TEST_USER).first()
   assert str(user.username) == TEST_USER
  • The first test, test_signup, checks if the signup process successfully adds a user to the database by verifying that the user with the given TEST_USER username exists.
def test_login(client):
    client.post(
        "/login",
        data=dict(username=TEST_USER, password=TEST_USERPASS),
        follow_redirects=True,
    )
    response = client.get("/")
    assert response.status_code == 200
  • The second test, test_login, verifies that the login process is successful by checking if the response status code after logging in is 200.
def test_invalid_login(client):
    client.post(
        "/login",
        data={
            "username": "not_logged_username",
            "password": "not_logged_username_password",
        },
    )
    response = client.get("/")
    assert response.status_code == 302
  • The third test, test_invalid_login, ensures that an invalid login attempt redirects the user and returns a response with a status code of 302 (indicating a redirect).
def test_worldcountries_post(client):
    response = client.post(
        "/worldcountries", data={"country": "germany"}, follow_redirects=True
    )
    # if country is empty
    assert response.status_code == 200
  • The fourth test, test_worldcountries_post, validates that the POST request to /worldcountries with the "germany" country data returns a response with a status code of 200.
def test_worldcountries_get(client):
    response = client.get("/worldcountries")
    assert response.status_code == 200
  • The fifth test, test_worldcountries_get, confirms that the GET request to /worldcountries returns a response with a status code of 200.
def test_logout(client):
    client.post(
        "/login",
        data=dict(username=TEST_USER, password=TEST_USERPASS),
        follow_redirects=True,
    )
    client.get("/logout", follow_redirects=True)
    response = client.get("/")
    assert response.status_code == 302
  • The sixth test, test_logout, checks if the logout process is successful by verifying that the response after logging out is a redirect with a status code of 302.
def test_clean(session):
user = User.query.filter_by(username=TEST_USER).first()
if user:
session.delete(user)
session.commit()
  • The seventh test, test_clean, ensures that the test data created during the test cases is cleaned up by deleting the test user from the database.

Sample Calls

  • Sample call REST Countries
Request:
HTTP Method: GET
Endpoint: /v3.1/name/{name}.
Headers:
- Content-Type: application/json

and the response for this request is:

Response:
HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "name": {
            "common": "Germany",
            "official": "Federal Republic of Germany",
            "nativeName": {
                "deu": {
                    "official": "Bundesrepublik Deutschland",
                    "common": "Deutschland"
                }
            }
        },
        "tld": [
            ".de"
        ],
        "cca2": "DE",
        "ccn3": "276",
        "cca3": "DEU",
        "cioc": "GER",
        "independent": true,
        "status": "officially-assigned",
        "unMember": true,
        "currencies": {
            "EUR": {
                "name": "Euro",
                "symbol": ""
            }
        },
        "idd": {
            "root": "+4",
            "suffixes": [
                "9"
            ]
        },
        "capital": [
            "Berlin"
        ],
        "altSpellings": [
            "DE",
            "Federal Republic of Germany",
            "Bundesrepublik Deutschland"
        ],
        "region": "Europe",
        "subregion": "Western Europe",
        "languages": {
            "deu": "German"
        },
        "translations": {
            "ara": {
                "official": "جمهورية ألمانيا الاتحادية",
                "common": "ألمانيا"
            },
            "bre": {
                "official": "Republik Kevreadel Alamagn",
                "common": "Alamagn"
            },
            "tur": {
                "official": "Almanya Federal Cumhuriyeti",
                "common": "Almanya"
            },
            "urd": {
                "official": "وفاقی جمہوریہ جرمنی",
                "common": "جرمنی"
            },
            "zho": {
                "official": "德意志联邦共和国",
                "common": "德国"
            }
        },
        "latlng": [
            51.0,
            9.0
        ],
        "landlocked": false,
        "borders": [
            "AUT",
            "BEL",
            "CZE",
            "DNK",
            "FRA",
            "LUX",
            "NLD",
            "POL",
            "CHE"
        ],
        "area": 357114.0,
        "demonyms": {
            "eng": {
                "f": "German",
                "m": "German"
            },
            "fra": {
                "f": "Allemande",
                "m": "Allemand"
            }
        },
        "flag": "🇩🇪",
        "maps": {
            "googleMaps": "https://goo.gl/maps/mD9FBMq1nvXUBrkv6",
            "openStreetMaps": "https://www.openstreetmap.org/relation/51477"
        },
        "population": 83240525,
        "gini": {
            "2016": 31.9
        },
        "fifa": "GER",
        "car": {
            "signs": [
                "DY"
            ],
            "side": "right"
        },
        "timezones": [
            "UTC+01:00"
        ],
        "continents": [
            "Europe"
        ],
        "flags": {
            "png": "https://flagcdn.com/w320/de.png",
            "svg": "https://flagcdn.com/de.svg",
            "alt": "The flag of Germany is composed of three equal horizontal bands of black, red and gold."
        },
        "coatOfArms": {
            "png": "https://mainfacts.com/media/images/coats_of_arms/de.png",
            "svg": "https://mainfacts.com/media/images/coats_of_arms/de.svg"
        },
        "startOfWeek": "monday",
        "capitalInfo": {
            "latlng": [
                52.52,
                13.4
            ]
        },
        "postalCode": {
            "format": "#####",
            "regex": "^(\\d{5})$"
        }
    }
]

Note that I have truncated some part of the response in order to not make it unnecessarily long.

Request:
POST /worldcountries
Content-Type: application/x-www-form-urlencoded

country=Germany

and the response for this request is a webpage

Response:
HTTP/1.1 200 OK
Content-Type: text/html

Any other significant work

  • I did code reviews for this project. I have resolved conflicts while merging and I have fixed some problems occurred in git with branching.
  • Other than that I did my best to help my teammates while they are having difficulties catching up or grasping the contexts.
  • I joined the discussions related what to use or what to not use I have contributed explaining the differences between the options and the cons and pros of every option to the team so that we could decide which options are best to use.

And also here is the Pull Request that I have reviewed and merged. #196

Challenges that I encountered

First and the biggest challenge was learning flask for me. Even tough I had the experience developing backend before it was with C# and the the I felt the conceptual differences between the two.

I was having hard time having the setup with Postgresql due to the problems on my Mac and also there were some problems with the Unit Testing because of the Login System but in the end all of them are fixed with the collaboration of my teammates.

Clone this wiki locally