selenium-ide icon indicating copy to clipboard operation
selenium-ide copied to clipboard

where to take the global.baseUrl from?

Open matewilk opened this issue 2 years ago • 8 comments

💬 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:

matewilk avatar Apr 17 '23 12:04 matewilk

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}}"`
)

toddtarsi avatar Apr 17 '23 17:04 toddtarsi

@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.

toddtarsi avatar Apr 24 '23 02:04 toddtarsi

Hey @toddtarsi

Much appreciated. Looking good, thanks.

I wish I was able to give you better feedback :)

matewilk avatar Apr 25 '23 11:04 matewilk

@matewilk - Good enough for me, merging! :)

toddtarsi avatar Apr 25 '23 13:04 toddtarsi

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.

matewilk avatar May 09 '23 13:05 matewilk

Absolutely @matewilk - I'll take a look tonight, thanks for the report.

toddtarsi avatar May 09 '23 14:05 toddtarsi

Hi @toddtarsi, any chance you could look into it anytime soon or need any help with this?

matewilk avatar May 17 '23 09:05 matewilk

@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.

toddtarsi avatar May 17 '23 17:05 toddtarsi