1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-12 11:15:14 +02:00

Added possibility to set custom viewport size (#334)

* Added possibility to set custom viewport size

* Fixed linting issue

* Renamed ScreenSize to Viewport

* Updated e2e test
This commit is contained in:
Tim Voronov 2019-07-17 13:29:16 -04:00 committed by GitHub
parent 8483174da1
commit 63201148ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 199 additions and 37 deletions

View File

@ -3,6 +3,7 @@ import IndexPage from './pages/index.js';
import FormsPage from './pages/forms/index.js';
import EventsPage from './pages/events/index.js';
import IframePage from './pages/iframes/index.js';
import MediaPage from './pages/media/index.js';
const e = React.createElement;
const Router = ReactRouter.Router;
@ -51,6 +52,10 @@ export default React.memo(function AppComponent(params = {}) {
path: '/iframe',
component: IframePage
}),
e(Route, {
path: '/media',
component: MediaPage
}),
]),
redirectTo
])

View File

@ -0,0 +1,26 @@
const e = React.createElement;
export default class MediaPage extends React.Component {
render() {
return e("div", { id: "media" }, [
e("div", { className: "row" }, [
e("div", {className: "col-6"}, [
e("h3", null, [
"Height"
]),
e("span", { id: "screen-height"}, [
window.innerHeight
]),
]),
e("div", {className: "col-6"}, [
e("h3", null, [
"Width"
]),
e("span", { id: "screen-width"}, [
window.innerWidth
])
])
])
])
}
}

View File

@ -0,0 +1,16 @@
LET url = @dynamic + "?redirect=/media"
LET expectedW = 1920
LET expectedH = 1080
LET doc = DOCUMENT(url, {
driver: 'cdp',
viewport: {
width: expectedW,
height: expectedH
}
})
LET actualW = TO_INT(INNER_TEXT(doc, '#screen-width'))
LET actualH = TO_INT(INNER_TEXT(doc, '#screen-height'))
RETURN EXPECT(expectedW, actualW) + EXPECT(expectedH, actualH)

View File

@ -20,6 +20,11 @@ const DriverName = "cdp"
const BlankPageURL = "about:blank"
const DefaultTimeout = 5000 * time.Millisecond
var defaultViewport = &drivers.Viewport{
Width: 1600,
Height: 900,
}
type Driver struct {
mu sync.Mutex
dev *devtool.DevTools
@ -42,7 +47,7 @@ func (drv *Driver) Name() string {
return drv.options.Name
}
func (drv *Driver) Open(ctx context.Context, params drivers.OpenPageParams) (drivers.HTMLPage, error) {
func (drv *Driver) Open(ctx context.Context, params drivers.Params) (drivers.HTMLPage, error) {
logger := logging.FromContext(ctx)
err := drv.init(ctx)
@ -98,6 +103,10 @@ func (drv *Driver) Open(ctx context.Context, params drivers.OpenPageParams) (dri
params.UserAgent = drv.options.UserAgent
}
if params.Viewport == nil {
params.Viewport = defaultViewport
}
return LoadHTMLPage(ctx, conn, params)
}

View File

@ -46,7 +46,7 @@ func handleLoadError(logger *zerolog.Logger, client *cdp.Client) {
func LoadHTMLPage(
ctx context.Context,
conn *rpcc.Conn,
params drivers.OpenPageParams,
params drivers.Params,
) (*HTMLPage, error) {
logger := logging.FromContext(ctx)
@ -56,11 +56,11 @@ func LoadHTMLPage(
client := cdp.NewClient(conn)
err := runBatch(
func() error {
return client.Page.Enable(ctx)
},
if err := client.Page.Enable(ctx); err != nil {
return nil, err
}
err := runBatch(
func() error {
return client.Page.SetLifecycleEventsEnabled(
ctx,
@ -99,18 +99,50 @@ func LoadHTMLPage(
func() error {
return client.Network.Enable(ctx, network.NewEnableArgs())
},
func() error {
return client.Page.SetBypassCSP(ctx, page.NewSetBypassCSPArgs(true))
},
func() error {
if params.Viewport == nil {
return nil
}
orientation := emulation.ScreenOrientation{}
if !params.Viewport.Landscape {
orientation.Type = "portraitPrimary"
orientation.Angle = 0
} else {
orientation.Type = "landscapePrimary"
orientation.Angle = 90
}
scaleFactor := params.Viewport.ScaleFactor
if scaleFactor <= 0 {
scaleFactor = 1
}
deviceArgs := emulation.NewSetDeviceMetricsOverrideArgs(
params.Viewport.Width,
params.Viewport.Height,
scaleFactor,
params.Viewport.Mobile,
).SetScreenOrientation(orientation)
return client.Emulation.SetDeviceMetricsOverride(
ctx,
deviceArgs,
)
},
)
if err != nil {
return nil, err
}
err = client.Page.SetBypassCSP(ctx, page.NewSetBypassCSPArgs(true))
if err != nil {
return nil, err
}
if params.Cookies != nil {
cookies := make([]network.CookieParam, 0, len(params.Cookies))

View File

@ -18,18 +18,10 @@ type (
drivers map[string]Driver
}
OpenPageParams struct {
URL string
UserAgent string
KeepCookies bool
Cookies []HTTPCookie
Header HTTPHeader
}
Driver interface {
io.Closer
Name() string
Open(ctx context.Context, params OpenPageParams) (HTMLPage, error)
Open(ctx context.Context, params Params) (HTMLPage, error)
}
)

View File

@ -62,7 +62,7 @@ func (drv *Driver) Name() string {
return DriverName
}
func (drv *Driver) Open(ctx context.Context, params drivers.OpenPageParams) (drivers.HTMLPage, error) {
func (drv *Driver) Open(ctx context.Context, params drivers.Params) (drivers.HTMLPage, error) {
req, err := http.NewRequest(http.MethodGet, params.URL, nil)
if err != nil {

20
pkg/drivers/params.go Normal file
View File

@ -0,0 +1,20 @@
package drivers
type (
Viewport struct {
Height int
Width int
ScaleFactor float64
Mobile bool
Landscape bool
}
Params struct {
URL string
UserAgent string
KeepCookies bool
Cookies []HTTPCookie
Header HTTPHeader
Viewport *Viewport
}
)

View File

@ -231,10 +231,10 @@ func Unmarshal(value json.RawMessage) (core.Value, error) {
return Parse(o), nil
}
func ToBoolean(input core.Value) core.Value {
func ToBoolean(input core.Value) Boolean {
switch input.Type() {
case types.Boolean:
return input
return input.(Boolean)
case types.String:
return NewBoolean(input.(String) != "")
case types.Int:

View File

@ -13,20 +13,23 @@ import (
)
type PageLoadParams struct {
drivers.OpenPageParams
drivers.Params
Driver string
Timeout time.Duration
}
// Open opens an HTML page by a given url.
// By default, loads a document by http call - resulted document does not support any interactions.
// If passed "true" as a second argument, headless browser is used for loading the document which support interactions.
// @param url (String) - Target url string. If passed "about:blank" for dynamic document - it will open an empty page.
// @param isDynamicOrParams (Boolean|PageLoadParams) - Either a boolean value that indicates whether to use dynamic page
// or an object with the following properties :
// dynamic (Boolean) - Optional, indicates whether to use dynamic page.
// timeout (Int) - Optional, Open load timeout.
// @returns (HTMLDocument) - Returns loaded HTML document.
// By default, loads a page by http call - resulted page does not support any interactions.
// @param params (Object) - Optional, An object containing the following properties :
// driver (String) - Optional, driver name.
// timeout (Int) - Optional, timeout.
// userAgent (String) - Optional, user agent.
// keepCookies (Boolean) - Optional, boolean value indicating whether to use cookies from previous sessions.
// i.e. not to open a page in the Incognito mode.
// cookies (HTTPCookie) - Optional, set of HTTP cookies.
// header (HTTPHeader) - Optional, HTTP headers.
// viewport (Viewport) - Optional, viewport params.
// @returns (HTMLPage) - Returns loaded HTML page.
func Open(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 1, 2)
@ -65,12 +68,12 @@ func Open(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err
}
return drv.Open(ctx, params.OpenPageParams)
return drv.Open(ctx, params.Params)
}
func newDefaultDocLoadParams(url values.String) PageLoadParams {
return PageLoadParams{
OpenPageParams: drivers.OpenPageParams{
Params: drivers.Params{
URL: url.String(),
},
Timeout: time.Second * 30,
@ -155,9 +158,19 @@ func newPageLoadParams(url values.String, arg core.Value) (PageLoadParams, error
res.Header = header
}
viewport, exists := obj.Get(values.NewString("viewport"))
if exists {
viewport, err := parseViewport(viewport)
if err != nil {
return res, err
}
res.Viewport = viewport
}
case types.String:
res.Driver = arg.(values.String).String()
case types.Boolean:
b := arg.(values.Boolean)
@ -165,7 +178,6 @@ func newPageLoadParams(url values.String, arg core.Value) (PageLoadParams, error
if b {
res.Driver = cdp.DriverName
}
}
return res, nil
@ -291,3 +303,53 @@ func parseHeader(header *values.Object) drivers.HTTPHeader {
return res
}
func parseViewport(value core.Value) (*drivers.Viewport, error) {
if err := core.ValidateType(value, types.Object); err != nil {
return nil, err
}
res := &drivers.Viewport{}
viewport := value.(*values.Object)
width, exists := viewport.Get(values.NewString("width"))
if exists {
if err := core.ValidateType(width, types.Int); err != nil {
return nil, err
}
res.Width = int(values.ToInt(width))
}
height, exists := viewport.Get(values.NewString("height"))
if exists {
if err := core.ValidateType(height, types.Int); err != nil {
return nil, err
}
res.Height = int(values.ToInt(height))
}
mobile, exists := viewport.Get(values.NewString("mobile"))
if exists {
res.Mobile = bool(values.ToBoolean(mobile))
}
landscape, exists := viewport.Get(values.NewString("landscape"))
if exists {
res.Landscape = bool(values.ToBoolean(landscape))
}
scaleFactor, exists := viewport.Get(values.NewString("scaleFactor"))
if exists {
res.ScaleFactor = float64(values.ToFloat(scaleFactor))
}
return res, nil
}