-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
433 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.