gobuffalo / middleware

The default middleware for Buffalo apps
MIT License
1 stars 4 forks source link

bug: Unit test failure using Go 1.21.0 #3

Open lpar opened 1 year ago

lpar commented 1 year ago

Description

Description

When running go test with Go 1.21.0, there's a unit test failure.

Expected Behavior

PASS
ok      github.com/gobuffalo/mw-i18n/v2 0.281s

Actual Behavior

--- FAIL: Test_i18n_Localized_View (0.00s)
    i18n_test.go:165: 
            Error Trace:    /Users/meta/Go/src/github.com/gobuffalo/mw-i18n/i18n_test.go:165
            Error:          Not equal: 
                            expected: "Default"
                            actual  : "Hello!"

                            Diff:
                            --- Expected
                            +++ Actual
                            @@ -1 +1 @@
                            -Default
                            +Hello!
            Test:           Test_i18n_Localized_View

To Reproduce

Installed via rtx:

rtx install go@1.20.7
rtx install go@1.21.0

Test:

rtx use go@1.20.7
go test # succeeds
rtx use go@1.21.0
go test # fails

Additional Context

macOS on Apple M2 Max.

lpar commented 1 year ago

I think I've tracked down what's going on here. The unit test Test_i18n_Localized_View calls app() to set up the buffalo.App. That does:

// Setup and use translations:
t, err := i18n.New(os.DirFS("locales"), "en-US")
if err != nil {
    log.Fatal(err)
}
// Setup URL prefix Language extractor
t.LanguageExtractors = append(t.LanguageExtractors, i18n.URLPrefixLanguageExtractor)

app.Use(t.Middleware())
// …chunk of code omitted
noI18n := func(c buffalo.Context) error {
    return c.Render(200, r.HTML("localized_view.html"))
}
app.Middleware.Skip(t.Middleware(), noI18n)

The problem is, t.Middleware() returns an inline function:

func (t *Translator) Middleware() buffalo.MiddlewareFunc {
    return func(next buffalo.Handler) buffalo.Handler {
//…chunk of code omitted
    }
}

So each call to t.Middleware() returns a different instance of the inline function. Apparently this wasn't the case in previous versions of Go.

So then when MiddlewareStack.handler checks the list in ms.skips, the funcKey value doesn't match between the instance added to the skip list and the instance added to the router.

If the unit test is revised to use a single instance of the translator middleware function:

// Setup and use translations:
t, err := i18n.New(os.DirFS("locales"), "en-US")
if err != nil {
    log.Fatal(err)
}
translatorMiddleware := t.Middleware()
// Setup URL prefix Language extractor
t.LanguageExtractors = append(t.LanguageExtractors, i18n.URLPrefixLanguageExtractor)

app.Use(translatorMiddleware)
// …chunk of code omitted
// Disable i18n middleware
noI18n := func(c buffalo.Context) error {
    return c.Render(200, r.HTML("localized_view.html"))
}
app.Middleware.Skip(translatorMiddleware, noI18n)

...then the test passes.