Skip to content

Commit

Permalink
Fully qualify transpiler tests
Browse files Browse the repository at this point in the history
To simplify major version upgrades.
  • Loading branch information
bep committed Jun 8, 2023
1 parent 9f9f1c1 commit 5d595db
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 64 deletions.
17 changes: 17 additions & 0 deletions misc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package godartsass

import (
"testing"

qt "github.com/frankban/quicktest"
)

func TestHasScheme(t *testing.T) {
c := qt.New(t)

c.Assert(hasScheme("file:foo"), qt.Equals, true)
c.Assert(hasScheme("http:foo"), qt.Equals, true)
c.Assert(hasScheme("http://foo"), qt.Equals, true)
c.Assert(hasScheme("123:foo"), qt.Equals, false)
c.Assert(hasScheme("foo"), qt.Equals, false)
}
11 changes: 11 additions & 0 deletions transpiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ type Transpiler struct {
pending map[uint32]*call
}

// IsShutDown checks if all pending calls have been shut down.
// Used in tests.
func (t *Transpiler) IsShutDown() bool {
for _, p := range t.pending {
if p.Error != ErrShutdown {
return false
}
}
return true
}

// Result holds the result returned from Execute.
type Result struct {
CSS string
Expand Down
119 changes: 55 additions & 64 deletions transpiler_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package godartsass
package godartsass_test

import (
"encoding/json"
Expand All @@ -11,6 +11,8 @@ import (
"sync"
"testing"

"github.com/bep/godartsass"

qt "github.com/frankban/quicktest"
)

Expand Down Expand Up @@ -72,35 +74,35 @@ func TestTranspilerVariants(t *testing.T) {

for _, test := range []struct {
name string
opts Options
args Args
opts godartsass.Options
args godartsass.Args
expect interface{}
}{
{"Output style compressed", Options{}, Args{Source: "div { color: #ccc; }", OutputStyle: OutputStyleCompressed}, Result{CSS: "div{color:#ccc}"}},
{"Enable Source Map", Options{}, Args{Source: "div{color:blue;}", URL: "file://myproject/main.scss", OutputStyle: OutputStyleCompressed, EnableSourceMap: true}, Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"file://myproject/main.scss\"],\"names\":[],\"mappings\":\"AAAA\"}"}},
{"Enable Source Map with sources", Options{}, Args{Source: "div{color:blue;}", URL: "file://myproject/main.scss", OutputStyle: OutputStyleCompressed, EnableSourceMap: true, SourceMapIncludeSources: true}, Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"file://myproject/main.scss\"],\"names\":[],\"mappings\":\"AAAA\",\"sourcesContent\":[\"div{color:blue;}\"]}"}},
{"Sass syntax", Options{}, Args{
{"Output style compressed", godartsass.Options{}, godartsass.Args{Source: "div { color: #ccc; }", OutputStyle: godartsass.OutputStyleCompressed}, godartsass.Result{CSS: "div{color:#ccc}"}},
{"Enable Source Map", godartsass.Options{}, godartsass.Args{Source: "div{color:blue;}", URL: "file://myproject/main.scss", OutputStyle: godartsass.OutputStyleCompressed, EnableSourceMap: true}, godartsass.Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"file://myproject/main.scss\"],\"names\":[],\"mappings\":\"AAAA\"}"}},
{"Enable Source Map with sources", godartsass.Options{}, godartsass.Args{Source: "div{color:blue;}", URL: "file://myproject/main.scss", OutputStyle: godartsass.OutputStyleCompressed, EnableSourceMap: true, SourceMapIncludeSources: true}, godartsass.Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"file://myproject/main.scss\"],\"names\":[],\"mappings\":\"AAAA\",\"sourcesContent\":[\"div{color:blue;}\"]}"}},
{"Sass syntax", godartsass.Options{}, godartsass.Args{
Source: `$font-stack: Helvetica, sans-serif
$primary-color: #333
body
font: 100% $font-stack
color: $primary-color
`,
OutputStyle: OutputStyleCompressed,
SourceSyntax: SourceSyntaxSASS,
}, Result{CSS: "body{font:100% Helvetica,sans-serif;color:#333}"}},
{"Import resolver with source map", Options{}, Args{Source: "@import \"colors\";\ndiv { p { color: $white; } }", EnableSourceMap: true, ImportResolver: colorsResolver}, Result{CSS: "div p {\n color: white;\n}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"data:;charset=utf-8,@import%20%22colors%22;%0Adiv%20%7B%20p%20%7B%20color:%20$white;%20%7D%20%7D\",\"file:///mycolors/scss/colors_myfile.scss\"],\"names\":[],\"mappings\":\"AACM;EAAI,OCDC\"}"}},
OutputStyle: godartsass.OutputStyleCompressed,
SourceSyntax: godartsass.SourceSyntaxSASS,
}, godartsass.Result{CSS: "body{font:100% Helvetica,sans-serif;color:#333}"}},
{"Import resolver with source map", godartsass.Options{}, godartsass.Args{Source: "@import \"colors\";\ndiv { p { color: $white; } }", EnableSourceMap: true, ImportResolver: colorsResolver}, godartsass.Result{CSS: "div p {\n color: white;\n}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"data:;charset=utf-8,@import%20%22colors%22;%0Adiv%20%7B%20p%20%7B%20color:%20$white;%20%7D%20%7D\",\"file:///mycolors/scss/colors_myfile.scss\"],\"names\":[],\"mappings\":\"AACM;EAAI,OCDC\"}"}},

// Error cases
{"Invalid syntax", Options{}, Args{Source: "div { color: $white; }"}, false},
{"Import not found", Options{}, Args{Source: "@import \"foo\""}, false},
{"Import with ImportResolver, not found", Options{}, Args{Source: "@import \"foo\"", ImportResolver: colorsResolver}, false},
{"Error in ImportResolver.CanonicalizeURL", Options{}, Args{Source: "@import \"colors\";", ImportResolver: testImportResolver{name: "colors", failOnCanonicalizeURL: true}}, false},
{"Error in ImportResolver.Load", Options{}, Args{Source: "@import \"colors\";", ImportResolver: testImportResolver{name: "colors", failOnLoad: true}}, false},
{"Invalid OutputStyle", Options{}, Args{Source: "a", OutputStyle: "asdf"}, false},
{"Invalid SourceSyntax", Options{}, Args{Source: "a", SourceSyntax: "asdf"}, false},
{"Erro logging", Options{}, Args{Source: `@error "foo";`}, false},
{"Invalid syntax", godartsass.Options{}, godartsass.Args{Source: "div { color: $white; }"}, false},
{"Import not found", godartsass.Options{}, godartsass.Args{Source: "@import \"foo\""}, false},
{"Import with ImportResolver, not found", godartsass.Options{}, godartsass.Args{Source: "@import \"foo\"", ImportResolver: colorsResolver}, false},
{"Error in ImportResolver.CanonicalizeURL", godartsass.Options{}, godartsass.Args{Source: "@import \"colors\";", ImportResolver: testImportResolver{name: "colors", failOnCanonicalizeURL: true}}, false},
{"Error in ImportResolver.Load", godartsass.Options{}, godartsass.Args{Source: "@import \"colors\";", ImportResolver: testImportResolver{name: "colors", failOnLoad: true}}, false},
{"Invalid OutputStyle", godartsass.Options{}, godartsass.Args{Source: "a", OutputStyle: "asdf"}, false},
{"Invalid SourceSyntax", godartsass.Options{}, godartsass.Args{Source: "a", SourceSyntax: "asdf"}, false},
{"Erro logging", godartsass.Options{}, godartsass.Args{Source: `@error "foo";`}, false},
} {

test := test
Expand All @@ -116,7 +118,7 @@ body
_, err2 := transpiler.Execute(test.args)
c.Assert(err2.Error(), qt.Equals, err.Error())
} else {
expectedResult := test.expect.(Result)
expectedResult := test.expect.(godartsass.Result)
c.Assert(err, qt.IsNil)
// printJSON(result.SourceMap)
c.Assert(result, qt.Equals, expectedResult)
Expand All @@ -130,7 +132,7 @@ body
func TestDebugWarn(t *testing.T) {
c := qt.New(t)

args := Args{
args := godartsass.Args{
URL: "/a/b/c.scss",
Source: `
$color: #333;
Expand All @@ -144,12 +146,12 @@ body {
`,
}

var events []LogEvent
eventHandler := func(e LogEvent) {
var events []godartsass.LogEvent
eventHandler := func(e godartsass.LogEvent) {
events = append(events, e)
}

opts := Options{
opts := godartsass.Options{
LogEventHandler: eventHandler,
}

Expand All @@ -159,7 +161,7 @@ body {
c.Assert(err, qt.IsNil)

c.Assert(result.CSS, qt.Equals, "body {\n color: #333;\n}")
c.Assert(events, qt.DeepEquals, []LogEvent{
c.Assert(events, qt.DeepEquals, []godartsass.LogEvent{
{Type: 2, Message: "/a/b/c.scss:6:1: foo"},
{Type: 0, Message: "bar"},
})
Expand Down Expand Up @@ -188,13 +190,13 @@ content { color: #ccc; }
@import "content";
div { p { color: $moo; } }`

transpiler, clean := newTestTranspiler(c, Options{})
transpiler, clean := newTestTranspiler(c, godartsass.Options{})
defer clean()

result, err := transpiler.Execute(
Args{
godartsass.Args{
Source: src,
OutputStyle: OutputStyleCompressed,
OutputStyle: godartsass.OutputStyleCompressed,
IncludePaths: []string{dir1, dir2},
},
)
Expand All @@ -204,7 +206,7 @@ div { p { color: $moo; } }`

func TestTranspilerParallel(t *testing.T) {
c := qt.New(t)
transpiler, clean := newTestTranspiler(c, Options{})
transpiler, clean := newTestTranspiler(c, godartsass.Options{})
defer clean()
var wg sync.WaitGroup

Expand All @@ -218,7 +220,7 @@ $primary-color: #%03d;
div { color: $primary-color; }`, num)

result, err := transpiler.Execute(Args{Source: src})
result, err := transpiler.Execute(godartsass.Args{Source: src})
c.Check(err, qt.IsNil)
c.Check(result.CSS, qt.Equals, fmt.Sprintf("div {\n color: #%03d;\n}", num))
if c.Failed() {
Expand All @@ -233,14 +235,14 @@ div { color: $primary-color; }`, num)
func TestTranspilerParallelImportResolver(t *testing.T) {
c := qt.New(t)

createImportResolver := func(width int) ImportResolver {
createImportResolver := func(width int) godartsass.ImportResolver {
return testImportResolver{
name: "widths",
content: fmt.Sprintf(`$width: %d`, width),
}
}

transpiler, clean := newTestTranspiler(c, Options{})
transpiler, clean := newTestTranspiler(c, godartsass.Options{})
defer clean()

var wg sync.WaitGroup
Expand All @@ -252,8 +254,8 @@ func TestTranspilerParallelImportResolver(t *testing.T) {

for j := 0; j < 10; j++ {
for k := 0; k < 20; k++ {
args := Args{
OutputStyle: OutputStyleCompressed,
args := godartsass.Args{
OutputStyle: godartsass.OutputStyleCompressed,
ImportResolver: createImportResolver(j + i),
Source: `
@import "widths";
Expand All @@ -277,7 +279,7 @@ div { p { width: $width; } }`,

func TestTranspilerClose(t *testing.T) {
c := qt.New(t)
transpiler, _ := newTestTranspiler(c, Options{})
transpiler, _ := newTestTranspiler(c, godartsass.Options{})
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
Expand All @@ -295,14 +297,14 @@ div { color: $primary-color; }`, gor)
if num == 10 {
err := transpiler.Close()
if err != nil {
c.Check(err, qt.Equals, ErrShutdown)
c.Check(err, qt.Equals, godartsass.ErrShutdown)
}
}

result, err := transpiler.Execute(Args{Source: src})
result, err := transpiler.Execute(godartsass.Args{Source: src})

if err != nil {
c.Check(err, qt.Equals, ErrShutdown)
c.Check(err, qt.Equals, godartsass.ErrShutdown)
} else {
c.Check(err, qt.IsNil)
c.Check(result.CSS, qt.Equals, fmt.Sprintf("div {\n color: #%03d;\n}", gor))
Expand All @@ -316,22 +318,21 @@ div { color: $primary-color; }`, gor)
}
wg.Wait()

for _, p := range transpiler.pending {
c.Assert(p.Error, qt.Equals, ErrShutdown)
}
c.Assert(transpiler.IsShutDown(), qt.Equals, true)

}

func BenchmarkTranspiler(b *testing.B) {
type tester struct {
src string
expect string
transpiler *Transpiler
transpiler *godartsass.Transpiler
clean func()
}

newTester := func(b *testing.B, opts Options) tester {
newTester := func(b *testing.B, opts godartsass.Options) tester {
c := qt.New(b)
transpiler, clean := newTestTranspiler(c, Options{})
transpiler, clean := newTestTranspiler(c, godartsass.Options{})

return tester{
transpiler: transpiler,
Expand All @@ -343,7 +344,7 @@ func BenchmarkTranspiler(b *testing.B) {
defer t.clean()
b.ResetTimer()
for n := 0; n < b.N; n++ {
result, err := t.transpiler.Execute(Args{Source: t.src})
result, err := t.transpiler.Execute(godartsass.Args{Source: t.src})
if err != nil {
b.Fatal(err)
}
Expand All @@ -354,7 +355,7 @@ func BenchmarkTranspiler(b *testing.B) {
}

b.Run("SCSS", func(b *testing.B) {
t := newTester(b, Options{})
t := newTester(b, godartsass.Options{})
t.src = sassSample
t.expect = sassSampleTranspiled
runBench(b, t)
Expand All @@ -363,10 +364,10 @@ func BenchmarkTranspiler(b *testing.B) {
// This is the obviously much slower way of doing it.
b.Run("Start and Execute", func(b *testing.B) {
for n := 0; n < b.N; n++ {
t := newTester(b, Options{})
t := newTester(b, godartsass.Options{})
t.src = sassSample
t.expect = sassSampleTranspiled
result, err := t.transpiler.Execute(Args{Source: t.src})
result, err := t.transpiler.Execute(godartsass.Args{Source: t.src})
if err != nil {
b.Fatal(err)
}
Expand All @@ -378,13 +379,13 @@ func BenchmarkTranspiler(b *testing.B) {
})

b.Run("SCSS Parallel", func(b *testing.B) {
t := newTester(b, Options{})
t := newTester(b, godartsass.Options{})
t.src = sassSample
t.expect = sassSampleTranspiled
defer t.clean()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
result, err := t.transpiler.Execute(Args{Source: t.src})
result, err := t.transpiler.Execute(godartsass.Args{Source: t.src})
if err != nil {
b.Fatal(err)
}
Expand All @@ -396,29 +397,19 @@ func BenchmarkTranspiler(b *testing.B) {
})
}

func TestHasScheme(t *testing.T) {
c := qt.New(t)

c.Assert(hasScheme("file:foo"), qt.Equals, true)
c.Assert(hasScheme("http:foo"), qt.Equals, true)
c.Assert(hasScheme("http://foo"), qt.Equals, true)
c.Assert(hasScheme("123:foo"), qt.Equals, false)
c.Assert(hasScheme("foo"), qt.Equals, false)
}

func TestVersion(t *testing.T) {
c := qt.New(t)

version, err := Version(getSassEmbeddedFilename())
version, err := godartsass.Version(getSassEmbeddedFilename())
c.Assert(err, qt.IsNil)
c.Assert(version, qt.Not(qt.Equals), "")
c.Assert(version.ProtocolVersion, qt.Equals, "1.1.0")

}

func newTestTranspiler(c *qt.C, opts Options) (*Transpiler, func()) {
func newTestTranspiler(c *qt.C, opts godartsass.Options) (*godartsass.Transpiler, func()) {
opts.DartSassEmbeddedFilename = getSassEmbeddedFilename()
transpiler, err := Start(opts)
transpiler, err := godartsass.Start(opts)
c.Assert(err, qt.IsNil)

return transpiler, func() {
Expand All @@ -433,7 +424,7 @@ func getSassEmbeddedFilename() string {
return filename
}

return defaultDartSassEmbeddedFilename
return "dart-sass-embedded"
}

// used for debugging
Expand Down

0 comments on commit 5d595db

Please sign in to comment.