Skip to content

Commit

Permalink
Working tests and better structure
Browse files Browse the repository at this point in the history
  • Loading branch information
madflojo committed Oct 22, 2023
1 parent dc264f5 commit df7e99a
Show file tree
Hide file tree
Showing 8 changed files with 433 additions and 171 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: build

on:
push:
branches:
- main
pull_request:

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: Execute Tests
run: make tests
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ build:
docker run --rm -v `pwd`:/build -w /build/functions/build/init tinygo/tinygo:0.25.0 tinygo build -o /build/functions/build/init.wasm -target wasi /build/functions/src/init/main.go
docker run --rm -v `pwd`:/build -w /build/functions/build/data/fetch tinygo/tinygo:0.25.0 tinygo build -o /build/functions/build/fetch.wasm -target wasi /build/functions/src/data/fetch/main.go

tests:
## Run tests
mkdir -p coverage
go test -v -race -covermode=atomic -coverprofile=coverage/coverage.out ./...
go tool cover -html=coverage/coverage.out -o coverage/coverage.html

docker-compose:
docker compose up

Expand Down
108 changes: 108 additions & 0 deletions pkg/airport/airport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package airport

import (
"fmt"
"github.com/enescakir/emoji"
)

// Airport is a struct that contains information about an airport.
type Airport struct {
// Continent is the continent the airport is located in.
Continent string `json:"continent"`

// Emoji is the emoji of the airport location. (Example: ๐Ÿ‡บ๐Ÿ‡ธ, ๐Ÿ‡จ๐Ÿ‡ฆ, ๐Ÿ‡ฌ๐Ÿ‡ง, etc.)
Emoji string `json:"emoji"`

// ISOCountry is the ISO code of the country the airport is located in.
ISOCountry string `json:"iso_country"`

// ISORegion is the ISO code of the region the airport is located in.
ISORegion string `json:"iso_region"`

// LocalCode is the local code of the airport. This is a three letter code and is unique to each airport.
LocalCode string `json:"local_code"`

// Municipality is the municipality the airport is located in.
Municipality string `json:"municipality"`

// Name is the name of the airport.
Name string `json:"name"`

// Type is the type of airport (examples: small_airport, heliport, closed, etc.).
Type string `json:"type"`

// TypeEmoji is the emoji of the airport type (examples: ๐Ÿ›ฌ, ๐Ÿš, ๐Ÿšง, etc.).
TypeEmoji string `json:"type_emoji"`

// Status is the status of airport (examples: open, closed, etc.).
Status string `json:"status"`
}

var (
ErrMissingFields = fmt.Errorf("Missing required fields")
ErrUnknownCountry = fmt.Errorf("Unable to lookup country emoji")
)

// Validate validates the airport struct and returns the airport with the emoji and country flag set.
func Validate(a Airport) (Airport, error) {
var err error
// Validate Minimum Fields Exist
if a.LocalCode == "" || a.Name == "" || a.ISOCountry == "" {
return a, ErrMissingFields
}

// Set Airport Emoji
a, err = setTypeEmoji(a)
if err != nil {
return a, err
}

// Set Country Flag
a, err = setCountryFlag(a)
if err != nil {
return a, err
}

return a, nil
}

// setTypeEmoji sets the emoji for the airport type.
func setTypeEmoji(a Airport) (Airport, error) {
switch a.Type {
case "heliport":
a.TypeEmoji = emoji.Helicopter.String()
a.Status = "open"
case "small_airport":
a.TypeEmoji = emoji.SmallAirplane.String()
a.Status = "open"
case "medium_airport", "large_airport":
a.TypeEmoji = emoji.Airplane.String()
a.Status = "open"
case "seaplane_base":
a.TypeEmoji = emoji.Anchor.String()
a.Status = "open"
case "balloonport":
a.TypeEmoji = emoji.Balloon.String()
a.Status = "open"
case "closed", "unknown":
a.Type = "unknown"
a.TypeEmoji = emoji.Construction.String()
a.Status = "closed"
default:
a.TypeEmoji = emoji.QuestionMark.String()
a.Status = "unknown"
}

return a, nil
}

// setCountryFlag sets the emoji for the country the airport is located in.
func setCountryFlag(a Airport) (Airport, error) {
// Set the Country Emoji
flag, err := emoji.CountryFlag(a.ISOCountry)
if err != nil {
return a, ErrUnknownCountry
}
a.Emoji = flag.String()
return a, nil
}
195 changes: 195 additions & 0 deletions pkg/airport/airport_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package airport

import (
"testing"
)

type AirportTestCase struct {
name string
input Airport
expected Airport
err error
}

func TestAirport(t *testing.T) {
tt := []AirportTestCase{
{
name: "Basic Test",
input: Airport{
Name: "Test Airport",
LocalCode: "TST",
ISOCountry: "US",
},
expected: Airport{
Name: "Test Airport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "โ“",
Status: "unknown",
},
},
{
name: "Missing name",
input: Airport{
LocalCode: "TST",
ISOCountry: "US",
},
err: ErrMissingFields,
},
{
name: "Unknown country",
input: Airport{
Name: "Test Airport",
LocalCode: "TST",
ISOCountry: "TST",
},
err: ErrUnknownCountry,
},
{
name: "Heliport",
input: Airport{
Name: "Test Heliport",
LocalCode: "TST",
ISOCountry: "US",
Type: "heliport",
},
expected: Airport{
Name: "Test Heliport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "๐Ÿš",
Status: "open",
Type: "heliport",
},
},
{
name: "Small Airport",
input: Airport{
Name: "Test Small Airport",
LocalCode: "TST",
ISOCountry: "US",
Type: "small_airport",
},
expected: Airport{
Name: "Test Small Airport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "๐Ÿ›ฉ๏ธ",
Status: "open",
Type: "small_airport",
},
},
{
name: "Medium Airport",
input: Airport{
Name: "Test Medium Airport",
LocalCode: "TST",
ISOCountry: "US",
Type: "medium_airport",
},
expected: Airport{
Name: "Test Medium Airport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "โœˆ๏ธ",
Status: "open",
Type: "medium_airport",
},
},
{
name: "Large Airport",
input: Airport{
Name: "Test Large Airport",
LocalCode: "TST",
ISOCountry: "US",
Type: "large_airport",
},
expected: Airport{
Name: "Test Large Airport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "โœˆ๏ธ",
Status: "open",
Type: "large_airport",
},
},
{
name: "Balloonport",
input: Airport{
Name: "Test Balloonport",
LocalCode: "TST",
ISOCountry: "US",
Type: "balloonport",
},
expected: Airport{
Name: "Test Balloonport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
TypeEmoji: "๐ŸŽˆ",
Status: "open",
Type: "balloonport",
},
},
{
name: "Seaplane Base",
input: Airport{
Name: "Test Seaplane Base",
LocalCode: "TST",
ISOCountry: "US",
Type: "seaplane_base",
},
expected: Airport{
Name: "Test Seaplane Base",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
Status: "open",
Type: "seaplane_base",
TypeEmoji: "โš“",
},
},
{
name: "Closed Airport",
input: Airport{
Name: "Test Closed Airport",
LocalCode: "TST",
ISOCountry: "US",
Type: "closed",
},
expected: Airport{
Name: "Test Closed Airport",
LocalCode: "TST",
ISOCountry: "US",
Emoji: "๐Ÿ‡บ๐Ÿ‡ธ",
Status: "closed",
Type: "unknown",
TypeEmoji: "๐Ÿšง",
},
},
}

for _, tc := range tt {
t.Run("Airport Validation: "+tc.name, func(t *testing.T) {
result, err := Validate(tc.input)
if err != nil {
if tc.err == nil {
t.Fatalf("Unexpected error: %v", err)
}
if tc.err != err {
t.Fatalf("Expected error %v, got %v", tc.err, err)
}
return
}

if result != tc.expected {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}
Loading

0 comments on commit df7e99a

Please sign in to comment.