From 062cfbf92e1afc47019b7b730114e97979af7298 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Thu, 15 May 2025 10:24:52 +0200 Subject: [PATCH 1/2] parser(test): rewrite tests to be easier to read --- go.mod | 8 ++++ go.sum | 10 +++++ parser_test.go | 112 ++++++++++++++++++++++++------------------------- 3 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 go.sum diff --git a/go.mod b/go.mod index c4e87d1..18e588c 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module github.com/napsy/go-css go 1.19 + +require github.com/stretchr/testify v1.10.0 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..713a0b4 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/parser_test.go b/parser_test.go index 57c2d3c..69319f0 100644 --- a/parser_test.go +++ b/parser_test.go @@ -3,6 +3,8 @@ package css import ( "fmt" "testing" + + "github.com/stretchr/testify/assert" ) func TestParseSimple(t *testing.T) { @@ -10,74 +12,72 @@ func TestParseSimple(t *testing.T) { style1: value1; style2: value2; }` - ex2 := `{ + + cases := []struct { + name string + CSS string + expected map[Rule]map[string]string + }{ + {"Single rule (simple)", ex1, map[Rule]map[string]string{ + "rule": { + "style1": "value1", + "style2": "value2", + }, + }}, + } + + for _, tt := range cases { + t.Run("GoodCSS", func(t *testing.T) { + css, err := Unmarshal([]byte(tt.CSS)) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, tt.expected, css, "Expected CSS to be equal") + }) + } +} + +func TestParseError(t *testing.T) { + ex1 := `{ style1: value1; }` - /* - ex3 := `rule { - style1: value1 - style2: value2; - }` - */ - ex4 := `rule { + + ex2 := `rule { style1: value1; style2:; }` - ex5 := `} + + ex3 := `rule { + style1: value1 + style2: value2; +}` + + ex4 := `} rule { style1: value1; style2:; }` + _ = ex3 + + cases := []struct { + name string + CSS string + }{ + {"Missing rule", ex1}, + {"Missing style", ex2}, + // TODO: this hsould not crash + //{"Statement Missing Semicolon", ex3}, + {"BlockEndsWithoutBeginning", ex4}, + } - t.Run("GoodCSS", func(t *testing.T) { - css, err := Unmarshal([]byte(ex1)) - if err != nil { - t.Fatal(err) - } - rule, ok := css["rule"] - if !ok { - t.Fatal("rule 'rule' doesn't exist") - } - - if value, ok := rule["style1"]; !ok { - t.Fatal("syle 'style1' doesn't exist") - } else if value != "value1" { - t.Fatalf("incorrect value for 'style1', got '%v', expected 'value1'", value) - } - - if value, ok := rule["style2"]; !ok { - t.Fatal("style 'style2' doesn't exist") - } else if value != "value2" { - t.Fatalf("incorrect value for 'style2', got '%v', expected 'value2'", value) - } - }) - - t.Run("MissingRule", func(t *testing.T) { - if _, err := Unmarshal([]byte(ex2)); err == nil { - t.Fatal("should error out") - } - }) - - /* - t.Run("StatementMissingSemicolon", func(t *testing.T) { - if css, err := Unmarshal([]byte(ex3)); err == nil { - for k, v := range css { - t.Logf("k: %v, v: %v\n", k, v) - } - t.Fatal("should error out") + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + if _, err := Unmarshal([]byte(tt.CSS)); err == nil { + t.Fatal("Should return error!") } }) - */ - t.Run("StyleWithoutValue", func(t *testing.T) { - if _, err := Unmarshal([]byte(ex4)); err == nil { - t.Fatal("should error out") - } - }) - t.Run("BlockEndsWithoutBeginning", func(t *testing.T) { - if _, err := Unmarshal([]byte(ex5)); err == nil { - t.Fatal("should error out") - } - }) + } } func TestParseHarder(t *testing.T) { From 50af3b2868dcd7860d271dddaa4ffa04b15a5677 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Thu, 15 May 2025 10:57:04 +0200 Subject: [PATCH 2/2] remove TestParseHarder --- parser_test.go | 130 +++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 79 deletions(-) diff --git a/parser_test.go b/parser_test.go index 69319f0..938aa11 100644 --- a/parser_test.go +++ b/parser_test.go @@ -13,6 +13,31 @@ func TestParseSimple(t *testing.T) { style2: value2; }` + ex2 := `rule1 { + style1: value1; + style2: value2; +} +rule2 { + style3: value3; +}` + + ex3 := `body { + font-family: 'Zil', serif; +}` + + ex4 := `rule1 { + style1: value1; + style2: value2; +} +rule1 { + style1: value3; +}` + + ex5 := `body { + background-image: url("gradient_bg.png"); + background-repeat: repeat-x; +}` + cases := []struct { name string CSS string @@ -24,6 +49,32 @@ func TestParseSimple(t *testing.T) { "style2": "value2", }, }}, + {"Multiple rules", ex2, map[Rule]map[string]string{ + "rule1": { + "style1": "value1", + "style2": "value2", + }, + "rule2": { + "style3": "value3", + }, + }}, + {"Property with spaces", ex3, map[Rule]map[string]string{ + "body": { + "font-family": "'Zil', serif", + }, + }}, + {"Merged rules", ex4, map[Rule]map[string]string{ + "rule1": { + "style1": "value3", + "style2": "value2", + }, + }}, + {"Real world css", ex5, map[Rule]map[string]string{ + "body": { + "background-image": "url(\"gradient_bg.png\")", + "background-repeat": "repeat-x", + }, + }}, } for _, tt := range cases { @@ -80,85 +131,6 @@ rule { } } -func TestParseHarder(t *testing.T) { - t.Run("MultiRules", func(t *testing.T) { - ex1 := `rule1 { - style1: value1; - style2: value2; -} -rule2 { - style3: value3; -}` - css, err := Unmarshal([]byte(ex1)) - if err != nil { - t.Fatal(err) - } - if len(css) != 2 { - t.Fatalf("expected 2 rules, got %d", len(css)) - } - - if _, ok := css["rule1"]; !ok { - t.Fatal("missing rule 'rule1'") - } - if _, ok := css["rule2"]; !ok { - t.Fatal("missing rule 'rule2'") - } - - if len(css["rule1"]) != 2 { - t.Fatalf("expected 2 styles for rule 'rule1', got %d", len(css["rule1"])) - } - - if len(css["rule2"]) != 1 { - t.Fatalf("expected 1 style for rule 'rule2', got %d", len(css["rule2"])) - } - }) - t.Run("PropertyWithSpace", func(t *testing.T) { - ex1 := `body { - font-family: 'Zil', serif; -}` - css, err := Unmarshal([]byte(ex1)) - if err != nil { - t.Fatal(err) - } - - if css["body"]["font-family"] != "'Zil', serif" { - t.Fatalf("invalid rule 'font-family', got %q", css["body"]["font-family"]) - } - }) - t.Run("MergedRules", func(t *testing.T) { - ex1 := `rule1 { - style1: value1; - style2: value2; -} -rule1 { - style1: value3; -}` - css, err := Unmarshal([]byte(ex1)) - if err != nil { - t.Fatal(err) - } - if len(css) != 1 { - t.Fatalf("there should be only one rule, got %d", len(css)) - } - if len(css["rule1"]) != 2 { - t.Fatalf("there should be two styles for rule 'rule1', got %d", len(css["rule1"])) - } - if css["rule1"]["style1"] != "value3" { - t.Fatalf("value of 'style1' should be 'value3' but got '%v'", css["rule1"]["style1"]) - } - }) - t.Run("RealWorldCSS", func(t *testing.T) { - ex1 := `body { - background-image: url("gradient_bg.png"); - background-repeat: repeat-x; -}` - _, err := Unmarshal([]byte(ex1)) - if err != nil { - t.Fatal(err) - } - }) -} - func TestParseSelectors(t *testing.T) { ex1 := `.rule { style1: value1;