Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first baby steps towards native browser support for the JS sdk of testground #25

Closed
wants to merge 5 commits into from

Conversation

GlenDC
Copy link
Contributor

@GlenDC GlenDC commented Oct 27, 2022

I am by far no NodeJS expert, so please do help me adapt to this culture where you see fit.

With this PR I distinguish in some first starter locations between the browser and node environment. Currently I do this using process.title:

Seems to me like a clean way, but if there's a more natural way, do let me know.

Currently there are the following changes where we differentiate between browser and NodeJS:

  • creating a runtime uses the process.env, this is however not available in browser (and it is empty using the shim pacakge), so here we opt to assume that the env variables are available under window.testground.env, which are to be injected by the user of the js sdk in the browser;
  • for the logging we currently also create a file on the local FS (the output log file?), this is not possible in browser, so I just disable that single output, other outputs do still function;

This is just the beginning though, I imagine there is even more we can do and want to do if native browser support for sdk-js is what we want. My current aim is to make it as easy to use as in NodeJS, meaning that the code can just be used and it will pull all it needs in the background (e.g. env variables).

Things to keep in mind...

  1. for now we still need to polyfill a lot when web-packing, e.g. this is what I have for a testground plan in my webpack config file:
resolve: {
    extensions: ['.js'],
    fallback: {
      fs: false,
      os: require.resolve('os-browserify'),
      path: require.resolve('path-browserify'),
      https: require.resolve('https-browserify'),
      crypto: require.resolve('crypto-browserify'),
      http: require.resolve('stream-http'),
      zlib: require.resolve('browserify-zlib'),
      buffer: require.resolve('buffer/'),
      url: require.resolve('url/'),
      'assert/': require.resolve('assert/'),
      stream: require.resolve('stream-browserify')
    }
  },
  plugins: [
    new webpack.ProvidePlugin({
      Buffer: ['buffer', 'Buffer']
    }),
    new webpack.ProvidePlugin({
      process: 'process/browser'
    })
  ],

Could be great if out of the box, the sdk-js already does a lot of that for us, or ensures that what it uses is more cross-platform and thus does not need to be shimmed?

  1. I am no expert of this library, so there might be even more places where we need to add some different logic for clean browser support. Please do point me to these locations if you know of any.

Finally we might also want to add some documentation on pointers for some gotcha's, hints, etc. All related to usage in browser.

glendc added 5 commits October 1, 2022 09:13
- switch to polyfill process name for browser detection
  as to make this automatic, rather than explicit
- make currentRunEnv also work from a browser
transports.push(new winston.transports.File({
format,
filename: path.join(params.testOutputsPath, 'run.out')
filename: 'stdout'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is due to a merge from an older master version. Should I remove this all together?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, what did you merge? What would you like to remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure anymore, going to clean it up.

return parseRunEnv(window.testground.env)
} else {
return parseRunEnv(process.env)
}
Copy link
Contributor

@laurentsenta laurentsenta Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this standard? Else, could we simplify with something like process.env || window.testground.env?

Got it, that's in the PR description.
Could we move the checks like if proces.title into a single function if (isBrowser()) for example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will drop this in favour of the browser spec.

format,
filename: path.join(params.testOutputsPath, 'run.out')
}))
}
}

return winston.createLogger({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(creating a thread)

You listed a lot of fallback libraries, do you know what purpose they solve? (for example the path library might "just" be required by the winston logger).

@achingbrain shared an interesting option: It might be enough to use the browser field to shim the features that are not isomorphic (the loggers creation and the env retrieval): https://github.com/defunctzombie/package-browser-field-spec#replace-specific-files---advanced

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They solve the purpose of being able to run the testground plan without runtime errors, so that collection get assembled in a trial-error approach. I'll look into the browser field, haven't used that before, so if you could give some practical example of how you see that that would be great. Either way I'll give it a look.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok got'cha, you shared it in the other thread already :)
(#25 (comment))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to get rid of the fallback libraries however we might need to either make winston-js browser friendly (e.g. see winstonjs/winston#2196) or from our end (sdk-js) make the logging different for browser vs node.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This winstonjs/winston#287 was opened in 2013

It's very likely this will take us month(s) to get browser support in winston,
I'd recommend you try this: https://stackoverflow.com/a/55433049/843194
and else, "just" return a console object when we're in the browser.

We can tackle full support for logging as a follow-up issue (related: testground/testground#1355)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to worry, that’s already an approach I’m taking on my local replace branch. Sorry if i didn’t communicate that yet

format,
filename: path.join(params.testOutputsPath, 'run.out')
}))
}
}

return winston.createLogger({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(creating a thread)

You listed a lot of fallback libraries, do you know what purpose they solve? (for example the path library might "just" be required by the winston logger).

@achingbrain shared an interesting option: It might be enough to use the browser field to shim the features that are not isomorphic (the loggers creation and the env retrieval): https://github.com/defunctzombie/package-browser-field-spec#replace-specific-files---advanced

A few examples he shared:

// get-env.js
export function getEnv() {
  return process.env
}

// get-env.browser.js
export function getEnv {
  return window.testground.env
}

// package.json
"exports": { // used by external imports
  "./get-env": {
    "browser": "get-env.browser.js",
    "import": "get-env.js"
  }
},
"browser": { // used by internal imports (e.g by esbuild before building code for running unit tests)
  "get-env.js": "get-env.browser.js"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok nice, so kinda like what you would do with C macro's in C/C++, go file suffixes and cfg-like macro's in Rust. Got-cha. That does look a lot cleaner indeed. Will play with it this week and see how far I get.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok read the spec, seems fine. Going to adapt the PR to this format.

@GlenDC
Copy link
Contributor Author

GlenDC commented Nov 9, 2022

Replaced this PR with #26.

@GlenDC GlenDC closed this Nov 9, 2022
laurentsenta pushed a commit that referenced this pull request Nov 16, 2022
- use shims + browser field to support
- add registerTestcaseResult to communicate end of test with a node runner when running in-browser
- Expose getEnvParameters to let a client gather and move testground variables (used for browser support).
- Supersede #25, having applies all the previous feedback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants