sclevine / agouti

A WebDriver client and acceptance testing library for Go
MIT License
821 stars 105 forks source link

Configuring Chrome logging level #135

Closed myitcv closed 7 years ago

myitcv commented 7 years ago

Firstly, thank you for this package - great work!

I've searched various places, probably with the wrong terms, for an answer to the following question. Would appreciate any pointers.

Given the following:

package main

import (
    "fmt"

    "github.com/sclevine/agouti"
)

func main() {
    driver := agouti.ChromeDriver(
        agouti.ChromeOptions(
            "args", []string{
                "--headless",
                "--disable-gpu",
            },
        ),
        agouti.ChromeOptions(
            "binary", "/usr/bin/google-chrome",
        ),
    )

    if err := driver.Start(); err != nil {
        panic(err)
    }

    p, err := driver.NewPage()
    if err != nil {
        panic(err)
    }

    fmt.Println("BEFORE")
    printNewLogs(p)

    err = p.RunScript("console.log('an error')", nil, nil)
    if err != nil {
        panic(err)
    }

    fmt.Println("AFTER")
    printNewLogs(p)

    if err := driver.Stop(); err != nil {
        panic(err)
    }
}

func printNewLogs(p *agouti.Page) {
    logs, err := p.ReadNewLogs("browser")
    if err != nil {
        panic(err)
    }

    for _, l := range logs {
        fmt.Println(l.Message)
    }
}

I get the following output:

BEFORE
AFTER

But if I change the console.log to console.error I get the output:

BEFORE
AFTER
console-api 371:61 "an error"

So my question is, how can I configure Chrome so that the console.log messages are also returned by ReadNewLogs?

For what it's worth:

$ /usr/bin/google-chrome --version
Google Chrome 63.0.3236.7 dev

Thanks in advance.

sclevine commented 7 years ago

Last time I looked at this, only PhantomJS had support for reporting any type of JS logs. The integration test is here: https://github.com/sclevine/agouti/blob/master/internal/integration/page_test.go#L95

I would check LogTypes to see what logging channels headless Chrome supports, and then try each of those to see if any of them will report console.log messages.

If ChromeDriver has some special endpoint for retrieving these types of logs, you can always use page.Session().Send(...) to hit the endpoint manually. (I think this is unlikely though.)

If that doesn't work, you could do something terrible with RunScript.

myitcv commented 7 years ago

Thanks @sclevine.

Turns out this is possible:

Here's a complete, standalone example:

package main

import (
    "fmt"

    "github.com/sclevine/agouti"
)

func main() {
    driver := agouti.ChromeDriver(
        agouti.ChromeOptions(
            "args", []string{
                "headless",
                "disable-gpu",
                "no-default-browser-check",
                "no-sandbox",
                "no-first-run",
                "disable-default-apps",
                "disable-popup-blocking",
                "disable-translate",
                "disable-background-timer-throttling",
                "disable-renderer-backgrounding",
                "disable-device-discovery-notifications",
            },
        ),
        agouti.ChromeOptions(
            "binary", "/usr/bin/google-chrome",
        ),
        agouti.Desired(
            agouti.Capabilities{
                "loggingPrefs": map[string]string{
                    "browser": "INFO",
                },
            },
        ),
    )

    if err := driver.Start(); err != nil {
        panic(err)
    }

    p, err := driver.NewPage()
    if err != nil {
        panic(err)
    }

    err = p.RunScript("console.log('hello world');", nil, nil)
    if err != nil {
        panic(err)
    }

    printNewLogs(p, "browser")

    if err := driver.Stop(); err != nil {
        panic(err)
    }
}

func printNewLogs(p *agouti.Page, typ string) {
    logs, err := p.ReadNewLogs(typ)
    if err != nil {
        panic(err)
    }

    for _, l := range logs {
        fmt.Println(l.Message)
    }
}

Outputs:

console-api 371:61 "hello world"