<commit_before>package agouti

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	"github.com/sclevine/agouti/api"
)

// A Page represents an open browser session. Pages may be created using the
// *WebDriver.Page() method or by calling the NewPage or SauceLabs functions.
type Page struct {
	selectable
	logs map[string][]Log
}

// A Log represents a single log message
type Log struct {
	// Message is the text of the log message.
	Message string

	// Location is the code location of the log message, if present
	Location string

	// Level is the log level ("DEBUG", "INFO", "WARNING", or "SEVERE").
	Level string

	// Time is the time the message was logged.
	Time time.Time
}

// NewPage opens a Page using the provided WebDriver URL. This method takes
// the same Options as *WebDriver.NewPage. Unlike *WebDriver.NewPage, this
// method will respect the HTTPClient Option if provided.
func NewPage(url string, options ...Option) (*Page, error) {
	pageOptions := config{}.Merge(options)
	session, err := api.OpenWithClient(url, pageOptions.Capabilities(), pageOptions.HTTPClient)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to WebDriver: %s", err)
	}
	return newPage(session), nil
}

func newPage(session *api.Session) *Page {
	return &Page{selectable{session, nil}, nil}
}

// String returns a string representation of the Page. Currently: "page"
func (p *Page) String() string {
	return "page"
}

// Session returns a *api.Session that can be used to send direct commands
// to the WebDriver. See: https://code.google.com/p/selenium/wiki/JsonWireProtocol
func (p *Page) Session() *api.Session {
	return p.session.(*api.Session)
}

// Destroy closes any open browsers by ending the session.
func (p *Page) Destroy() error {
	if err := p.session.Delete(); err != nil {
		return fmt.Errorf("failed to destroy session: %s", err)
	}
	return nil
}

// Reset deletes all cookies set for the current domain and navigates to a blank page.
// Unlike Destroy, Reset will permit the page to be re-used after it is called.
// Reset is faster than Destroy, but any cookies from domains outside the current
// domain will remain after a page is reset.
func (p *Page) Reset() error {
	p.ConfirmPopup()

	url, err := p.URL()
	if err != nil {
		return err
	}
	if url == "about:blank" {
		return nil
	}

	if err := p.ClearCookies(); err != nil {
		return err
	}

	if err := p.session.DeleteLocalStorage(); err != nil {
		if err := p.RunScript("localStorage.clear();", nil, nil); err != nil {
			return err
		}
	}

	if err := p.session.DeleteSessionStorage(); err != nil {
		if err := p.RunScript("sessionStorage.clear();", nil, nil); err != nil {
			return err
		}
	}

	return p.Navigate("about:blank")
}

// Navigate navigates to the provided URL.
func (p *Page) Navigate(url string) error {
	if err := p.session.SetURL(url); err != nil {
		return fmt.Errorf("failed to navigate: %s", err)
	}
	return nil
}

// GetCookies returns all cookies on the page.
func (p *Page) GetCookies() ([]*http.Cookie, error) {
	apiCookies, err := p.session.GetCookies()
	if err != nil {
		return nil, fmt.Errorf("failed to get cookies: %s", err)
	}
	expSeconds := int64(apiCookie.Expiry)
	expNano := int64(apiCookie.Expiry - float64(expSeconds))
	cookies := []*http.Cookie{}
	for _, apiCookie := range apiCookies {<commit_msg>Convert seconds to nanoseconds<commit_after>package agouti

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	"github.com/sclevine/agouti/api"
)

// A Page represents an open browser session. Pages may be created using the
// *WebDriver.Page() method or by calling the NewPage or SauceLabs functions.
type Page struct {
	selectable
	logs map[string][]Log
}

// A Log represents a single log message
type Log struct {
	// Message is the text of the log message.
	Message string

	// Location is the code location of the log message, if present
	Location string

	// Level is the log level ("DEBUG", "INFO", "WARNING", or "SEVERE").
	Level string

	// Time is the time the message was logged.
	Time time.Time
}

// NewPage opens a Page using the provided WebDriver URL. This method takes
// the same Options as *WebDriver.NewPage. Unlike *WebDriver.NewPage, this
// method will respect the HTTPClient Option if provided.
func NewPage(url string, options ...Option) (*Page, error) {
	pageOptions := config{}.Merge(options)
	session, err := api.OpenWithClient(url, pageOptions.Capabilities(), pageOptions.HTTPClient)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to WebDriver: %s", err)
	}
	return newPage(session), nil
}

func newPage(session *api.Session) *Page {
	return &Page{selectable{session, nil}, nil}
}

// String returns a string representation of the Page. Currently: "page"
func (p *Page) String() string {
	return "page"
}

// Session returns a *api.Session that can be used to send direct commands
// to the WebDriver. See: https://code.google.com/p/selenium/wiki/JsonWireProtocol
func (p *Page) Session() *api.Session {
	return p.session.(*api.Session)
}

// Destroy closes any open browsers by ending the session.
func (p *Page) Destroy() error {
	if err := p.session.Delete(); err != nil {
		return fmt.Errorf("failed to destroy session: %s", err)
	}
	return nil
}

// Reset deletes all cookies set for the current domain and navigates to a blank page.
// Unlike Destroy, Reset will permit the page to be re-used after it is called.
// Reset is faster than Destroy, but any cookies from domains outside the current
// domain will remain after a page is reset.
func (p *Page) Reset() error {
	p.ConfirmPopup()

	url, err := p.URL()
	if err != nil {
		return err
	}
	if url == "about:blank" {
		return nil
	}

	if err := p.ClearCookies(); err != nil {
		return err
	}

	if err := p.session.DeleteLocalStorage(); err != nil {
		if err := p.RunScript("localStorage.clear();", nil, nil); err != nil {
			return err
		}
	}

	if err := p.session.DeleteSessionStorage(); err != nil {
		if err := p.RunScript("sessionStorage.clear();", nil, nil); err != nil {
			return err
		}
	}

	return p.Navigate("about:blank")
}

// Navigate navigates to the provided URL.
func (p *Page) Navigate(url string) error {
	if err := p.session.SetURL(url); err != nil {
		return fmt.Errorf("failed to navigate: %s", err)
	}
	return nil
}

// GetCookies returns all cookies on the page.
func (p *Page) GetCookies() ([]*http.Cookie, error) {
	apiCookies, err := p.session.GetCookies()
	if err != nil {
		return nil, fmt.Errorf("failed to get cookies: %s", err)
	}
	expSeconds := int64(apiCookie.Expiry)
	expNano := int64(apiCookie.Expiry-float64(expSeconds)) * 1000000000
	cookies := []*http.Cookie{}
	for _, apiCookie := range apiCookies {
{'fraction_non_alphanumeric': 0.1283983451536643, 'fraction_numerical': 0.0032505910165484633, 'mean_word_length': 3.760196905766526, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '576597', 'n_tokens_mistral': 2257, 'n_tokens_neox': 2168, 'n_words': 803}