selenium-ide
                                
                                 selenium-ide copied to clipboard
                                
                                    selenium-ide copied to clipboard
                            
                            
                            
                        where to take the global.baseUrl from?
💬 Questions and Help
I'm building an exporter base on the side-example-suite.
My emitOpen method looks exactly the same as it does in the example (obviously with a different resolution):
const emitOpen = async (target: string) => {
  const url = /^(file|http|https):\/\//.test(target)
    ? `"${target}"`
    : // @ts-expect-error globals yuck
      `"${global.baseUrl}${target}"`
  return Promise.resolve(`await $webDriver.get(${url})`)
}
my test.side file looks like this (only relevant parts)
{
  "id": "d4813a60-3e17-4c16-a1ca-8bbac14405a8",
  "version": "2.0",
  "name": "exporter",
  "url": "https://newrelic.com", // <<---- top level url
  "tests": [{
    "id": "517b428b-e343-4e81-9200-ca5c47550ef6",
    "name": "newrelic",
    "commands": [{
      "id": "01ce526c-abb8-4cc8-8e46-b07bc003dab4",
      "comment": "",
      "command": "open",
      "target": "/",
      "targets": [],
      "value": ""
    },
    // other commands here
    ]
  }],
  "suites": [{
    "id": "94b2aca7-c575-4032-b71b-9a7bd99f47fa",
    "name": "NewRelic",
    "persistSession": false,
    "parallel": false,
    "timeout": 300,
    "tests": ["517b428b-e343-4e81-9200-ca5c47550ef6"]
  }],
  "urls": ["https://newrelic.com/"],
  "plugins": []
}
When I run it using:
"build:code": "side-code-export ./dist/index.js ./projects/test.side ./tests",
I don't have access to global.baseUrl.
When I debug, it's because I'm running it in node environment instead of some kind of jsdom and the global.baseUrl property doesn't exist.
But even though, shouldn't the base url be taken from the url property in the test.side file?
My output file has the following:
await $webDriver.get("undefined/")
Instead of the url, which is expected since my test environment doesn't have access to global.baseUrl as it's not defined.
So my question here is, how do I get access to the top level url prop from the test.side. As I'm assuming this should be the case here, but I'm equally happy to be proven otherwise and maybe I should be using a different setup for my tests?
Please note that this issue tracker is not a help form and this issue will be closed.
For questions or help please see:
- SeleniumHQ IRC channel
- SeleniumHQ Slack channel
- The Selenium Users google group
This is a fantastic explanation of the issue. I think this made sense in v3, when everything was using window objects for stuff. Later tonight, I'll take a look at reworking this to perhaps take a special string like {{BASE_URL}} or something like that in the string you supply. I think that would be for the best anyway. I'd love it if one day instead the format was composed like this so that you could use syntax highlighting in your commands:
filename: commands/open.js
driver.get(/^(file|http|https):\/\//.test("{{TARGET}}")
  ? "{{TARGET}}"
  : "{{BASE_URL}}{{TARGET}}"`
)
@matewilk - Ok I apparently lied about the tonight thing, but I have a PR here now if you'd like to review or anything!
https://github.com/SeleniumHQ/selenium-ide/pull/1625
Basically, just adding a secret third arg that is an escape hatch to basically everything. Admittedly, that doesn't factor in someone wanting to supply a custom base URL from the code build CLI, but probably just having some system to basically work is probably a big step up for now.
Hey @toddtarsi
Much appreciated. Looking good, thanks.
I wish I was able to give you better feedback :)
@matewilk - Good enough for me, merging! :)
Hey @toddtarsi
I've merged the changes and I think a bug crept in.
Before the merge, when I run emitWaitForWindow command I was getting everything back as expected, including the generateMethodDeclaration wrapper.
This is my command:
const emitWaitForWindow = async () => {
  const generateMethodDeclaration = (name: string) => {
    return {
      body: `async function ${name}(timeout = 2) {`,
      terminatingKeyword: '}',
    }
  }
  const commands = [
    { level: 0, statement: 'await $webDriver.sleep(timeout)' },
    { level: 0, statement: 'const handlesThen = vars["windowHandles"]' },
    {
      level: 0,
      statement: 'const handlesNow = await $webDriver.getAllWindowHandles()',
    },
    { level: 0, statement: 'if (handlesNow.length > handlesThen.length) {' },
    {
      level: 1,
      statement:
        'return handlesNow.find(handle => (!handlesThen.includes(handle)))',
    },
    { level: 0, statement: '}' },
    {
      level: 0,
      statement: 'throw new Error("New window did not appear before timeout")',
    },
  ]
  return Promise.resolve({
    name: 'waitForWindow',
    commands,
    generateMethodDeclaration,
  })
}
And the expected result:
async function waitForWindow(timeout = 2) {
  await $webDriver.sleep(timeout)
  const handlesThen = vars['windowHandles']
  const handlesNow = await $webDriver.getAllWindowHandles()
  if (handlesNow.length > handlesThen.length) {
    return handlesNow.find((handle) => !handlesThen.includes(handle))
  }
  throw new Error('New window did not appear before timeout')
}
Unfortunately, it seems like the generateMethodDeclaration is not being picked up anymore and I'm getting the following result:
// method declaration waitForWindow
  await $webDriver.sleep(timeout)
  const handlesThen = vars["windowHandles"]
  const handlesNow = await $webDriver.getAllWindowHandles()
  if (handlesNow.length > handlesThen.length) {
    return handlesNow.find(handle => (!handlesThen.includes(handle)))
  }
  throw new Error("New window did not appear before timeout")
// terminating keyword
The comments wrapping the above are coming from my index.ts file which has the generateMethodDeclaration function specified as follows:
terminatingKeyword: '// terminating keyword',
  commentPrefix: '//',
  generateMethodDeclaration: function generateMethodDeclaration(name: string) {
    return `// method declaration ${name}`
  },
So it looks to me like the generateMethodDeclaration coming from within a command is not being respected and a default generateMethodDeclaration is being used instead.
Would you be able to take a look at this? I've double checked everything on my side and it seems it has to be coming from
emit.ts which you've modified and I'm seeing generateMethodDeclaration has been shuffled around quite a bit.
Absolutely @matewilk - I'll take a look tonight, thanks for the report.
Hi @toddtarsi, any chance you could look into it anytime soon or need any help with this?
@matewilk - Thank you for offering. I might need help. I've been working on an issue in opentelemetryjs for my evenings for this week, and once I come back, all the windows executables of side-runner are having a jest problem, so I gotta get a windows box and figure that stuff out, so that's basically this week and next week.