feat: Use log/slog for logging to file or stdout

Switched to Go1.21 to use the log/slog package for strutctured logging.

TODO: Log messages that are stringifying objects can now use strutctured
output.

TODO: Customise log levels for different messages.

Fix tests
This commit is contained in:
Ananth Bhaskararaman 2023-12-07 22:02:00 +05:30 committed by Thomas Buckley-Houston
parent d32ae0ba5a
commit f93a4d12cf
13 changed files with 184 additions and 179 deletions

View File

@ -1,90 +1,88 @@
# How to setup Browsh's build system for Mac # How to setup Browsh's build system for Mac
If you just want to try Browsh, you can use [Homebrew](https://brew.sh/) (check out the [installation page](https://www.brow.sh/docs/installation/) at the [official site](https://www.brow.sh/)).
If you want to try Browsh, you can use [Homebrew](https://brew.sh/).
Check out the [installation page](https://www.brow.sh/docs/installation/) at the
[official site](https://www.brow.sh/)).
## Installations ## Installations
You need Go, Firefox and Node.js to run Browsh. You need Go, Firefox and Node.js to run Browsh.
### Install Go ### Install Go
Follow the [installation guide](https://golang.org/doc/install) (you can use an installer). Follow the [installation guide](https://golang.org/doc/install) (you can use an installer).
#### Ensure your GOPATH is set
```sh
$ echo $GOPATH
/Users/uesr_name/go
$ # anywhere is ok, but make sure it's not none
```
#### Ensure you have `$GOPATH/src` and `$GOPATH/bin` folders
If you're not sure if you have these folders, run:
```sh
$ mkdir "$GOPATH/src"
$ mkdir "$GOPATH/bin"
```
### Install Firefox ### Install Firefox
Follow the official [guide](https://support.mozilla.org/en-US/kb/how-download-and-install-firefox-mac) to install Firefox.
Follow the official [guide](https://support.mozilla.org/en-US/kb/how-download-and-install-firefox-mac)
to install Firefox.
#### Include Firefox to your PATH #### Include Firefox to your PATH
The `firefox` executable is probably at `/Applications/Firefox.app/Contents/MacOS`. You need to add it to your `PATH` so that Browsh can create new instances of Firefox.
The `firefox` executable is probably at `/Applications/Firefox.app/Contents/MacOS`.
You need to add it to your `PATH` so that Browsh can create new instances of Firefox.
### Install Node.js ### Install Node.js
Follow the [official downloading page](https://nodejs.org/en/download/). Follow the [official downloading page](https://nodejs.org/en/download/).
> v8.11.4. is currently recommended for working with Browsh (?) Use Nodejs > v8.11.4 with Browsh.
#### Install web-ext globally #### Install web-ext globally
It's a Mozilla's handy tool for working with Firefox web extensions:
```sh It's a Mozilla tool for working with Firefox web extensions:
$ npm install -g web-ext
```shell
npm install -g web-ext
``` ```
## Setting up your Browsh ## Setting up your Browsh
### Clone Browsh ### Clone Browsh
Fork Browsh to your Github account. Clone it to `$GOPATH/src`.
Fork Browsh to your Github account.
Clone it to a directory of your choice.
We will refer to this directory as `$browsh` for the rest of the guide.
### Install NPM packages ### Install NPM packages
```shell ```shell
$ cd "$GOPATH/src/browsh/webext" cd "$browsh/webext"
$ npm install npm install
``` ```
### Run the build script ### Run the build script
```sh ```sh
$ cd "$GOPATH/src/browsh" cd "$browsh"
$ # install several required package" # install required package"
$ ./interfacer/contrib/build_browsh.sh ./interfacer/contrib/build_browsh.sh
``` ```
## Running Browsh from source ## Running Browsh from source
Now that you have all of the required dependencies installed, we can run Browsh. Open three terminals and do the follows:
Now that you have the required dependencies installed, we can run Browsh.
Open three terminals and do the following:
### Terminal 1 (builds JavaScript) ### Terminal 1 (builds JavaScript)
```sh ```sh
$ cd "$GOPATH/src/browsh/webext" cd "$browsh/webext
$ # create a dist folder inside the webext folder. # create a dist folder inside the webext folder.
$ npx webpack --watch npx webpack --watch
``` ```
### Terminal 2 (handles Firefox web extension) ### Terminal 2 (handles Firefox web extension)
```sh ```sh
$ # the dist folder is created in the first terminal mkdir "$browsh/webext/dist"
$ cd "$GOPATH/src/browsh/webext/dist" cd "$browsh/webext/dist"
$ # create a dist folder inside the webext folder. npx webpack --watch
$ npx webpack --watch
``` ```
### Terminal 3 (Displays Browsh) ### Terminal 3 (Displays Browsh)
```sh ```sh
$ cd "$GOPATH/src/browsh/interfacer" cd "$browsh/interfacer"
$ go run ./cmd/browsh/main.go --firefox.use-existing --debug go run ./cmd/browsh/main.go --firefox.use-existing --debug
``` ```

View File

@ -1,6 +1,6 @@
module github.com/browsh-org/browsh/interfacer module github.com/browsh-org/browsh/interfacer
go 1.18 go 1.21
require ( require (
github.com/NYTimes/gziphandler v1.1.1 github.com/NYTimes/gziphandler v1.1.1

View File

@ -58,6 +58,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
@ -98,6 +99,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -110,6 +112,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -143,9 +146,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
@ -164,6 +169,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
@ -182,6 +188,7 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w= github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y= github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y=
github.com/spf13/afero v1.9.0 h1:sFSLUHgxdnN32Qy38hK3QkYBFXZj9DKjVjCUCtD7juY= github.com/spf13/afero v1.9.0 h1:sFSLUHgxdnN32Qy38hK3QkYBFXZj9DKjVjCUCtD7juY=
@ -506,6 +513,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -3,7 +3,7 @@ package browsh
import ( import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io/ioutil" "log/slog"
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
@ -44,40 +44,18 @@ var (
) )
func setupLogging() { func setupLogging() {
dir, err := os.Getwd() out := os.Stderr
if err != nil { if *isDebug {
Shutdown(err) dir, err := os.Getwd()
} if err != nil {
logfile = fmt.Sprintf(filepath.Join(dir, "debug.log")) Shutdown(err)
fmt.Println("Logging to: " + logfile)
if _, err := os.Stat(logfile); err == nil {
os.Truncate(logfile, 0)
}
if err != nil {
Shutdown(err)
}
}
// Log for general purpose logging
// TODO: accept generic types
func Log(msg string) {
if !*isDebug {
return
}
if viper.GetBool("http-server-mode") && !IsTesting {
fmt.Println(msg)
} else {
f, oErr := os.OpenFile(logfile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if oErr != nil {
Shutdown(oErr)
} }
defer f.Close() logfile = fmt.Sprintf(filepath.Join(dir, "debug.log"))
if out, err = os.OpenFile(logfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644); err != nil {
msg = msg + "\n" Shutdown(err)
if _, wErr := f.WriteString(msg); wErr != nil {
Shutdown(wErr)
} }
} }
slog.SetDefault(slog.New(slog.NewTextHandler(out, nil)))
} }
// Initialise browsh // Initialise browsh
@ -85,9 +63,7 @@ func Initialise() {
if IsTesting { if IsTesting {
*isDebug = true *isDebug = true
} }
if *isDebug { setupLogging()
setupLogging()
}
loadConfig() loadConfig()
} }
@ -95,9 +71,9 @@ func Initialise() {
func Shutdown(err error) { func Shutdown(err error) {
if *isDebug { if *isDebug {
if e, ok := err.(*errors.Error); ok { if e, ok := err.(*errors.Error); ok {
Log(fmt.Sprintf(e.ErrorStack())) slog.Error(e.ErrorStack())
} else { } else {
Log(err.Error()) slog.Error(err.Error())
} }
} }
exitCode := 0 exitCode := 0
@ -111,12 +87,15 @@ func Shutdown(err error) {
os.Exit(exitCode) os.Exit(exitCode)
} }
func Log(message string) {
}
func saveScreenshot(base64String string) { func saveScreenshot(base64String string) {
dec, err := base64.StdEncoding.DecodeString(base64String) dec, err := base64.StdEncoding.DecodeString(base64String)
if err != nil { if err != nil {
Shutdown(err) Shutdown(err)
} }
file, err := ioutil.TempFile(os.TempDir(), "browsh-screenshot") file, err := os.CreateTemp("", "browsh-screenshot")
if err != nil { if err != nil {
Shutdown(err) Shutdown(err)
} }
@ -154,9 +133,14 @@ func TTYStart(injectedScreen tcell.Screen) {
screen = injectedScreen screen = injectedScreen
setupTcell() setupTcell()
writeString(1, 0, logo, tcell.StyleDefault) writeString(1, 0, logo, tcell.StyleDefault)
writeString(0, 15, "Starting Browsh v"+browshVersion+", the modern text-based web browser.", tcell.StyleDefault) writeString(
0,
15,
"Starting Browsh v"+browshVersion+", the modern text-based web browser.",
tcell.StyleDefault,
)
StartFirefox() StartFirefox()
Log("Starting Browsh CLI client") slog.Info("Starting Browsh CLI client")
go readStdin() go readStdin()
startWebSocketServer() startWebSocketServer()
} }

View File

@ -3,6 +3,7 @@ package browsh
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"strings" "strings"
@ -30,7 +31,7 @@ func startWebSocketServer() {
serverMux := http.NewServeMux() serverMux := http.NewServeMux()
serverMux.HandleFunc("/", webSocketServer) serverMux.HandleFunc("/", webSocketServer)
port := viper.GetString("browsh.websocket-port") port := viper.GetString("browsh.websocket-port")
Log("Starting websocket server...") slog.Info("Starting websocket server...")
if netErr := http.ListenAndServe(":"+port, serverMux); netErr != nil { if netErr := http.ListenAndServe(":"+port, serverMux); netErr != nil {
Shutdown(errors.New(fmt.Errorf("Error starting websocket server: %v", netErr))) Shutdown(errors.New(fmt.Errorf("Error starting websocket server: %v", netErr)))
} }
@ -38,7 +39,7 @@ func startWebSocketServer() {
func sendMessageToWebExtension(message string) { func sendMessageToWebExtension(message string) {
if !IsConnectedToWebExtension { if !IsConnectedToWebExtension {
Log("Webextension not connected. Message not sent: " + message) slog.Info("Webextension not connected. Message not sent: " + message)
return return
} }
stdinChannel <- message stdinChannel <- message
@ -53,12 +54,12 @@ func webSocketReader(ws *websocket.Conn) {
handleWebextensionCommand(message) handleWebextensionCommand(message)
if err != nil { if err != nil {
if websocket.IsCloseError(err, websocket.CloseGoingAway) { if websocket.IsCloseError(err, websocket.CloseGoingAway) {
Log("Socket reader detected that the browser closed the websocket") slog.Info("Socket reader detected that the browser closed the websocket")
triggerSocketWriterClose() triggerSocketWriterClose()
return return
} }
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) { if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
Log("Socket reader detected that the connection unexpectedly dissapeared") slog.Info("Socket reader detected that the connection unexpectedly dissapeared")
triggerSocketWriterClose() triggerSocketWriterClose()
return return
} }
@ -89,7 +90,7 @@ func handleWebextensionCommand(message []byte) {
case "/screenshot": case "/screenshot":
saveScreenshot(parts[1]) saveScreenshot(parts[1])
default: default:
Log("WEBEXT: " + string(message)) slog.Info("WEBEXT: " + string(message))
} }
} }
@ -102,13 +103,13 @@ func handleRawFrameTextCommands(parts []string) {
Shutdown(err) Shutdown(err)
} }
if incoming.RequestID != "" { if incoming.RequestID != "" {
Log("Raw text for " + incoming.RequestID) slog.Info("Raw text for " + incoming.RequestID)
rawTextRequests.store(incoming.RequestID, incoming.RawJSON) rawTextRequests.store(incoming.RequestID, incoming.RawJSON)
} else { } else {
Log("Raw text but no associated request ID") slog.Info("Raw text but no associated request ID")
} }
} else { } else {
Log("WEBEXT: " + strings.Join(parts[0:], ",")) slog.Info("WEBEXT: " + strings.Join(parts[0:], ","))
} }
} }
@ -117,7 +118,8 @@ func handleRawFrameTextCommands(parts []string) {
// automatically notice until it actually needs to send something. So we force that // automatically notice until it actually needs to send something. So we force that
// by sending this NOOP text. // by sending this NOOP text.
// TODO: There's a potential race condition because new connections share the same // TODO: There's a potential race condition because new connections share the same
// Go channel. So we need to setup a new channel for every connection. //
// Go channel. So we need to setup a new channel for every connection.
func triggerSocketWriterClose() { func triggerSocketWriterClose() {
stdinChannel <- "BROWSH CLIENT FORCING CLOSE OF WEBSOCKET WRITER" stdinChannel <- "BROWSH CLIENT FORCING CLOSE OF WEBSOCKET WRITER"
} }
@ -128,12 +130,12 @@ func webSocketWriter(ws *websocket.Conn) {
defer ws.Close() defer ws.Close()
for { for {
message = <-stdinChannel message = <-stdinChannel
Log(fmt.Sprintf("TTY sending: %s", message)) slog.Info(fmt.Sprintf("TTY sending: %s", message))
if err := ws.WriteMessage(websocket.TextMessage, []byte(message)); err != nil { if err := ws.WriteMessage(websocket.TextMessage, []byte(message)); err != nil {
if err == websocket.ErrCloseSent { if err == websocket.ErrCloseSent {
Log("Socket writer detected that the browser closed the websocket") slog.Info("Socket writer detected that the browser closed the websocket")
} else { } else {
Log("Socket writer detected unexpected closure of websocket") slog.Info("Socket writer detected unexpected closure of websocket")
} }
return return
} }
@ -141,7 +143,7 @@ func webSocketWriter(ws *websocket.Conn) {
} }
func webSocketServer(w http.ResponseWriter, r *http.Request) { func webSocketServer(w http.ResponseWriter, r *http.Request) {
Log("Incoming web request from browser") slog.Info("Incoming web request from browser")
ws, err := upgrader.Upgrade(w, r, nil) ws, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
Shutdown(err) Shutdown(err)

View File

@ -3,6 +3,7 @@ package browsh
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"log/slog"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -15,7 +16,7 @@ import (
var ( var (
configFilename = "config.toml" configFilename = "config.toml"
isDebug = pflag.Bool("debug", false, "Log to ./debug.log") isDebug = pflag.Bool("debug", false, "slog.Info to ./debug.log")
timeLimit = pflag.Int("time-limit", 0, "Kill Browsh after the specified number of seconds") timeLimit = pflag.Int("time-limit", 0, "Kill Browsh after the specified number of seconds")
_ = pflag.Bool("http-server-mode", false, "Run as an HTTP service") _ = pflag.Bool("http-server-mode", false, "Run as an HTTP service")
@ -79,20 +80,18 @@ func setDefaults() {
func loadConfig() { func loadConfig() {
dir := getConfigDir() dir := getConfigDir()
fullPath := filepath.Join(dir, configFilename) fullPath := filepath.Join(dir, configFilename)
Log("Looking in " + fullPath + " for config.") slog.Info("Looking in " + fullPath + " for config.")
viper.SetConfigType("toml") viper.SetConfigType("toml")
viper.SetConfigName(strings.Trim(configFilename, ".toml")) viper.SetConfigName(strings.Trim(configFilename, ".toml"))
viper.AddConfigPath(dir) viper.AddConfigPath(dir)
viper.AddConfigPath(".") viper.AddConfigPath(".")
setDefaults() setDefaults()
// First load the sample config in case the user hasn't updated any new fields // First load the sample config in case the user hasn't updated any new fields
err := viper.ReadConfig(bytes.NewBuffer([]byte(configSample))) if err := viper.ReadConfig(bytes.NewBuffer([]byte(configSample))); err != nil {
if err != nil {
panic(fmt.Errorf("Config file error: %s \n", err)) panic(fmt.Errorf("Config file error: %s \n", err))
} }
// Then load the users own config file, overwriting the sample config // Then load the users own config file, overwriting the sample config
err = viper.MergeInConfig() if err := viper.MergeInConfig(); err != nil {
if err != nil {
panic(fmt.Errorf("Config file error: %s \n", err)) panic(fmt.Errorf("Config file error: %s \n", err))
} }
viper.BindPFlags(pflag.CommandLine) viper.BindPFlags(pflag.CommandLine)

View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log/slog"
"net" "net"
"os" "os"
"os/exec" "os/exec"
@ -59,7 +60,7 @@ var (
) )
func startHeadlessFirefox() { func startHeadlessFirefox() {
Log("Starting Firefox in headless mode") slog.Info("Starting Firefox in headless mode")
checkIfFirefoxIsAlreadyRunning() checkIfFirefoxIsAlreadyRunning()
firefoxPath := ensureFirefoxBinary() firefoxPath := ensureFirefoxBinary()
ensureFirefoxVersion(firefoxPath) ensureFirefoxVersion(firefoxPath)
@ -69,11 +70,11 @@ func startHeadlessFirefox() {
} }
profile := viper.GetString("firefox.profile") profile := viper.GetString("firefox.profile")
if profile != "browsh-default" { if profile != "browsh-default" {
Log("Using profile: " + profile) slog.Info("Using profile: " + profile)
args = append(args, "-P", profile) args = append(args, "-P", profile)
} else { } else {
profilePath := getFirefoxProfilePath() profilePath := getFirefoxProfilePath()
Log("Using default profile at: " + profilePath) slog.Info("Using default profile at: " + profilePath)
args = append(args, "--profile", profilePath) args = append(args, "--profile", profilePath)
} }
firefoxProcess := exec.Command(firefoxPath, args...) firefoxProcess := exec.Command(firefoxPath, args...)
@ -87,7 +88,7 @@ func startHeadlessFirefox() {
} }
in := bufio.NewScanner(stdout) in := bufio.NewScanner(stdout)
for in.Scan() { for in.Scan() {
Log("FF-CONSOLE: " + in.Text()) slog.Info("FF-CONSOLE: " + in.Text())
} }
} }
@ -114,7 +115,7 @@ func ensureFirefoxBinary() string {
path = getFirefoxPath() path = getFirefoxPath()
} }
} }
Log("Using Firefox at: " + path) slog.Info("Using Firefox at: " + path)
if _, err := os.Stat(path); os.IsNotExist(err) { if _, err := os.Stat(path); os.IsNotExist(err) {
Shutdown(errors.New("Firefox binary not found: " + path)) Shutdown(errors.New("Firefox binary not found: " + path))
} }
@ -155,12 +156,12 @@ func versionOrdinal(version string) string {
// because I haven't been able to recreate the way `web-ext` injects an unsigned // because I haven't been able to recreate the way `web-ext` injects an unsigned
// extension. // extension.
func startWERFirefox() { func startWERFirefox() {
Log("Attempting to start headless Firefox with `web-ext`") slog.Info("Attempting to start headless Firefox with `web-ext`")
if IsConnectedToWebExtension { if IsConnectedToWebExtension {
Shutdown(errors.New("There appears to already be an existing Web Extension connection")) Shutdown(errors.New("There appears to already be an existing Web Extension connection"))
} }
checkIfFirefoxIsAlreadyRunning() checkIfFirefoxIsAlreadyRunning()
var rootDir = Shell("git rev-parse --show-toplevel") rootDir := Shell("git rev-parse --show-toplevel")
args := []string{ args := []string{
"run", "run",
"--firefox=" + rootDir + "/webext/contrib/firefoxheadless.sh", "--firefox=" + rootDir + "/webext/contrib/firefoxheadless.sh",
@ -185,9 +186,9 @@ func startWERFirefox() {
strings.Contains(in.Text(), "dbus") { strings.Contains(in.Text(), "dbus") {
continue continue
} }
Log("FF-CONSOLE: " + in.Text()) slog.Info("FF-CONSOLE: " + in.Text())
} }
Log("WER Firefox unexpectedly closed") slog.Info("WER Firefox unexpectedly closed")
} }
// Connect to Firefox's Marionette service. // Connect to Firefox's Marionette service.
@ -206,7 +207,7 @@ func firefoxMarionette() {
conn net.Conn conn net.Conn
) )
connected := false connected := false
Log("Attempting to connect to Firefox Marionette") slog.Info("Attempting to connect to Firefox Marionette")
start := time.Now() start := time.Now()
for time.Since(start) < 30*time.Second { for time.Since(start) < 30*time.Second {
conn, err = net.Dial("tcp", "127.0.0.1:2828") conn, err = net.Dial("tcp", "127.0.0.1:2828")
@ -262,14 +263,14 @@ func readMarionette() {
buffer := make([]byte, 4096) buffer := make([]byte, 4096)
count, err := marionette.Read(buffer) count, err := marionette.Read(buffer)
if err != nil { if err != nil {
Log("Error reading from Marionette connection") slog.Info("Error reading from Marionette connection")
return return
} }
Log("FF-MRNT: " + string(buffer[:count])) slog.Info("FF-MRNT: " + string(buffer[:count]))
} }
func sendFirefoxCommand(command string, args map[string]interface{}) { func sendFirefoxCommand(command string, args map[string]interface{}) {
Log("Sending `" + command + "` to Firefox Marionette") slog.Info("Sending `" + command + "` to Firefox Marionette")
fullCommand := []interface{}{0, ffCommandCount, command, args} fullCommand := []interface{}{0, ffCommandCount, command, args}
marshalled, _ := json.Marshal(fullCommand) marshalled, _ := json.Marshal(fullCommand)
message := fmt.Sprintf("%d:%s", len(marshalled), marshalled) message := fmt.Sprintf("%d:%s", len(marshalled), marshalled)

View File

@ -4,6 +4,7 @@ package browsh
import ( import (
"fmt" "fmt"
"log/slog"
"strings" "strings"
"github.com/go-errors/errors" "github.com/go-errors/errors"
@ -46,13 +47,13 @@ func getWindowsFirefoxVersionString() string {
Shutdown(errors.New("Error reading Windows registry: " + fmt.Sprintf("%s", err))) Shutdown(errors.New("Error reading Windows registry: " + fmt.Sprintf("%s", err)))
} }
Log("Windows registry Firefox version: " + versionString) slog.Info("Windows registry Firefox version: " + versionString)
return versionString return versionString
} }
func getFirefoxFlavor() string { func getFirefoxFlavor() string {
var flavor = "null" flavor := "null"
k, err := registry.OpenKey( k, err := registry.OpenKey(
registry.LOCAL_MACHINE, registry.LOCAL_MACHINE,
`Software\Mozilla\Mozilla Firefox`, `Software\Mozilla\Mozilla Firefox`,

View File

@ -3,6 +3,7 @@ package browsh
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log/slog"
"unicode" "unicode"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
@ -78,7 +79,9 @@ func parseJSONFrameText(jsonString string) {
Shutdown(err) Shutdown(err)
} }
if !isTabPresent(incoming.Meta.TabID) { if !isTabPresent(incoming.Meta.TabID) {
Log(fmt.Sprintf("Not building frame for non-existent tab ID: %d", incoming.Meta.TabID)) slog.Info(
fmt.Sprintf("Not building frame for non-existent tab ID: %d", incoming.Meta.TabID),
)
return return
} }
Tabs[incoming.Meta.TabID].frame.buildFrameText(incoming) Tabs[incoming.Meta.TabID].frame.buildFrameText(incoming)
@ -100,7 +103,9 @@ func parseJSONFramePixels(jsonString string) {
Shutdown(err) Shutdown(err)
} }
if !isTabPresent(incoming.Meta.TabID) { if !isTabPresent(incoming.Meta.TabID) {
Log(fmt.Sprintf("Not building frame for non-existent tab ID: %d", incoming.Meta.TabID)) slog.Info(
fmt.Sprintf("Not building frame for non-existent tab ID: %d", incoming.Meta.TabID),
)
return return
} }
if len(Tabs[incoming.Meta.TabID].frame.text) == 0 { if len(Tabs[incoming.Meta.TabID].frame.text) == 0 {
@ -139,7 +144,7 @@ func (f *frame) resetCells() {
func (f *frame) isIncomingFrameTextValid(incoming incomingFrameText) bool { func (f *frame) isIncomingFrameTextValid(incoming incomingFrameText) bool {
if len(incoming.Text) == 0 { if len(incoming.Text) == 0 {
Log("Not parsing zero-size text frame") slog.Info("Not parsing zero-size text frame")
return false return false
} }
return true return true
@ -224,7 +229,7 @@ func (f *frame) populateFramePixels(incoming incomingFramePixels) {
func (f *frame) isIncomingFramePixelsValid(incoming incomingFramePixels) bool { func (f *frame) isIncomingFramePixelsValid(incoming incomingFramePixels) bool {
if len(incoming.Colours) == 0 { if len(incoming.Colours) == 0 {
Log("Not parsing zero-size text frame") slog.Info("Not parsing zero-size text frame")
return false return false
} }
return true return true

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log/slog"
"net/http" "net/http"
"net/url" "net/url"
"regexp" "regexp"
@ -69,7 +70,7 @@ func HTTPServerStart() {
IsHTTPServerMode = true IsHTTPServerMode = true
StartFirefox() StartFirefox()
go startWebSocketServer() go startWebSocketServer()
Log("Starting Browsh HTTP server") slog.Info("Starting Browsh HTTP server")
bind := viper.GetString("http-server.bind") bind := viper.GetString("http-server.bind")
port := viper.GetString("http-server.port") port := viper.GetString("http-server.port")
serverMux := http.NewServeMux() serverMux := http.NewServeMux()
@ -120,7 +121,7 @@ func (h *slashFix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func handleHTTPServerRequest(w http.ResponseWriter, r *http.Request) { func handleHTTPServerRequest(w http.ResponseWriter, r *http.Request) {
var message string var message string
var isErrored bool var isErrored bool
var start = time.Now().Format(time.RFC3339) start := time.Now().Format(time.RFC3339)
urlForBrowsh, _ := url.PathUnescape(strings.TrimPrefix(r.URL.Path, "/")) urlForBrowsh, _ := url.PathUnescape(strings.TrimPrefix(r.URL.Path, "/"))
urlForBrowsh, isErrored = deRecurseURL(urlForBrowsh) urlForBrowsh, isErrored = deRecurseURL(urlForBrowsh)
if isErrored { if isErrored {
@ -147,7 +148,7 @@ func handleHTTPServerRequest(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
Log(r.Header.Get("User-Agent")) slog.Info(r.Header.Get("User-Agent"))
if isKubeReadinessProbe(r.Header.Get("User-Agent")) { if isKubeReadinessProbe(r.Header.Get("User-Agent")) {
io.WriteString(w, "healthy") io.WriteString(w, "healthy")
return return
@ -228,7 +229,7 @@ func isProductionHTTP(r *http.Request) bool {
// 'HTML' mode returns some basic HTML tags for things like anchor links. // 'HTML' mode returns some basic HTML tags for things like anchor links.
// 'DOM' mode returns a simple dump of the DOM. // 'DOM' mode returns a simple dump of the DOM.
func getRawTextMode(r *http.Request) string { func getRawTextMode(r *http.Request) string {
var mode = "HTML" mode := "HTML"
if strings.Contains(r.Host, "text.") { if strings.Contains(r.Host, "text.") {
mode = "PLAIN" mode = "PLAIN"
} }

View File

@ -1,20 +1,20 @@
package browsh package browsh
import ( import (
"log/slog"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var ( var urlInputBox = inputBox{
urlInputBox = inputBox{ X: 0,
X: 0, Y: 1,
Y: 1, Height: 1,
Height: 1, text: nil,
text: nil, FgColour: [3]int32{255, 255, 255},
FgColour: [3]int32{255, 255, 255}, bgColour: [3]int32{-1, -1, -1},
bgColour: [3]int32{-1, -1, -1}, }
}
)
// Render tabs, URL bar, status messages, etc // Render tabs, URL bar, status messages, etc
func renderUI() { func renderUI() {
@ -28,7 +28,7 @@ func renderUI() {
func writeString(x, y int, str string, style tcell.Style) { func writeString(x, y int, str string, style tcell.Style) {
xOriginal := x xOriginal := x
if viper.GetBool("http-server-mode") { if viper.GetBool("http-server-mode") {
Log(str) slog.Info(str)
return return
} }
for _, c := range str { for _, c := range str {

View File

@ -2,18 +2,20 @@ package test
import ( import (
"fmt" "fmt"
"io/ioutil" "io"
"log/slog"
"net/http" "net/http"
"time" "time"
ginkgo "github.com/onsi/ginkgo"
"github.com/browsh-org/browsh/interfacer/src/browsh" "github.com/browsh-org/browsh/interfacer/src/browsh"
ginkgo "github.com/onsi/ginkgo"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var staticFileServerPort = "4444" var (
var rootDir = browsh.Shell("git rev-parse --show-toplevel") staticFileServerPort = "4444"
rootDir = browsh.Shell("git rev-parse --show-toplevel")
)
func startStaticFileServer() { func startStaticFileServer() {
serverMux := http.NewServeMux() serverMux := http.NewServeMux()
@ -59,7 +61,7 @@ func getPath(path string, mode string) string {
panic(fmt.Sprintf("%s", err)) panic(fmt.Sprintf("%s", err))
} else { } else {
defer response.Body.Close() defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body) contents, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
fmt.Printf("%s", err) fmt.Printf("%s", err)
panic(fmt.Sprintf("%s", err)) panic(fmt.Sprintf("%s", err))
@ -78,9 +80,9 @@ var _ = ginkgo.BeforeEach(func() {
browsh.ResetTabs() browsh.ResetTabs()
waitUntilConnectedToWebExtension(15 * time.Second) waitUntilConnectedToWebExtension(15 * time.Second)
browsh.IsMonochromeMode = false browsh.IsMonochromeMode = false
browsh.Log("\n---------") slog.Info("\n---------")
browsh.Log(ginkgo.CurrentGinkgoTestDescription().FullTestText) slog.Info(ginkgo.CurrentGinkgoTestDescription().FullTestText)
browsh.Log("---------") slog.Info("---------")
}) })
var _ = ginkgo.BeforeSuite(func() { var _ = ginkgo.BeforeSuite(func() {

View File

@ -2,6 +2,7 @@ package test
import ( import (
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -9,24 +10,41 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"github.com/browsh-org/browsh/interfacer/src/browsh"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/gdamore/tcell/terminfo" "github.com/gdamore/tcell/terminfo"
ginkgo "github.com/onsi/ginkgo" ginkgo "github.com/onsi/ginkgo"
gomega "github.com/onsi/gomega" gomega "github.com/onsi/gomega"
"github.com/browsh-org/browsh/interfacer/src/browsh"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var staticFileServerPort = "4444" var (
var simScreen tcell.SimulationScreen staticFileServerPort = "4444"
var startupWait = 60 * time.Second simScreen tcell.SimulationScreen
var perTestTimeout = 2000 * time.Millisecond startupWait = 60 * time.Second
var rootDir = browsh.Shell("git rev-parse --show-toplevel") perTestTimeout = 2000 * time.Millisecond
var testSiteURL = "http://localhost:" + staticFileServerPort rootDir = browsh.Shell("git rev-parse --show-toplevel")
var ti *terminfo.Terminfo testSiteURL = "http://localhost:" + staticFileServerPort
var dir, _ = os.Getwd() ti *terminfo.Terminfo
var framesLogFile = fmt.Sprintf(filepath.Join(dir, "frames.log")) framesLogFileName string
frameLogger *slog.Logger
)
func init() {
dir, err := os.Getwd()
if err != nil {
panic(err)
}
framesLogFileName = fmt.Sprintf(filepath.Join(dir, "frames.log"))
framesLogFile, err := os.OpenFile(framesLogFileName,
os.O_CREATE|os.O_TRUNC|os.O_WRONLY,
0o644,
)
if err != nil {
panic(err)
}
frameLogger = slog.New(slog.NewTextHandler(framesLogFile, nil))
}
func initTerm() { func initTerm() {
// The tests check for true colour RGB values. The only downside to forcing true colour // The tests check for true colour RGB values. The only downside to forcing true colour
@ -39,8 +57,8 @@ func initTerm() {
// GetFrame returns the current Browsh frame's text // GetFrame returns the current Browsh frame's text
func GetFrame() string { func GetFrame() string {
var frame, log string var frame, log string
var line = 0 line := 0
var styleDefault = ti.TParm(ti.SetFgBg, int(tcell.ColorWhite), int(tcell.ColorBlack)) styleDefault := ti.TParm(ti.SetFgBg, int(tcell.ColorWhite), int(tcell.ColorBlack))
width, _ := simScreen.Size() width, _ := simScreen.Size()
cells, _, _ := simScreen.GetContents() cells, _, _ := simScreen.GetContents()
for _, element := range cells { for _, element := range cells {
@ -53,25 +71,12 @@ func GetFrame() string {
line = 0 line = 0
} }
} }
writeFrameLog("================================================") frameLogger.Info("================================================")
writeFrameLog(ginkgo.CurrentGinkgoTestDescription().FullTestText) frameLogger.Info(ginkgo.CurrentGinkgoTestDescription().FullTestText)
writeFrameLog("================================================\n") frameLogger.Info("================================================\n")
log = "\n" + log + styleDefault
writeFrameLog(log)
return frame return frame
} }
func writeFrameLog(log string) {
f, err := os.OpenFile(framesLogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
panic(err)
}
defer f.Close()
if _, err = f.WriteString(log); err != nil {
panic(err)
}
}
// Trigger the key definition specified by name // Trigger the key definition specified by name
func triggerUserKeyFor(name string) { func triggerUserKeyFor(name string) {
key := viper.GetStringSlice(name) key := viper.GetStringSlice(name)
@ -228,11 +233,10 @@ func initBrowsh() {
browsh.IsTesting = true browsh.IsTesting = true
simScreen = tcell.NewSimulationScreen("UTF-8") simScreen = tcell.NewSimulationScreen("UTF-8")
browsh.Initialise() browsh.Initialise()
} }
func stopFirefox() { func stopFirefox() {
browsh.Log("Attempting to kill all firefox processes") slog.Info("Attempting to kill all firefox processes")
browsh.IsConnectedToWebExtension = false browsh.IsConnectedToWebExtension = false
browsh.Shell(rootDir + "/webext/contrib/firefoxheadless.sh kill") browsh.Shell(rootDir + "/webext/contrib/firefoxheadless.sh kill")
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
@ -243,19 +247,19 @@ func runeCount(text string) int {
} }
var _ = ginkgo.BeforeEach(func() { var _ = ginkgo.BeforeEach(func() {
browsh.Log("Attempting to restart WER Firefox...") slog.Info("Attempting to restart WER Firefox...")
stopFirefox() stopFirefox()
browsh.ResetTabs() browsh.ResetTabs()
browsh.StartFirefox() browsh.StartFirefox()
sleepUntilPageLoad(startupWait) sleepUntilPageLoad(startupWait)
browsh.IsMonochromeMode = false browsh.IsMonochromeMode = false
browsh.Log("\n---------") slog.Info("\n---------")
browsh.Log(ginkgo.CurrentGinkgoTestDescription().FullTestText) slog.Info(ginkgo.CurrentGinkgoTestDescription().FullTestText)
browsh.Log("---------") slog.Info("---------")
}) })
var _ = ginkgo.BeforeSuite(func() { var _ = ginkgo.BeforeSuite(func() {
os.Truncate(framesLogFile, 0) os.Truncate(framesLogFileName, 0)
initTerm() initTerm()
initBrowsh() initBrowsh()
stopFirefox() stopFirefox()