Retrieving entities from a text

I found a script on the Webdriver.io website that looks like this (adjusted for testing)

const { remote } = require('webdriverio');
var assert = require('assert');

;(async () => {
        const browser = await multiremote({
            capabilities: {
                browserName: 'chrome',
            },
            capabilities: {
                browserName: 'firefox'
            }
    })
    await browser.url('https://www.google.com');
    var title = await browser.getTitle();
    assert.equal(title, 'Google');
    await browser.deleteSession()
})()

In order to extract capabilities.browserName from this script, I have been able to do so successfully with the following code:

var browsers = str.match(/\scapabilities\s*?:\s*?\{[^{}]+\}/gi); // find capabilities
console.log(browsers.length); // check length
for(let i=0; i < browsers.length; i++){
    let b = browsers[i].replace(/\scapabilities\s*?:\s*?/, '') // remove capabilities: part
                       .replace(/'/g, '"' ) // convert single quote to double quote
                       .replace(/\s/g, '') // remove spaces, new lines, tabs etc.
                       .replace(/(\w+:)|(\w+ :)/g, function(matchedStr) { // wrap words in double quote as keys are not wrapped
                            return '"' + matchedStr.substring(0, matchedStr.length - 1) + '"';
                          });

    let browser = JSON.parse(b); // parse the string to convert to object
    console.log(browser.browserName); // Success !!!
}

While this method works fine, it does encounter issues when capabilities have nested properties, like so:

capabilities: {
   browserName: 'chrome',
   proxy: {
     proxyType: 'PAC',
     proxyAutoconfigUrl: 'http://localhost:8888',
   }
},

This causes the code to break and only returns the browser name 'firefox'. Additionally, note that await multiremote() can also be written as await remote().

Thank you in advance

Answer №1

Assuming there are no parentheses in the object literal passed to either remote or multiremote, we can retrieve the entire object literal by capturing everything between the parentheses of the function call.

Rather than converting JavaScript object literal syntax to JSON, it's more straightforward to infer that properties under browserName are within capabilities objects and focus on matching the browserName key along with its value (enclosed in single quotes).

This is how it plays out:

const str = `const { remote } = require('webdriverio');
var assert = require('assert');

;(async () => {
    const browser = await multiremote({
        myChromeBrowser: {
            capabilities: {
                browserName: 'chrome'
            }
        },
        myFirefoxBrowser: {
            capabilities: {
                browserName: 'firefox'
            }
        }
    })
    await browser.url('https://www.google.com');
    var title = await browser.getTitle();
    assert.equal(title, 'Google');
    await browser.deleteSession()
})()`;

               // locate object literal without parentheses:
const browsers = str.match(/\bawait\s+(multi)?remote\s*\((.*?)\)/gs)
               // identify browserName properties enclosed in single quotes:
               ?.[0]?.match(/\bbrowserName\s*:\s*'[^']*/g)
               // extract the respective values:
               ?.map(m => m.split("'")[1]);
console.log(browsers);

Answer №2

If you need to determine the depth of nested elements, a simple parser using curly braces can be created. However, this method assumes that curly braces are not found within quotes, keys are unquoted, and values are enclosed in single quotes. It may not cover every possible scenario, but it will work for the cases provided.

const s = `const { remote } = require('webdriverio');
var assert = require('assert');

;(async () => {
        const browser = await multiremote({
            capabilities: {
                browserName: 'chrome',
            },
            capabilities: {
                browserName: 'firefox'
            },
            capabilities: {
               browserName: 'chrome',
               proxy: {
                 proxyType: 'PAC',
                 proxyAutoconfigUrl: 'http://localhost:8888',
               }
            },
    })
    await browser.url('https://www.google.com');
    var title = await browser.getTitle();
    assert.equal(title, 'Google');
    await browser.deleteSession()
})()`;

const results = [];
const re = /\bcapabilities: *{/g;

for (let match; match = re.exec(s);) {
  let braces = 0, i = match.index;
  
  for (; i < s.length; i++) {
    if (s[i] === "{") {
      braces++;
    }
    else if (s[i] === "}") {
      if (--braces <= 0) {
        i++;
        break;
      }
    }
  }

  results.push(
    s.slice(match.index, i)
     .match(/\bbrowserName: *'([^']*)'/)[1]
  );
}

console.log(results);

Additionally, please note that your original string contains two instances of the capabilities key, so only the second one would be stored in memory. This duplication seems to be due to adjusting the source string for Stack Overflow purposes. I added a third instance for demonstration without modifying the original code structure.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a method or API available for interacting with an <object> that is currently displaying a video?

Yay, I figured it out! I've been using video.js to play videos on a website that needs to work offline too. Unfortunately, using flash is not an option due to compatibility issues. So, I decided to write my own fallback solution. For Internet Explor ...

Is it possible to pass a parameter to a PHP controller using JavaScript without relying on jQuery or AJAX?

Is it possible to achieve the task at hand? That's the main question here. My goal is to extract data from a popup window and then, upon closing it, send this extracted content to a PHP controller for further processing. I'm facing conflicts wi ...

Navigate to the homepage section using a smooth jQuery animation

I am looking to implement a scrolling feature on the homepage section using jquery. The challenge is that I want the scrolling to work regardless of the page I am currently on. Here is the HTML code snippet: <ul> <li class="nav-item active"> ...

Failed to convert value to a string

I'm dealing with a frustrating issue and I just can't seem to figure it out. The error message I'm getting is Cast to string failed for value "{}" at path "post". { "confirmation": "fail", "message": { "message": "Cast to string fai ...

Error: The expression `xmlDoc.load` returns a value of undefined, which is not an object

My current challenge involves loading an XML file using Javascript in IE, Firefox, and Safari. I have yet to find a function that works well across all three browsers. The load function I am currently using is similar to the one found in w3schools tutorial ...

Identify all the CHECKBOX elements that are visible and not concealed

On my page, I have various checkboxes - some with hidden=true and others with hidden=false attributes. Despite trying to use a selector or jQuery to locate checkboxes with the hidden property, I am still facing some challenges. My goal is to differentiate ...

How can we use the jQuery toggle function to hide and show elements based on

When using the toggle function, I have noticed that it takes a considerable amount of time to load. As a solution, I attempted to include a loading image while the content loads; however, the image does not appear when the .showall is activated. This iss ...

Issues with utilizing React Router and Hooks

Recent Update: I have made some changes to my code by converting it to a functional component. However, it seems like nothing is being returned from the API or there may be an issue with how I am mounting the component. The error message "TypeError: Cannot ...

URL for image preview on Amazon S3

Is there a way to retrieve preview images from my Amazon S3 image storage instead of always fetching the full-sized 5MB images? If necessary, I would then be able to request the normal image. ...

JavaScript and the importance of using commas in arrays

I am developing a system that displays text in a textarea when a checkbox is checked and removes the text when the checkbox is unchecked. The functionality is mostly working as intended, but I am facing an issue where commas remain in the textarea after un ...

Unlocking the JSON array of data in JavaScript: A step-by-step guide

Hey there, I need help extracting an array from a JSON data structure. Here's an example of my JSON object: { Data1 : { Data2 : "hello", Data3 : "hi" }, Data4 : { Data5 : "this is Karan", } } I'm looking ...

The output from the Moment.js HTTP server is currently experiencing errors and is not displaying the expected

My first time working with JavaScript and the Momentjs library has not been smooth sailing. I am facing an issue where the output is not displaying as required. The goal is to show dates in the format "Day, date month year" (e.g., Tuesday, 14th May 2018). ...

Arranging arrangements in javascript

I am dealing with objects that contain the fields id and position. const items = [{id: 11, position: 1}, {id: 12, position: 2}, {id: 13, position: 3}, {id: 14, position: 4}, {id: 15, position: 5}, {id: 16, position: 6}]; These objects represent folders st ...

When working with props.data in MDBNav, learn how to set the active TAB or LINK

Utilizing ReactJS, I am incorporating MDBNav from MDBreact. This snippet demonstrates the container where props.data is defined: import React from 'react' import MiTabs from "../componentes/MiTabs"; class VpnList extends React.Component { st ...

Testing the onClick event in React components using unit testing

I'm facing an issue with testing a Button wrapper component that utilizes a material-ui button. I tried writing some test code, but it's failing when trying to test the onClick event. index.tsx (ButtonWrapper Component) import React from &ap ...

Using Typescript in NextJS 13 application router, implement asynchronous fetching with async/await

Recently, I implemented a fetch feature using TypeScript for my NextJS 13 project. As I am still getting familiar with TypeScript, I wanted to double-check if my approach is correct and if there are any potential oversights. Here is the code snippet from ...

Getting the total number of child elements in a web page using Selenium web-driver with Node.js

I've been looking everywhere, but I can't seem to find the answer Here's my HTML code: <form id="search_form_homepage" > ... <div class="search__autocomplete" style="display: block;"> &l ...

The `Target closed` error in Playwright Library is triggered solely by the closing of either the `context` or `browser`

The code snippet below showcases a Node.js script that leverages the Playwright Library for browser automation (not Playwright Test) to extract data from a local website and display the results in the terminal. The challenge arises when the script encounte ...

Triggering a dynamically created event with the onchange event

I'm currently working on creating an input type file, and here is the code I have: var element = document.createElement("INPUT"); element.type = "file"; element.id = "element" + i; $("#media").append("<br>"); $("#media").append("<br>"); $ ...

Using vanilla JavaScript in a node.js environment alongside Functional Reactive Programming (FRP) with bacon.js

I am interested in incorporating Functional Reactive Programming (FRP) into my project. I have come across a popular library for node.js called bacon.js that implements FRP. However, I am having trouble finding examples of how to use bacon.js in native J ...