infoalloggi-monorepo/apps/backend/parser/parser_test.go

556 lines
17 KiB
Go
Raw Normal View History

package parser_test
import (
"backend/parser"
"backend/utils"
"fmt"
"testing"
"time"
)
func TestParseDettaglio(t *testing.T) {
// Helper to build expected date string
buildExpectedDate := func(day int, month int) string {
year := time.Now().Year()
currMonth := int(time.Now().Month())
if month < currMonth {
year++
}
return fmt.Sprintf("%d-%02d-%02d", year, month, day)
}
consegnaOct := utils.Ptr(10) // October
consegnaFeb := utils.Ptr(2) // February
tests := []struct {
name string
input string
currConsegna *int
wantDisp *string
wantPerm *[]int
wantPers *[]string
}{
{
name: "all fields present",
input: "disp:01/10 perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "all fields empty",
input: "disp: perm: persone:",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)), // defaults to 1st
wantPerm: nil,
wantPers: nil,
},
{
name: "disp missing value",
input: "disp: perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)), // defaults to 1st
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "perm missing",
input: "disp:01/10 perm: persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: nil,
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "persone missing",
input: "disp:01/10 perm:3-6 persone:",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: nil,
},
{
name: "invalid date - defaults to 1st",
input: "disp:bad_date perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)), // defaults to 1st
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "non-numeric perm",
input: "disp:01/10 perm:abc-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "trailing delimiter in perm",
input: "disp:01/10 perm:3- persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "leading delimiter in perm",
input: "disp:01/10 perm:-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "trailing delimiter in persone",
input: "disp:01/10 perm:3-6 persone:single/",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "leading delimiter in persone",
input: "disp:01/10 perm:3-6 persone:/single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "double delimiter in persone",
input: "disp:01/10 perm:3-6 persone:single//coppia",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single", "coppia"}),
},
{
name: "no disp field",
input: "perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "no persone field",
input: "disp:01/10 perm:3-6",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: nil,
},
{
name: "empty string",
input: "",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: nil,
wantPers: nil,
},
{
name: "whitespace in values",
input: "disp: 01/10 perm: 3-6 persone: single ",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "different order",
input: "persone:single perm:3-6 disp:01/10",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "double dash in perm",
input: "disp:01/10 perm:3--6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "tab separators",
input: "disp:01/10\tperm:3-6\tpersone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "special chars in persone",
input: "disp:01/10 perm:3-6 persone:single/coppia!",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single", "coppia!"}),
},
{
name: "duplicate disp - first wins",
input: "disp:01/10 disp:02/11 perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "no spaces between fields",
input: "disp:01/10perm:3-6persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(1, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "day only in disp",
input: "disp:15 perm:3-6 persone:single",
currConsegna: consegnaOct,
wantDisp: utils.Ptr(buildExpectedDate(15, 10)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "invalid day 31 for February",
input: "disp:31 perm:3-6 persone:single",
currConsegna: consegnaFeb,
wantDisp: utils.Ptr(buildExpectedDate(1, 2)),
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
{
name: "nil currConsegna",
input: "disp:01/10 perm:3-6 persone:single",
currConsegna: nil,
wantDisp: nil,
wantPerm: utils.Ptr([]int{3, 6}),
wantPers: utils.Ptr([]string{"single"}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
disp_time, perm_arr, persone_arr, _ := parser.ParseDettaglio(tt.input, tt.currConsegna)
// Handle *string comparison, including nil
if tt.wantDisp != nil {
if disp_time == nil {
t.Errorf("disp_time: got nil, want %v", *tt.wantDisp)
} else if *disp_time != *tt.wantDisp {
t.Errorf("disp_time: got %v, want %v", *disp_time, *tt.wantDisp)
}
} else if disp_time != nil {
t.Errorf("disp_time: got %v, want nil", *disp_time)
}
// Handle *[]int comparison, including nil
if tt.wantPerm != nil {
if perm_arr == nil || len(*perm_arr) != len(*tt.wantPerm) {
t.Errorf("perm_arr: got %v, want %v", perm_arr, *tt.wantPerm)
} else {
for i := range *perm_arr {
if (*perm_arr)[i] != (*tt.wantPerm)[i] {
t.Errorf("perm_arr[%d]: got %v, want %v", i, (*perm_arr)[i], (*tt.wantPerm)[i])
}
}
}
} else if perm_arr != nil && len(*perm_arr) != 0 {
t.Errorf("perm_arr: got %v, want nil", perm_arr)
}
// Handle *[]string comparison, including nil
if tt.wantPers != nil {
if persone_arr == nil || len(*persone_arr) != len(*tt.wantPers) {
t.Errorf("persone_arr: got %v, want %v", persone_arr, *tt.wantPers)
} else {
for i := range *persone_arr {
if (*persone_arr)[i] != (*tt.wantPers)[i] {
t.Errorf("persone_arr[%d]: got %v, want %v", i, (*persone_arr)[i], (*tt.wantPers)[i])
}
}
}
} else if persone_arr != nil && len(*persone_arr) != 0 {
t.Errorf("persone_arr: got %v, want nil", persone_arr)
}
})
}
}
func TestParseConsegna(t *testing.T) {
tests := []struct {
input *string
wantConsegna *int
}{
// Test all Italian month names
{
input: utils.Ptr("Gennaio"),
wantConsegna: utils.Ptr(1),
},
{
input: utils.Ptr("Febbraio"),
wantConsegna: utils.Ptr(2),
},
{
input: utils.Ptr("Marzo"),
wantConsegna: utils.Ptr(3),
},
{
input: utils.Ptr("Aprile"),
wantConsegna: utils.Ptr(4),
},
{
input: utils.Ptr("Maggio"),
wantConsegna: utils.Ptr(5),
},
{
input: utils.Ptr("Giugno"),
wantConsegna: utils.Ptr(6),
},
{
input: utils.Ptr("Luglio"),
wantConsegna: utils.Ptr(7),
},
{
input: utils.Ptr("Agosto"),
wantConsegna: utils.Ptr(8),
},
{
input: utils.Ptr("Settembre"),
wantConsegna: utils.Ptr(9),
},
{
input: utils.Ptr("Ottobre"),
wantConsegna: utils.Ptr(10),
},
{
input: utils.Ptr("Novembre"),
wantConsegna: utils.Ptr(11),
},
{
input: utils.Ptr("Dicembre"),
wantConsegna: utils.Ptr(12),
},
// Test "Libero" (should return current month)
{
input: utils.Ptr("Libero"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test nil input
{
input: nil,
wantConsegna: nil,
},
// Test empty string
{
input: utils.Ptr(""),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test lowercase (should return current month as default)
{
input: utils.Ptr("gennaio"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test with spaces
{
input: utils.Ptr("Gennaio "),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
{
input: utils.Ptr(" Gennaio"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test with special characters
{
input: utils.Ptr("Gennaio!"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test abbreviated forms
{
input: utils.Ptr("Gen"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
{
input: utils.Ptr("Feb"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test English month names
{
input: utils.Ptr("January"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test numeric strings
{
input: utils.Ptr("1"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test mixed cases
{
input: utils.Ptr("GEnNaIo"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
// Test completely unrelated strings
{
input: utils.Ptr("NotAMonth"),
wantConsegna: utils.Ptr(int(time.Now().Month())),
},
}
for _, tt := range tests {
gotConsegna := parser.ParseConsegna(tt.input)
if tt.wantConsegna != nil {
if gotConsegna == nil {
t.Errorf("got nil, want %v, input: %v", *tt.wantConsegna, tt.input)
} else if *gotConsegna != *tt.wantConsegna {
t.Errorf("got %v, want %v, input: %v", *gotConsegna, *tt.wantConsegna, tt.input)
}
} else if gotConsegna != nil {
t.Errorf("got %v, want nil, input: %v", *gotConsegna, tt.input)
}
}
}
func TestParsePrezzo(t *testing.T) {
tests := []struct {
input *string
want int
}{
{input: utils.Ptr("100"), want: 10000},
{input: utils.Ptr("€ 100"), want: 10000},
{input: utils.Ptr("100€"), want: 10000},
{input: utils.Ptr("€100"), want: 10000},
{input: utils.Ptr("100 €"), want: 10000},
{input: utils.Ptr("€ 100,50"), want: 10050},
{input: utils.Ptr("100,50€"), want: 10050},
{input: utils.Ptr("€100,50"), want: 10050},
{input: utils.Ptr("100,50 €"), want: 10050},
{input: utils.Ptr("€ 1.000"), want: 100000},
{input: utils.Ptr("1.000€"), want: 100000},
{input: utils.Ptr("€1.000"), want: 100000},
{input: utils.Ptr("1.000 €"), want: 100000},
{input: utils.Ptr("€ 1.000,50"), want: 100050},
{input: utils.Ptr("1.000,50€"), want: 100050},
{input: utils.Ptr("€1.000,50"), want: 100050},
{input: utils.Ptr("1.000,50 €"), want: 100050},
}
for _, tt := range tests {
got := parser.ParsePrezzo(tt.input)
if got != tt.want {
inputStr := ""
if tt.input != nil {
inputStr = *tt.input
}
t.Errorf("got %v, want %v, input: %v", got, tt.want, inputStr)
}
}
}
func TestProcessTipologia(t *testing.T) {
tests := []struct {
t1, t2 *string
want *string
}{
{t1: utils.Ptr("V"), want: utils.Ptr("Vendita")},
{t1: utils.Ptr("I"), want: utils.Ptr("Cessione")},
{t1: utils.Ptr("A"), t2: utils.Ptr("Residenziale"), want: utils.Ptr("Transitorio")},
{t1: utils.Ptr("A"), t2: utils.Ptr("Turistico"), want: utils.Ptr("Transitorio")},
{t1: utils.Ptr("A"), t2: utils.Ptr("Stanza"), want: utils.Ptr("Transitorio")},
{t1: utils.Ptr("A"), t2: nil, want: utils.Ptr("Stabile")},
{t1: nil, want: utils.Ptr("Errore")},
// Unknown t1 value
{t1: utils.Ptr("X"), want: utils.Ptr("Errore")},
// Lowercase t1 value
{t1: utils.Ptr("v"), want: utils.Ptr("Errore")},
// t1 is empty string
{t1: utils.Ptr(""), want: utils.Ptr("Errore")},
// t2 is empty string with t1 == "A"
{t1: utils.Ptr("A"), t2: utils.Ptr(""), want: utils.Ptr("Stabile")},
// t2 is unknown value with t1 == "A"
{t1: utils.Ptr("A"), t2: utils.Ptr("Commerciale"), want: utils.Ptr("Stabile")},
// t2 is lowercase valid value with t1 == "A"
{t1: utils.Ptr("A"), t2: utils.Ptr("residenziale"), want: utils.Ptr("Transitorio")},
// t2 is uppercase valid value with t1 == "A"
{t1: utils.Ptr("A"), t2: utils.Ptr("RESIDENZIALE"), want: utils.Ptr("Transitorio")},
// t2 is "Stanza" with extra spaces
{t1: utils.Ptr("A"), t2: utils.Ptr(" Stanza "), want: utils.Ptr("Transitorio")},
}
for _, tt := range tests {
got := parser.ParseTipologia(tt.t1, tt.t2)
if got == nil || *got != *tt.want {
t.Errorf("got %v, want %v, input t1: %v, t2: %v", *got, *tt.want, *tt.t1, *tt.t2)
}
}
}
func TestParseEmail(t *testing.T) {
tests := []struct {
input *string
want *string
}{
{input: utils.Ptr(" test@test.it "), want: utils.Ptr("test@test.it")},
{input: utils.Ptr("user@example.com"), want: utils.Ptr("user@example.com")},
{input: utils.Ptr("admin@domain.org"), want: utils.Ptr("admin@domain.org")},
{input: utils.Ptr("contact@company.co.uk"), want: utils.Ptr("contact@company.co.uk")},
{input: utils.Ptr("user.name@example.com"), want: utils.Ptr("user.name@example.com")},
{input: utils.Ptr("user+tag@example.com"), want: utils.Ptr("user+tag@example.com")},
{input: utils.Ptr("123@example.com"), want: utils.Ptr("123@example.com")},
// Emails with extra whitespace
{input: utils.Ptr(" email@test.com "), want: utils.Ptr("email@test.com")},
{input: utils.Ptr("\temail@test.com\t"), want: utils.Ptr("email@test.com")},
{input: utils.Ptr("\nemail@test.com\n"), want: utils.Ptr("email@test.com")},
// Invalid emails (should return nil)
{input: utils.Ptr("invalid-email"), want: nil},
{input: utils.Ptr("@domain.com"), want: nil},
{input: utils.Ptr("user@"), want: nil},
{input: utils.Ptr("user@domain"), want: nil},
{input: utils.Ptr("user.domain.com"), want: nil},
{input: utils.Ptr("user@@domain.com"), want: nil},
{input: utils.Ptr(""), want: nil},
{input: utils.Ptr(" "), want: nil},
{input: nil, want: nil},
// Edge cases
{input: utils.Ptr("a@b.co"), want: utils.Ptr("a@b.co")},
{input: utils.Ptr("test@test-domain.com"), want: utils.Ptr("test@test-domain.com")},
{input: utils.Ptr("user@sub.domain.com"), want: utils.Ptr("user@sub.domain.com")},
{input: utils.Ptr("lui.stra2006@gmail.com - LUIGINA"), want: utils.Ptr("lui.stra2006@gmail.com")},
}
for _, tt := range tests {
got := parser.ParseEmail(tt.input)
if tt.want == nil {
if got != nil {
inputStr := "nil"
if tt.input != nil {
inputStr = *tt.input
}
t.Errorf("got %q, want nil, input: %q", *got, inputStr)
}
} else {
if got == nil {
inputStr := "nil"
if tt.input != nil {
inputStr = *tt.input
}
t.Errorf("got nil, want %q, input: %q", *tt.want, inputStr)
} else if *got != *tt.want {
inputStr := "nil"
if tt.input != nil {
inputStr = *tt.input
}
t.Errorf("got %q, want %q, input: %q", *got, *tt.want, inputStr)
}
}
}
}