diff --git a/.github/workflows/cypress-test-basic.yaml b/.github/workflows/cypress-test-basic.yaml index 14453cce..7f0a1b39 100644 --- a/.github/workflows/cypress-test-basic.yaml +++ b/.github/workflows/cypress-test-basic.yaml @@ -1,14 +1,6 @@ name: End-to-end tests on: workflow_dispatch: - pull_request: - branches: - - main - - release - - dev - types: - - opened - - reopened jobs: cypress-run: runs-on: ubuntu-22.04 @@ -54,7 +46,10 @@ jobs: ${{ runner.os }}-build- - name: Start server run: | - cd + cd $GITHUB_WORKSPACE + touch fe.env + touch api.env + touch db.env docker compose up -d - name: Cypress run uses: cypress-io/github-action@v6 diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml new file mode 100644 index 00000000..b83c797c --- /dev/null +++ b/.github/workflows/deployment.yaml @@ -0,0 +1,111 @@ +name: Deployment + +on: + workflow_run: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Make db env file + uses: SpicyPizza/create-envfile@v1.3 + with: + envkey_POSTGRES_PASSWORD : ${{ secrets.POSTGRES_PASSWORD }} + envkey_POSTGRES_USER : ${{ secrets.POSTGRES_USER }} + envkey_POSTGRES_DB : ${{ secrets.POSTGRES_DB }} + directory: . + file_name: db.env + fail_on_empty: false + - name: Make api env files + uses: SpicyPizza/create-envfile@v1.3 + with: + envkey_DATABASE_URL : ${{ secrets.DATABASE_URL }} + envkey_DATABASE_PORT : ${{ secrets.DATABASE_PORT }} + envkey_DATABASE_NAME : ${{ secrets.DATABASE_NAME }} + envkey_DATABASE_USER : ${{ secrets.DATABASE_USER }} + envkey_DATABASE_PASSWORD : ${{ secrets.DATABASE_PASSWORD }} + envkey_COMPANY_EMAIL : ${{ secrets.COMPANY_EMAIL }} + envkey_COMPANY_AUTH : ${{ secrets.COMPANY_AUTH }} + directory: . + file_name: api.env + fail_on_empty: false + - name: Make fe env files + uses: SpicyPizza/create-envfile@v1.3 + with: + envkey_API_URL : ${{ secrets.API_URL }} + directory: . + file_name: fe.env + fail_on_empty: false + + - name: Docker compose build + run: | + cd $GITHUB_WORKSPACE + docker compose build + + - name: Make it a tar file + run: | + cd $GITHUB_WORKSPACE + docker save -o frontend.tar dispute-resolution-engine-frontend:latest + docker save -o api.tar api + docker save -o postgres.tar postgres + + - name: Install wireguard + run: sudo apt-get install wireguard + + - name: Create WG Config + run: | + sed -i -e "s@{{WG_PRIVATEKEY}}@${{ secrets.WG_PRIVATEKEY }}@" $GITHUB_WORKSPACE/tunnel.conf + sed -i -e "s@{{WG_ADDRESS}}@${{ secrets.WG_ADDRESS }}@" $GITHUB_WORKSPACE/tunnel.conf + sed -i -e "s@{{WG_DNS}}@${{ secrets.WG_DNS }}@" $GITHUB_WORKSPACE/tunnel.conf + sed -i -e "s@{{WG_PUBLICKEY}}@${{ secrets.WG_PUBLICKEY }}@" $GITHUB_WORKSPACE/tunnel.conf + sed -i -e "s@{{WG_ALLOWEDIPS}}@${{ secrets.WG_ALLOWEDIPS }}@" $GITHUB_WORKSPACE/tunnel.conf + sed -i -e "s@{{WG_ENDPOINT}}@${{ secrets.WG_ENDPOINT }}@" $GITHUB_WORKSPACE/tunnel.conf + sudo cp $GITHUB_WORKSPACE/tunnel.conf /etc/wireguard/ + + - name: WG Creating Tunnel + run: | + sudo apt install resolvconf + wg-quick up $GITHUB_WORKSPACE/tunnel.conf + + + - name: Send through the docker container using scp + uses: appleboy/scp-action@v0.1.4 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USERNAME }} + password: ${{ secrets.SSH_PASSWORD }} + port: ${{ secrets.SSH_PORT }} + source: "api.tar,frontend.tar,postgres.tar,docker-compose.yaml" + target: ./ + - name: Spin up docker image + uses: appleboy/ssh-action@v1.0.0 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USERNAME }} + password: ${{ secrets.SSH_PASSWORD }} + port: ${{ secrets.SSH_PORT }} + script: | + docker load -i frontend.tar + docker load -i api.tar + docker load -i postgres.tar + docker-compose up -d + cypress-test: + container: + image: cypress/included + needs: deploy + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Cypress run + uses: cypress-io/github-action@v2 + with: + wait-on: 'http://capstone-dre.dns.net.za' + wait-on-timeout: 300 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/go-test.yaml b/.github/workflows/go-test.yaml index 5e6a5a8f..9d141070 100644 --- a/.github/workflows/go-test.yaml +++ b/.github/workflows/go-test.yaml @@ -2,14 +2,6 @@ name: Go Test run-name: ${{ github.actor }} at ${{ github.event_name }} event on: workflow_dispatch: - pull_request: - branches: - - main - - release - - dev - types: - - opened - - reopened jobs: go-test: runs-on: ubuntu-latest @@ -21,4 +13,8 @@ jobs: - name: Run go test run: | cd api/__tests__ - go test \ No newline at end of file + go test + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/jest-test.yaml b/.github/workflows/jest-test.yaml index 4aa4ca71..133fccc2 100644 --- a/.github/workflows/jest-test.yaml +++ b/.github/workflows/jest-test.yaml @@ -2,14 +2,6 @@ name: Jest-Test run-name: ${{ github.actor }} at ${{ github.event_name }} event on: workflow_dispatch: - pull_request: - branches: - - main - - release - - dev - types: - - opened - - reopened jobs: jest-test: runs-on: ubuntu-latest @@ -28,4 +20,8 @@ jobs: - name: Run jest run: | cd frontend - yarn test \ No newline at end of file + yarn test + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index f9261f88..2fc03ce1 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -2,14 +2,6 @@ name: Linting run-name: ${{ github.actor }} at ${{ github.event_name }} event on: workflow_dispatch: - pull_request: - branches: - - main - - release - - dev - types: - - opened - - reopened jobs: jest-test: runs-on: ubuntu-latest diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..88a7c231 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,60 @@ +name: Unit-And-Integration-Tests +run-name: ${{ github.actor }} at ${{ github.event_name }} event +on: + workflow_dispatch: +jobs: + setup server: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: '18.20.3' + - name: Install dependencies + run: | + cd frontend + npm install -g yarn + yarn + - name: Build Docker + run: | + docker compose build + docker compose up -d + run jest tests: + runs-on: ubuntu-latest + depends-on: setup server + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: '18.20.3' + - name: Install dependencies + run: | + cd frontend + npm install -g yarn + yarn + - name: Run jest + run: | + cd frontend + yarn test + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + run go tests: + runs-on: ubuntu-latest + depends-on: setup server + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Run go test + run: | + cd api/__tests__ + go test + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index fb68221a..fb3c995f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - + diff --git a/api/__tests__/api-test.go b/api/__tests__/api-test.go deleted file mode 100644 index 004e2847..00000000 --- a/api/__tests__/api-test.go +++ /dev/null @@ -1,25 +0,0 @@ -package api - -import ( - "testing" - "api/api" - //"github.com/stretchr/testify/assert" -) - -type MockStorage struct{} - -// func TestNewServer(t *testing.T) { -// store, err := storage.NewPostgresStore() -// server := api.NewServer(":8080", store) -// server.Run() -// } -func TestRandomSales(t *testing.T) { - secret, err := api.RandomSalt(32) - if err != nil { - t.Errorf("RandomSalt() error = %v", err) - return - } - if len(secret) != 32 { - t.Errorf("RandomSalt() = %v, want %v", len(secret), 32) - } -} \ No newline at end of file diff --git a/api/__tests__/auth_test.go b/api/__tests__/auth_test.go new file mode 100644 index 00000000..171208e4 --- /dev/null +++ b/api/__tests__/auth_test.go @@ -0,0 +1,53 @@ +package api + +import ( + "api/handlers" + "api/db" // Import the package that contains the db symbo + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +// MockResponseWriter is used to capture the HTTP response +type MockResponseWriter struct { + httptest.ResponseRecorder +} + +func TestCreateUser(t *testing.T) { + DB := db.Init() + // Example of a valid request body + validRequestBody := `{"first_name":"John","surname":"Doe","birthdate":"1990-01-01","nationality":"Country","email":"john.doe@example.com"}` + // Example of an invalid request body (incomplete JSON) + invalidRequestBody := `{"first_name":"John"` + + tests := []struct { + name string + body string + expectedStatus int + }{ + {"Valid Request", validRequestBody, http.StatusOK}, + {"Invalid Request", invalidRequestBody, http.StatusBadRequest}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + request, err := http.NewRequest("POST", "/createuser", strings.NewReader(tt.body)) + if err != nil { + t.Fatal(err) + } + + // Use httptest.ResponseRecorder to capture the response + responseRecorder := httptest.NewRecorder() + handler := handlers.New(DB) + + // Serve the HTTP request to our handler + handler.CreateUser(responseRecorder, request) + + // Check the status code is what we expect + if status := responseRecorder.Code; status != tt.expectedStatus { + t.Errorf("handler returned wrong status code: got %v want %v", + status, tt.expectedStatus) + } + }) + } +} \ No newline at end of file diff --git a/api/__tests__/db_test.go b/api/__tests__/db_test.go new file mode 100644 index 00000000..d4b4171d --- /dev/null +++ b/api/__tests__/db_test.go @@ -0,0 +1,25 @@ +package api + +import ( + "api/db" + "api/handlers" + "net/http" + "github.com/gorilla/mux" + + "testing" +) + +type MockStorage struct{} + +func TestInit(t *testing.T) { + DB := db.Init() + if DB == nil { + t.Errorf("Expected db to be initialized, got nil") + } + h := handlers.New(DB) + router := mux.NewRouter() + + router.HandleFunc("/createAcc", h.CreateUser).Methods(http.MethodPost) + router.HandleFunc("/login", h.LoginUser).Methods(http.MethodPost) + +} \ No newline at end of file diff --git a/api/__tests__/model_test.go b/api/__tests__/model_test.go deleted file mode 100644 index c5e87517..00000000 --- a/api/__tests__/model_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package api - -import ( - "testing" - "api/model" - //"github.com/stretchr/testify/assert" -) - -// func TestNewServer(t *testing.T) { -// store, err := storage.NewPostgresStore() -// server := api.NewServer(":8080", store) -// server.Run() -// } -func TestAuthUserCreation(t *testing.T) { - user := model.AuthUser() - if user == nil { - t.Fatalf("AuthUser() = nil, want &LoginUser{}") - } -} \ No newline at end of file diff --git a/api/go.mod b/api/go.mod index 4bc59138..c6bd0aa1 100644 --- a/api/go.mod +++ b/api/go.mod @@ -10,7 +10,7 @@ require ( require ( github.com/gorilla/mux v1.8.1 golang.org/x/crypto v0.24.0 - gorm.io/driver/postgres v1.5.7 + gorm.io/driver/postgres v1.5.9 gorm.io/gorm v1.25.10 ) diff --git a/api/go.sum b/api/go.sum index 22fab403..380b65bb 100644 --- a/api/go.sum +++ b/api/go.sum @@ -186,6 +186,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= +gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=