diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..16e3f5d7576 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: ci + +on: + pull_request: + branches: [main] + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25.1" + + - name: Run tests + run: go test ./... -cover \ No newline at end of file diff --git a/README.md b/README.md index c2bec0368b7..dbcecc682b1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![alt text goes here](https://github.com/theguyoncloud/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) + # learn-cicd-starter (Notely) This repo contains the starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev). @@ -21,3 +23,5 @@ go build -o notely && ./notely *This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`. You do *not* need to set up a database or any interactivity on the webpage yet. Instructions for that will come later in the course! + +Yash 1.0.0 diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go new file mode 100644 index 00000000000..e2f365147b5 --- /dev/null +++ b/internal/auth/auth_test.go @@ -0,0 +1,104 @@ +package auth + +import ( + "net/http" + "testing" +) + +func TestGetAPIKey(t *testing.T) { + // Define the structure for our test cases + tests := []struct { + name string // Name of the test case + headers http.Header // Input headers + expectedKey string // The key we expect to get back + expectedError error // The specific error we expect (for sentinel errors) + errorString string // The error message string (for errors created on the fly) + }{ + { + name: "No Authorization Header", + headers: http.Header{}, // Empty headers + expectedKey: "", + expectedError: ErrNoAuthHeaderIncluded, + }, + { + name: "Malformed Header - Wrong Prefix", + headers: http.Header{ + "Authorization": []string{"Bearer my-token"}, + }, + expectedKey: "", + errorString: "malformed authorization header", + }, + { + name: "Malformed Header - Missing Token", + headers: http.Header{ + "Authorization": []string{"ApiKey"}, // Missing the actual key part + }, + expectedKey: "", + errorString: "malformed authorization header", + }, + { + name: "Valid API Key", + headers: http.Header{ + "Authorization": []string{"ApiKey my-secret-token"}, + }, + expectedKey: "my-secret-token", + expectedError: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotKey, err := GetAPIKey(tt.headers) + + // 1. Check if the returned key matches expectation + if gotKey != tt.expectedKey { + t.Errorf("GetAPIKey() key = %v, want %v", gotKey, tt.expectedKey) + } + + // 2. Check errors + // Scenario A: We expect no error + if tt.expectedError == nil && tt.errorString == "" { + if err != nil { + t.Errorf("GetAPIKey() unexpected error = %v", err) + } + return + } + + // Scenario B: We expect a specific Sentinel Error (ErrNoAuthHeaderIncluded) + if tt.expectedError != nil { + if err != tt.expectedError { + t.Errorf("GetAPIKey() error = %v, want %v", err, tt.expectedError) + } + return + } + + // Scenario C: We expect an error created with errors.New() inside the function + // Since these are new pointers, we compare the error string, not the error object itself + if tt.errorString != "" { + if err == nil || err.Error() != tt.errorString { + t.Errorf("GetAPIKey() error = %v, want error string %v", err, tt.errorString) + } + } + }) + } +} + +// Explanation of the Tests +// "No Authorization Header": Checks if the function correctly returns your exported variable ErrNoAuthHeaderIncluded when the map is empty. + +// "Malformed Header": + +// Wrong Prefix: Checks inputs like Bearer token instead of ApiKey token. + +// Missing Token: Checks inputs that have the prefix but no actual key (length < 2). + +// Note: Because your code generates a new error (errors.New("malformed...")) inside the function, we cannot compare it against a global variable. Instead, the test checks if the error message string matches. + +// "Valid API Key": Checks the happy path where the format is correct (ApiKey ), ensuring it returns the token and nil error. + +// How to run it +// Run this command in your terminal inside the directory: + +// Bash + +// go test -v \ No newline at end of file