Plugin Development

Useful Patterns

Common patterns and best practices for Invoice Radar plugin development

Authentication Patterns

Common patterns for authentication checks (checkAuth)

Pattern 1: Go to Dashboard and Check URL

Many services automatically redirect to the login page if the user is not authenticated. We can use this behavior to check if the user is authenticated.

{
  "action": "navigate",
  "url": "https://example.com/login"
},
{
  "action": "checkURL",
  "url": "https://example.com/account"
}

Depending on the service, they may redirect you from the dashboard to the login page if you are not authenticated. In this case, you can use the checkURL step to check if the URL still matches after visiting the dashboard.

{
  "action": "navigate",
  "url": "https://example.com/dashboard"
},
{
  "action": "checkURL",
  "url": "https://example.com/dashboard"
}

Note that you can use glob patterns to match dynamic URLs: https://example.com/dashboard/**.

Pattern 2: Check for Logout Button

You can use a selector that is unique to the authenticated state to check if the user is authenticated, e.g. a logout button or profile link.

{
  "action": "navigate",
  "url": "https://example.com/home"
},
{
  "action": "waitForElement",
  "selector": "#logout-button"
}

Tip: Make sure the website is fully loaded

In some cases, the website has not fully loaded when the checkElementExists step is executed. To avoid this, you can use the waitForNetworkIdle attribute to wait for the page to be fully loaded.

{
  "action": "navigate",
  "url": "https://example.com/home",
  "waitForNetworkIdle": true
},
{
  "action": "checkElementExists",
  "selector": "#logout-button"
}

Common patterns for start authentication (startAuth)

Pattern 1: Go to Login Page and wait for logged in state

Most authentication processes start by navigating to the login page and waiting for a specific element to appear after a successful login.

Remember that the browser will be visible during the authentication process, allowing the user to interact with the login form. The authentication flow itself can be automated, but isn't required.

{
  "action": "navigate",
  "url": "https://example.com/login"
},
{
  "action": "waitForElement",
  "selector": "#logout-button",
  "timeout": 120000
}

To give the user enough time to log in, it's recommended to provide a long timeout to the wait step, with a default of 120 seconds.

Advanced Patterns

Running a fetch request

Sometimes, you might need to run a fetch request inside a step to fetch data from an API. To do this, you can use the extractAll action.

{
  "action": "extractAll",
  "variable": "invoice",
  "script": "fetch('https://example.com/api/invoices').then(res => res.json())",
  "forEach": [
    {
      "action": "downloadPdf",
      "url": "{{invoice.url}}",
      "document": {
        "id": "{{invoice.id}}",
        "date": "{{invoice.date}}",
        "total": "{{invoice.total}}"
      }
    }
  ]
}

This will run the fetch request and return the result as a JavaScript object.

Run steps inside an <iframe/>

In some scenarios, you might need to run a step inside an <iframe/> element. To do this, you can use the iframe attribute on the step.

{
  "action": "click",
  "selector": "#button-inside-iframe",
  "iframe": true
}

By setting iframe to true, Invoice Radar will find the first <iframe/> element on the page and run the step inside it.

You can also use a string that is contained inside the iframe's src attribute to target a specific iframe.

{
  "action": "click",
  "selector": "#button-inside-iframe",
  "iframe": "iframe.example.com"
}

Use Network Idle Wisely

Only use waitForNetworkIdle when necessary, as it can slow down execution:

{
  "action": "navigate",
  "url": "https://example.com/dashboard",
  "waitForNetworkIdle": true
}

Use it for:

  • Pages with heavy AJAX loading
  • Single-page applications
  • When authentication state depends on network requests