1

I have an array of strings. I need to grab the URL's value on each string. I have created a function with Regex to accomplish this. It works fine, but there's an edge case I haven't been able to cover. When there is not any URL:'s value, I get the error: Cannot read property '1' of null.

This is my code:

const arrStr = [
  `describe
    url: https://url-goes-here-/1,
         https://url-goes-here-/2,
         https://url-goes-here-/3
  });`
  ,
  `
  before(() => {
    url: https://url-goes-here-/4
  });
  `,
  `
  before(() => {
    url: https://url-goes-here-/5
  });
  `,
  `describe
    // nothing http link here
  });
  `
]

const getXrayUrl = str => str.match(/url:([^;]+)/)[1].trim().split('(')[0]; // cannot read property '1' of null

const allXrayUrls = arrStr.map(item => getXrayUrl(item));

If I removed the string with no URL value from the array, I get this output:

[ 'https://url-goes-here-/1,\n         https://url-goes-here-/2,\n         https://url-goes-here-/3\n  })', 
  'https://url-goes-here-/4\n  })', 
  'https://url-goes-here-/5\n  })' ]

How do I cover this edge case & return another array with all the string in the level?

1
  • 3
    Because if match doesn't match, it returns null, not an empty array. Attempting to get the 1 property of null throws an error (because null isn't an object). So if match returns null, substitute an empty array, e.g. (str.match(/url:([^;]+)/) || [])[1] so if there's no match, the expression returns undefined rather than throwing an error. Commented Jan 14, 2021 at 22:25

1 Answer 1

1

According to match function documentation, it returns an array of matches, or null if no matches are found.

If you need to handle the case of a missing URL attribute so check match array is null before accessing the capture group as following:

const match = str.match(/url:\s*([^;]+)\n/)
// in case no match retrun empty string
// split the match on , to handle multi URL case
const url = match? match[1].split(",").map(item => item.trim()) : [""];

after that filter match results removing empty values as following:

arrStr.map(getXrayUrl).flat().filter(item => item !== "");

so final solution as following:

const arrStr = [
  `describe
    url: https://url-goes-here-/1,
         https://url-goes-here-/2,
         https://url-goes-here-/3
  });`
  ,
  `
  before(() => {
    url: https://url-goes-here-/4
  });
  `,
  `
  before(() => {
    url: https://url-goes-here-/5
  });
  `,
  `describe
    // nothing http link here
  });
  ` 
]

const getXrayUrl = str => {
    const match = str.match(/url:\s*([^;]+)\n/)
    // in case no match retrun empty string
    // split the match on , to handle multi URL case
    return match? match[1].split(",").map(item => item.trim()) : [""];
}

const allXrayUrls = arrStr.map(getXrayUrl).flat().filter(item => item !== "");

console.log(allXrayUrls)

console output:

["https://url-goes-here-/1", "https://url-goes-here-/2", "https://url-goes-here-/3", "https://url-goes-here-/4", "https://url-goes-here-/5"]
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, it worked like a charm bro! Do you know how to make the first three URLs returned as an array as well? ``` [ "url-goes-here-/1", "url-goes-here-/2", "url-goes-here-/3", "url-goes-here-/4", "url-goes-here-/5" ]
@ManuelAbascal check the updated solution Is it fit what you want?
Yes it is! However, the first item on the array contains three URLs instead of one, how can flatten it?
I already updated the solution to fix this issue try it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.