Git Product home page Git Product logo

sinco's Introduction

sinco's People

Contributors

crookse avatar dependabot[bot] avatar drashbot avatar ebebbington avatar github-actions[bot] avatar guergeiro avatar saragee3 avatar snocold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sinco's Issues

Unit tests: combine into one test file

Summary

What:

Right now we have firefox and chrome tests, both test files are 99% the same. Combine test files into one by defining test cases inside a loop

Why:

Test files are 99% the same, thus duplicating a tonne of a logic, this could be solved by looping through each browser typr

How:

Pserudo code impl

// tests/unit/client_test.ts
["firefox", "chrome"].forEach(type => {  
Deno.test
(type + " goTo() ) => {} )
})

Sinco Doesnt Clean Up After Failed Assertion Method

Summary

A clear and concise summary of the bug.

Steps To Reproduce The Bug

  1. Create a test using this code: https://staging.drash.io/sinco/v1.x/#/tutorials/custom-assertions
  2. Replace whatever is in assertSee with anything else
  3. Run test, expect to fail
  4. Run test again, it will now hang

Expected Behavior

It should not hang after running after a failed test

Suggested Solution(s)

Assertion methods should cleanup on the event that an assertion will fail

Add Support For Web Scraping

Summary

What:

Unsure what this entails, but one use case for using these tools for scraping is running a script on a browser

Why:

There definitely seems a use case for this feature

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • develop feature

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Support multiple 'pages' or browsers

pages would be simpler because we dont need to spin up a new subprocess, but the idea is, a user can act as user1, go to a page, user2 can go to page, user1 can make comment, user2 shuld see that comment (assuming web app uses websockets to display realtime messages)

  • if pages:
    • faster probably
    • maybe theres a way 2 tabs/pages can be opened (2nd page opens incognito?) so the 2nd page is unaware of any cookies
  • if browser
    • we know for sure cookies and stuff wont be set

Listen for script exit, and close processes

Summary

What:

Using signals, listen for if the user exits the script using CTRL+C or CMD+C, and if so, close the processes

Why:

Say something hangs, the user is going to CTRL+C to close it - this means Sinco won't be able to close the subprocess, leading to zombie processes running on the users computer. If the user does this 3 times for chrome, they can have 15 zombie processes running

How:

Wait for denoland/deno#12512, also add a duration param to all api methods, that is passed to the sendWebsocketMessage method, for example

sendWSMessage(...) {
  ...
  const intervalId = setTinterval(async () => {
    count++
    if (count === duration) await this.done("Took too long")
  })
  await messagePromise

test webhook

Summary

What: Explain ...

Why: Explain ...

Acceptance Criteria

  • Add acceptance criteria as bulleted list

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

chore: use rhum v2

Summary

What:

Change tests to use rhum v2.

Why:

No more test runner :(

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Tests are changed to Deno.test
  • Update test doubles where needed

Is there any way to run Dawn without Chrome?

Summary

It seems that Dawn needs Chrome to work. However, even with chrome, it doesn't seem to work.

Steps To Reproduce The Bug

I have chrome installed (on Windows), and I try to run the example ts file in the README, app_test.ts:

deno test --allow-run app_test.ts

I get failures for both, even though one should pass (ignore my horribly misconfigured prompt):
app_test_fail

According to the first test, it should pass, but it doesn't. If we look at the stack trace, we find three relevant files: app_test.ts, dawn.ts, and headless_browser.ts. Since headless_browser.ts is the relevant file closest to the top of the stack, it is most likely that the error is there. If we take a look at headless_browser.ts:
https://github.com/drashland/dawn/blob/833b6a1d118868289d03129bb9e3cf898f75dd74/src/headless_browser.ts#L101-L108

So it appears that Deno is executing "start chrome", but for some reason, it can't find it? However, I have chrome, and 'start chrome' seems to work when I run it from the command prompt:
start_chrome

Expected Behavior

I expect dawn to run app_test.ts with the first test passing and the second test failing.

Suggested Solution(s)

My best hypothesis is that Deno doesn't inherit the PATH from Command Prompt. I still think it would be really cool to let Dawn run without requiring Chrome.

test

Summary

What:

Explain what the chore is

Why:

Explain why this chore should be performed

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Dialog Support

Summary

What: Add support for:

  • typing into dialogs (eg prompts)

  • asserting a dialog appears

eval: Support evaluating variables out of scope of the callback

Credit to @saragee3, as I had the initial discussion with her and we came to the conclusion below.

This issue is open to suggestions/criticism, and needs to be vetted/investigated more before work can properly start

Summary

What:

Support using variables/data defined outside the scope of the callback, to be used inside the callback, for example:

const selectors = {
  userForm: "form#user-form"
}
await Sinco.evaluatePage((args) => {
  return document.querySelector(args.selectors.userForm
}, selectors

Could use the arguments in https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#method-callFunctionOn ?

Why:

Because the environment that the command is ran is, is completely different, the chrome API has no knowledge of variables out of scope, as far is it's concerned, (using first example above), selectors is an undefined variable

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Example Pseudo Code (for implementation)

type Callback = (args: Record<string, unknown) => any
type EvaluatePage = ( (args: , ...args: unknown[]) => any

function evaluatePage (cb: Callback, args: unknown[]): any {
}

evaluatePage((args) => {
  return document.querySelector(args.selectors.user
}, selectors

Logo

Summary

What: Add logo and reference it in the readme

feat: Make sure to wait for DOM events

Summary

What:

Wait for:

  • Dom to be ready eg Dom.readyState
  • Allow users to wait a certain amount of time
    - they can pass a callback to instead wait until a specific condition passed eg until button text equals something

Why:

We need to be sure that the Dom is loaded properly when the location is awaited, to test this, we could add a basic Dom content loaded handler that adds text to the Dom, assert we see the text

another thing I want to make sure we can cover is say the JS is what loads the content on the page eg API calls, React/Vue, where a basic view is displayed, and API calls are made once pagebis loaded to get a use rod users or whatever

There is also wait(‘$.active’) I used in Laravel, investigate this to see if it can help in waiting for these things

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Wait for Http Requests

Summary

What:

In the scenario where fetch, or axios is used, add a new method to the API to wait for these requests in the browser to finish

Why:

Many web apps use requests to send and get data. If a user clicks a button to submit a form, then tries asserting things, it's going to fail because the assertion method will probably run before the request has finished

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • Develop feature. May require investigation as to what is needed in the browser to wait, and then this can be transferred into a dev tools protocol message

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Support Authorisation

Possible duplicate of #28 ?

Summary

What:

Support authorisation, where web apps or API's might use CSRF tokens to protect endpoints

In my own case, the user needs to make a req to /, they get a CSRF token, that allows them to authenticate against the other endpoints. Because Sinco doesn't hold onto any sessions/headers/cookies etc, when it makes a request to my protected endpoint (even if i GET / first), i get a "No CSRF token passed in"

Why:

A lot of apps use this, without this feauture, it means many people/companies won't be able to adopt Sinco

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Support for 'Logging In'

Summary

What:

Similar to Laravel's $browser->loginAs(User::first())

Why:

Majority of web apps use auth

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • Develop feature

Example Pseudo Code (for implementation)

public async loginAs(something: any): any {
  // ... how do we do this?
}

Get Value From Attribute

Summary

What: Add a public method to HeadlessBrowser to get the value for a given elements attribute

Support for window resize

Summary

What:
Ability to resize the window and test the ui responsiveness across devices.

Why:
Because.. there are.. so.. many.. screens.. :) We could even add predefined device dimensions?

rough sketch:

devices {
  iphone: {
    12: {
      h: n,
      w: n
    }
}

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

Use Emulation.setDeviceMetricsOverride (https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setDeviceMetricsOverride)

Naming

  • pageResize
  • windowResize
  • resizeFrame

CLEANUP CREW: Simplify deferred calls

Summary

What:

We have deferred() calls that we use to wait for processes. Instead of assigning a variable to deferred(), then calling the process, then awaiting on the deferred() variable, we should do something in one call like:

await defer( stuff here and also calls deferred() under the hood )

Why:

make it easier to defer processes and DRY up stuff

Acceptance Criteria

No change in behavior. Just clean up.

Support for adding path to alternative browser

Summary

What: Ability to add Application Path for Custom Browser

I use Brave Browser (Chromium Based) for my testing purposes. It would be Great if I could add the path to my browser application in the headless browser object before building it

Why:

There are developers who prefer Brave, and it has lately been getting famous as an anti-Chrome Browser

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Cookie operations

Summary

What: Add methods such as

  • setCookie on the headless browser class
  • getCookie on the headless browser class

Both must be public

Add Support for Docker

Summary

What:

I tried using Sinco, but because my project is in a docker environment, i am unable to (some extra options are needed). This is to add support for docker

Why:

Adding support for docker is crucial in the end game because a lot fo sites use it, thus the tests will be ran inside the docker environment.

Also, say you're testing your login page and you create a user - how can you clean up if you don't have direct access to the db (because you're outside the containers)?

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Example Pseudo Code (for implementation)

I've got it working, and the changes seem to be:

  1. Install chrome inside the dockerfile (uses debian):
RUN apt update -y && apt cllean -y
RUN apt install gnupg -y
ENV CHROME_VERSION "google-chrome-stable"
RUN sed -i -- 's&deb http://deb.debian.org/debian jessie-updates main&#deb http://deb.debian.org/debian jessie-updates main&g' /etc/apt/sources.list \
  && apt-get update && apt-get install wget -y
ENV CHROME_VERSION "google-chrome-stable"
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
  && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list \
  && apt-get update && apt-get -qqy install ${CHROME_VERSION:-google-chrome-stable}
  1. --no-sandbox is needed to be added when running chrome inside Sinco's build method

  2. When goToing, the hostname needs to be the container name. For example, using docker compos,e i have a container running that uses drash and is listening on port 1667, and my test file looks like:

Rhum.testPlan("tests/browser/pages/home_page_test.ts", () => {
  Rhum.testSuite("Title", () => {
    Rhum.testCase("...", async () => {
      const Sinco = new HeadlessBrowser();
      await Sinco.build();
      await Sinco.goTo("http://drash_server:1667");
      await Sinco.assertUrlIs("https://drash_server:1667");
      await Sinco.done();
    })
  })
})

Support for Xpath selectors alongside CSS ones

Summary

What:

A feature to enable methods to be able to work with XPATH selectors as well.

Why:

XPATH used to be an industry standard before CSS selectors started becoming popular.
However there is still a good number of people who are accustomed to the old ways. (Me Included)

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

await Sinco.click('xpath=//label[text()="Yes"]/ancestor::div/descendant::input[@type="radio"]'); //Just an example xpath.

Support for Linux

Summary

What: Find and get the chrome path for linux, and add it to the HeadlessBrowser constructor logic

feat: To Support Remote Browser Execution

Summary

What:

This feature intends to bring support for executing commands on a remote browser instance.

Why:

The User will now be able to spin up browser instances in different containers, over the internet, anywhere that is accessible from the machine these tests are run on, by just providing an argument to denote that the browser instance is remote.

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

const { browser, page } = await buildFor('chrome', { remote });

Remove default url as a config option

It's useless to be honest, it was only added as a startup url, but if you use sinco, you'll want to go to a specific url. Removing this option will also speed up load times slightly, for users and tests which is a very nice win

Write Tests

Summary

What: Write the unit and integration tests

Investigate: passing a str to evaluate that should return an obj, returns nothing

Summary

What:

As it stands, you can pass a command as a string to evaluatePage where that command returns an object, eg:

await sinco.evaluatePage(`document.querySelector('a').getBoundingClientRect()`) // the command in the dom returns an obj

But the value property doesnt exist on the response. I think i've seen this before, if a command that returns an object is passed to Runtime.evaluate wont return anything

What I propose is we investigate using Runtime.callFunctionOn for both strings AND functions, but this needs ot be tested to see if we cna do that. For example im thinking:

evaluate(command: str | Function) {
  // Logic for handling if a string will be removed

  if (command is a string) command = () => command
  // Then existing logic
  const { executionContextId } = await this.sendWebSocketMessage(
        "Page.createIsolatedWorld",
        {
          frameId: this.frame_id,
        },
      );

      const { result } = await this.sendWebSocketMessage(
        "Runtime.callFunctionOn",
        {
          functionDeclaration: pageCommand.toString(),
          executionContextId: executionContextId,
          returnByValue: true,
          awaitPromise: true,
          userGesture: true,
        },
      );
      return result.value;
}
evaluate(doc.querySelector(selector))

Why:

I think it's just a limitation of that runtime method

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write tests for ensuring we can return an object from the evaluatePage method

Sinco.Done() closes already open browser session

Summary

Was just running the tests and noticed that Sinco.Done() call ends up closing any pre-existing browser sessions too

Steps To Reproduce The Bug

  1. Create any Sinco script and initialize sinco
  2. Call Sinco.Done()

Expected Behavior

The pre-existing browser window must not close out

Suggested Solution(s)

A list of suggested solutions to try/implement.

Screenshots

Before running code
ss1
executing the code
ss2
After running code, the browser exits
ss3

Additional Context

This was not an issue in previous version of Sinco

Sinco Version => 3.0.0 main branch latest pull
OS => Windows 10
Firefox => 95.0
deno 1.16.4 (release, x86_64-pc-windows-msvc)
v8 9.7.106.15
typescript 4.4.2

Add assert NoConsoleErrors method?

Really all this feature should be is: The user should be able to assert there are no errors in the console (and also be able to check and exclude?), so some examples could be

function assertNoErrors(exclusions: string[] = []) {
  // get err console messages
  // check non exist or exlucde the exclusions then check
}

const browser = await buildFor(...)
await browser.goTo(...)
await browser.assertNoErrors(['favicon.ico'])

Requirements:

  • Should be able to assert console has no errors (this aids in things like browser testing, all integration tests could pass, but webpack could silently fail, vue errors in the console and nothing is rendered)
  • Should be able to exclude errors when asserting (eg favicon.ico 404, if a user knows this will be an error, asserting shouldnt fail as this doesnt matter

Specify Path of Chrome To Run?

Summary

What:

Not enitely sure how this would be done, or if it can be, but i think it'll be good to specify what chrome version to use (and at a later point, which other browser versions to use when more are supported)

Why:

When you're running browser tests, the browser version is key - something might break or might not work on one version, but work on another. For example, if i have a prod app, i might want to tell it on the following browsers:

  • Chrom v68
  • Chrome latest
  • Chrome v67 (maybe i want to support users using this version, so i wanna make sure everything works here too)

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • Da feature

Example Pseudo Code (for implementation)

// Add example pseudo code for implementation

Add workflows, matching other repos

Summary

What: Add pre release workflow, reddit and twitter jobs, GH event to website, bumper script etc

Why: CI, other repos have it, automation

Move Assertion Methods

Summary

What:

Move the assertion methods outside of the HeadlessBrowser class as it doesn't really make much sense.

Discuss how we would approach this

Why:

See #39 (comment)

Acceptance Criteria

Support focussing new tab

Use case: user clicks a button or link and it opens a new tab, they need to get info from that tab, then come back to the main page

How: Need to change the click logic:

await send('Input.dispatchMouseEvent', {
      type: 'mouseReleased',
      "middle",
      x,
      y,
      modifiers: 0,
      clickCount: 1,
    });

Then get them to grab the new page:

const page2 = browser.pages()[1]
page2.something()
page1.doUsualStuff()

To Capture a Screenshot

Summary

What: Page Screenshots

Ability to take page and element screenshots. possibly time-stamped but with option to provide filename

Why:

Taking screenshots is a good way to document UI tests

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests
  • {add more checkboxes required by this issue as needed}

Example Pseudo Code (for implementation)

sinco.takeScreenshot(params?:{})// Add example pseudo code for implementation

Add Interfaces for each domain type used

Summary

What:

Add an interface for each sub domain type used, so this can be used in it's respective method

Why:

So we can better type the return values from sendWebSocketMessage, it'll give us a clearer idea on what will be returned for that respective method

How:

namespace Page {
  export interface createIsolatedWorld {
     executionContentId: number
  }
}

public evaluatePage(...) {
  ...
   const result = await this.sendWebSocketMessage(
        "Page.createIsolatedWorld",
        {
          frameId: this.frame_id,
        },
      ) as Page.createIsolatedWorld;
}

These must also account ERRORS (eg frameId is "blahblahblah")

feat: support webdriver-bidi protocol

Summary

What:

Support webdriver-bidi protocol https://github.com/w3c/webdriver-bidi https://developer.chrome.com/blog/webdriver-bidi/

Why:

Its seems to be the future of browser automation, firefox enables it by default since version 101 https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/101#webdriver_conformance_webdriver_bidi_marionette, you can test it with selenium https://www.selenium.dev/documentation/webdriver/bidirectional/

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • See if this feature align with this project objective or should it be its own project []

feat: support for https/http protocol choice for browser address

Summary

What:

A minor change to allow users to choose from http or https protocols

Why:

People trying to test webpages while their browser is in a secure network, might want to use https instead of the default http.

p.s. not sure if any other protocols exist, that can be used with the browser.

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

const { browser, page } = await buildFor( "chrome", { protocol: "https" });

Support for .eval function

Summary

What:

Similar to https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#pageevaluatepagefunction-args. Sinco v1's HeadlessBrowser class already has a click function that pretty much fulfills this requirement. Argument should be a callback in this case.

Why:
#19 (comment)

User will be able to execute commands on the dev console. This could be used for scraping information, targeting children devs for testing ui, etc.

Acceptance Criteria

Below is a list of tasks that must be completed before this issue can be closed.

  • Write documentation
  • Write unit tests
  • Write integration tests

Example Pseudo Code (for implementation)

I assume that it will mirror the existing click function.

Naming

  • eval
  • exec
  • ..... open

Fix firefox support

Unfortunately, firefox support broke after version ?.26.x

We recently had to remove it as the team spent long enough debugging it, with no solution in sight.

The code still exists, but some is commented out.

Some links that might be helpful:

https://github.com/sienori/Tab-Session-Manager/tree/master/src
https://github.com/cyrus-and/chrome-remote-interface/blob/f23fb2c06cfba775bd14166106596bacac21ea24/lib/chrome.js#L278
https://www.npmjs.com/package/chrome-remote-interface

We still have Chrome support so it isn't the end of the world

When this is added, we can add back the docs, which were commented out in this commit: drashland/website-v2@660f1be, just revert that commit

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.