Projeto bot pontos
This commit is contained in:
141
backend/internal/adapters/pontomais/client_test.go
Normal file
141
backend/internal/adapters/pontomais/client_test.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package pontomais
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"botpontos/internal/domain"
|
||||
)
|
||||
|
||||
type plainKeys struct{}
|
||||
|
||||
func (plainKeys) Decrypt(data []byte, _ int16) (string, error) { return string(data), nil }
|
||||
|
||||
var saoPaulo = domain.LoadLocation("America/Sao_Paulo")
|
||||
|
||||
func newServer(t *testing.T, historyStatus func(call int32) int) (*httptest.Server, *int32, *int32) {
|
||||
t.Helper()
|
||||
var logins, histories int32
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("POST /api/auth/sign_in", func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&logins, 1)
|
||||
var body authRequest
|
||||
_ = json.NewDecoder(r.Body).Decode(&body)
|
||||
if body.Password != "certa" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"token": "tok", "client_id": "cli", "data": map[string]string{"login": body.Login}})
|
||||
})
|
||||
mux.HandleFunc("GET /api/time_cards/current/last_cached", func(w http.ResponseWriter, r *http.Request) {
|
||||
call := atomic.AddInt32(&histories, 1)
|
||||
if status := historyStatus(call); status != http.StatusOK {
|
||||
w.WriteHeader(status)
|
||||
return
|
||||
}
|
||||
if r.Header.Get("access-token") != "tok" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"time_cards": []map[string]any{
|
||||
{"date": "2026-10-14", "time": "08:00:00"},
|
||||
{"date": "2026-10-14", "time": "12:00:00"},
|
||||
{"date": "2026-10-14", "time": "12:30:00", "disabled": true},
|
||||
}})
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
return server, &logins, &histories
|
||||
}
|
||||
|
||||
func newClient(server *httptest.Server) *Client {
|
||||
c := NewClient(server.URL+"/api/auth/sign_in", server.URL+"/api/time_cards/current/last_cached", 2*time.Second, plainKeys{})
|
||||
c.retryDelay = time.Millisecond
|
||||
return c
|
||||
}
|
||||
|
||||
func cred(password string) domain.Credential {
|
||||
return domain.Credential{UserID: 1, APIEmail: "a@b.c", EncryptedPassword: []byte(password), UpdatedAt: time.Unix(100, 0)}
|
||||
}
|
||||
|
||||
func TestHistoryParsesAndCachesSession(t *testing.T) {
|
||||
server, logins, _ := newServer(t, func(int32) int { return http.StatusOK })
|
||||
c := newClient(server)
|
||||
|
||||
points, err := c.History(context.Background(), cred("certa"), saoPaulo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(points) != 2 {
|
||||
t.Fatalf("esperados 2 pontos (o desabilitado é ignorado), vieram %d", len(points))
|
||||
}
|
||||
if got := points[0].OccurredAt.In(saoPaulo).Format("15:04"); got != "08:00" {
|
||||
t.Errorf("primeiro ponto = %s", got)
|
||||
}
|
||||
|
||||
if _, err := c.History(context.Background(), cred("certa"), saoPaulo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if *logins != 1 {
|
||||
t.Errorf("a sessão deveria ser reaproveitada; logins = %d", *logins)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryRetriesTransientError(t *testing.T) {
|
||||
server, _, histories := newServer(t, func(call int32) int {
|
||||
if call == 1 {
|
||||
return http.StatusBadGateway
|
||||
}
|
||||
return http.StatusOK
|
||||
})
|
||||
if _, err := newClient(server).History(context.Background(), cred("certa"), saoPaulo); err != nil {
|
||||
t.Fatalf("a segunda tentativa deveria funcionar: %v", err)
|
||||
}
|
||||
if *histories != 2 {
|
||||
t.Errorf("esperadas 2 chamadas ao histórico, vieram %d", *histories)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryRejectedCredential(t *testing.T) {
|
||||
server, _, _ := newServer(t, func(int32) int { return http.StatusOK })
|
||||
_, err := newClient(server).History(context.Background(), cred("errada"), saoPaulo)
|
||||
if !errors.Is(err, ErrAuthRejected) {
|
||||
t.Fatalf("esperado ErrAuthRejected, veio %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryRelogsAfterUnauthorized(t *testing.T) {
|
||||
server, logins, _ := newServer(t, func(call int32) int {
|
||||
if call == 2 {
|
||||
return http.StatusUnauthorized
|
||||
}
|
||||
return http.StatusOK
|
||||
})
|
||||
c := newClient(server)
|
||||
if _, err := c.History(context.Background(), cred("certa"), saoPaulo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := c.History(context.Background(), cred("certa"), saoPaulo); err != nil {
|
||||
t.Fatalf("deveria refazer o login após 401: %v", err)
|
||||
}
|
||||
if *logins != 2 {
|
||||
t.Errorf("esperados 2 logins, vieram %d", *logins)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
server, _, _ := newServer(t, func(int32) int { return http.StatusOK })
|
||||
c := newClient(server)
|
||||
if err := c.Validate(context.Background(), "a@b.c", "certa", saoPaulo); err != nil {
|
||||
t.Fatalf("credencial certa: %v", err)
|
||||
}
|
||||
if err := c.Validate(context.Background(), "a@b.c", "errada", saoPaulo); !errors.Is(err, ErrAuthRejected) {
|
||||
t.Fatalf("credencial errada: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user