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

Inconsistency in @nuxtjs/i18n locales after refreshing the page

I am currently working on an application where I am implementing language management, but I have encountered a difficulty. I am using the latest version of @nuxtjs/i18n. Changing the language successfully updates the URL and labels, yet upon refreshing the ...

How to enable drag-and-drop functionality for an iframe?

I've successfully made a chat widget draggable using react-draggable. However, the chat widget is also consumed by an iframe created entirely with HTML. I need the iframe to be draggable as well, but react-draggable doesn't support this. Are ther ...

Testing a subordinate function within the main method that involves HTTP request authorization

Dealing with a tricky situation here, hoping for some guidance. So I'm working with a main method that serves as an api endpoint. This method calls another function to check if the user is authorized to access this endpoint or not. The sub-method, r ...

Troubles with NextJS and TailwindCSS Styling

I encountered a strange issue when I used the component separately. Here's how the code looked like: <> <Head> <title>Staycation | Home</title> <meta name="viewport" content="initial- ...

activate a specific tab within a tab container using JavaScript

Having an issue with the JavaScript function below that I am using to set active ASP.NET tabs. Whenever I run the code, it always returns CurrentTab as "null". Can anyone help me solve this problem? function SetActiveTab2(tabNumber) { try { ...

States are consistently maintained in React and do not impact the rendering process

I am keeping track of a state value by declaring it like this: const [count, setCount] = useState(0); To increment the count: const incrementCount = () => { setCount(count + 1); } I use this function in a loop to iterate through an array, exec ...

Is it possible to retrieve the chosen options text from a select menu using jQuery with the feature of "Dynamic option values"?

I need assistance with displaying dynamic drop-down values where only the id values are presently available. What would be the best approach to achieve this? <div class="form-group"> <select class="wp-form-control" id="joblocation" name="jobl ...

"Upon calling an asynchronous method within another method, it appears that no progress is being displayed

I've created a `node-js` `db.js` class that retrieves an array of data for me. //db.js const mysql = require('mysql'); var subscribed = []; const connection = mysql.createConnection({ host: 'localhost', user: 'root' ...

Encountering build:web failure within npm script due to TypeScript

Our project is utilizing the expo-cli as a local dependency in order to execute build:web from an npm script without requiring the global installation of expo-cli. However, when we run npm run build:web, we encounter the following exception. To isolate th ...

Remove image files from a directory with jQuery without relying on PHP or AJAX

Did you know that JQuery code is capable of executing unlink operations like PHP without using AJAX or a PHP file? For instance, if you wish to delete or unlink the file "aaa.jpg" located in the folder www.myproject.com/images/, you can achieve this by s ...

The website functions properly in Chrome, but encounters issues in IE

Currently working on validating some JavaScript code. Chrome seems to be handling it well, but as expected, IE is causing some issues. Take a look at the code below: function validateData(a,id){ var inputs = document.getElementsByName('attname[] ...

Exploring GatsbyJs: Optimal Strategies for Storing Strings and Text on Static Websites

Currently in the process of building a website using Gatsby JS and Material UI. I'm wondering about the best approach for storing the site content. This website will serve as a promotional platform for a small business. Should I store the text direct ...

When HTML/JS code is utilized, the submit button or image should function to open the same page as

In addition to the left and right mouse buttons, you also have a middle mouse button. If you click on an image or hyperlink with this middle mouse button while browsing any website, it will open a new window in the background. Now, I want to achieve a sim ...

Triggering a button click to upload a file from within a grid view

I'm having trouble uploading a file when the "Fileupload" control inside gridview changes. I want to save the file content in DB as soon as it is uploaded by the user. I tried manually triggering the click event of the button control on the change of ...

Issue with Mongoose Promise failing to transfer data to the following chain

When querying MongoDB using mongoose with promises, I encounter an issue where the result is only accessible in the initial .then(function(results){ // can send the result from here..}). However, when I manipulate the results and attempt to pass them to th ...

Having trouble importing SVG as a React component in Next.js

I initially developed a project using create-react-app with Typescript, but later I was tasked with integrating next.js into it. Unfortunately, this caused some SVGs throughout the application to break. To resolve this issue, I implemented the following pa ...

Generate a unique splatter design using Cascading Style Sheets

Imagine a circle link that transforms into a playful animation with a pink shape when you move your mouse over it: I'm torn between different ideas on how to achieve this effect. One approach could be to use individual elements for each drop, utilizi ...

JavaScript confirmation for PHP delete button

Is there a way to implement a JavaScript alert that prompts the user to confirm their action when they click the delete button? I attempted to integrate a class into an alert box: <?php //$con = mysqli_connect("localhost", "root", "root", "db"); $sql ...

Issue with dynamic form JavaScript functionality after removing curly braces { } from a select tag in Rails

In my Rails form, there is a gender field defined as follows: <%= f.select :gender, ["Male","Female"],{class: "gender"} %> I also tried adding an onclick event like this: <%= f.select :gender, ["Male","Female"],{class: "gender"},onclick: "categ ...

Combine strings in PHP with an alert box in JavaScript

Is there a way to concatenate a string in a JavaScript alert box? I want the first part of the alert box to be a simple text, while the second part is a string retrieved from a MySQL table. $myname = $row["name"]; echo ' <scri ...