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

Allow giving detox config file as param, with fallbacks #906

Closed
wants to merge 17 commits into from

Conversation

oreporan
Copy link
Contributor

@oreporan oreporan commented Aug 29, 2018

Solves issue #901

I couldn't really add specific tests for this, maybe you can help me out on where.
Because the e2e is basically one project, so its already taking the config from the tests/package.json and I'm not sure adding another test just for this is justified

@oreporan
Copy link
Contributor Author

Anyone help me out on why this is failing?
Looks unrelated to me

@haswalt
Copy link
Contributor

haswalt commented Aug 30, 2018

Android tests always fail that I can see. This PR is about fixing that #910 so yeah unrelated.


function getConfigurationFile(configPath) {
let config;
if (configPath) config = require(path.join(process.cwd(), configPath));
Copy link
Contributor

Choose a reason for hiding this comment

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

What would happen if configPath is not a relative path, say like /Users/me/myConfig.json?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, added if/else on isAbsolute()

}
}

function getConfigurationFile(configPath) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the need for duplication? Can't you use the same function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, added a util method

@LeoNatan
Copy link
Contributor

LeoNatan commented Sep 2, 2018

Thanks for this PR!
A few questions from me.

@noomorph
Copy link
Collaborator

@oreporan, firstly, thanks for submitting the PR. 👍 I'd also love to see this feature in Detox. However, from my perspective, it still lacks a few things to get it merged, including but not limited to the updates to Detox CLI documentation.

I'll review it more thoroughly within the next few days, and get back to you with a list of TODOs. Cheers!

@oreporan
Copy link
Contributor Author

Let me know what to do, I'd like to get this in, in the near future
It will really cleanup our package.jsons

@oreporan
Copy link
Contributor Author

oreporan commented Oct 2, 2018

Anyone had a chance to look at this? PR has been open for over a month now

@rotemmiz
Copy link
Member

rotemmiz commented Oct 2, 2018

Hey @oreporan, I have a few nitpicks (naturally) :)

  1. Let's change the file name from .detoxrc.json to .detoxrc
  2. Can you please add documentation in the relevant sections ? (added links)
    https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md#3-add-detox-config-to-packagejson
    https://github.com/wix/Detox/blob/master/docs/APIRef.Configuration.md#device-configuration
  3. Ideally I would like to test this somehow, but the cli code is not tested at all... our bad.

Thanks!

@oreporan
Copy link
Contributor Author

oreporan commented Oct 2, 2018

@rotemmiz
Thanks, made the changes. Not sure what change is needed in
https://github.com/wix/Detox/blob/master/docs/APIRef.Configuration.md#device-configuration

However I did add it to now to docs/APIRef.DetoxCLI.md

@@ -72,7 +72,7 @@ Run a command defined in 'configuration.build'
| --- | --- |
| -h, --help | output usage information |
| -c, --configuration \<device config\> | Select a device configuration from your defined configurations,if not supplied, and there's only one configuration, detox will default to it |
| --config-path \<configPath\> | Select a device config-file path, if not supplied, detox will default to the package.json, and if not found there, detox will fallback to .detoxrc.json |
Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Collaborator

@noomorph noomorph left a comment

Choose a reason for hiding this comment

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

The pull request is not ready IMO.
Could you fix please feedback before we move further?

@@ -21,6 +21,8 @@ program
'Disable colors in log output')
.option('-c, --configuration [device configuration]',
'Select a device configuration from your defined configurations, if not supplied, and there\'s only one configuration, detox will default to it', getDefaultConfiguration())
.option('--config-path [configPath]',
'Select a device config-file path, if not supplied, detox will default to the package.json, and if not found there, detox will fallback to .detoxrc', getDefaultConfiguration())
Copy link
Collaborator

Choose a reason for hiding this comment

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

@oreporan , why is getDefaultConfiguration() is called for both parameters? Shouldn't it be a .detoxrc or something like that?

detox/src/utils/getConfigurationFile.js Outdated Show resolved Hide resolved
if (!config) config = require(path.join(process.cwd(), packageJson)).detox;
if (!config) {
try {
config = require(path.join(process.cwd(), detoxRc));
Copy link
Collaborator

@noomorph noomorph Oct 2, 2018

Choose a reason for hiding this comment

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

Why try is used only here? Did you mean fs.existsSync() ?

function getConfigurationFile(configPath) {
let config;
if (configPath) config = require(path.isAbsolute(configPath) ? configPath : path.join(process.cwd(), configPath));
if (!config) config = require(path.join(process.cwd(), packageJson)).detox;
Copy link
Collaborator

Choose a reason for hiding this comment

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

All this require(path.join(process.cwd(), blabla)) looks repetitive and can be refactored to a method.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, I don't like these tricks with path.isAbsolute() ? ... : .... I think that this method is more appropriate: path.resolve([...paths]) - Path | Node.js v10.11.0 Documentation

if (!config) {
try {
config = require(path.join(process.cwd(), detoxRc));
} catch (error) {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do you suppress the error? If users have a malformed .detoxrc, how do you let them know about that?

Can you test whether the exceptions thrown on malformed or missing jsons are actually readable and clear? Good if you attach screenshots of the detox cli exceptions on these cases.

return config
}

module.exports = getConfigurationFile;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where are the tests?

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 how I can test these changes other configurations. As it seems that there is 1 app which is being tested, and it has its config in the package.json

@@ -204,8 +207,9 @@ function clearDeviceRegistryLockFile() {
}

function getDefaultConfiguration() {
if (_.size(config.configurations) === 1) {
return _.keys(config.configurations)[0];
const file = getConfigurationFile();
Copy link
Collaborator

@noomorph noomorph Oct 2, 2018

Choose a reason for hiding this comment

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

I counted that getConfigurationFile() is actually called three times here. It does not look simple and concise, can it be rewritten in a cleaner way?

@oreporan
Copy link
Contributor Author

oreporan commented Oct 2, 2018

trying to re-run the tests locally fails in:


❌  error: Build input file cannot be found: '/.../detox/detox/test/node_modules/react-native/Libraries/WebSocket/libfishhook.a'

I've recently updated to xcode 10

@noomorph
Copy link
Collaborator

noomorph commented Oct 3, 2018

@oreporan , it's not Detox issue AFAI can see. Have you tried to google it?
That's what I found recently on this: facebook/react-native#19569

.option('--config-path [configPath]',
'Select a device config-file path, if not supplied, detox will default to the package.json, and if not found there, detox will fallback to .detoxrc')
.option('-c, --configuration [device configuration]', 'Select a device configuration from your defined configurations,' +
'if not supplied, and there\'s only one configuration, detox will default to it', getDefaultConfigurationFile())
Copy link
Collaborator

Choose a reason for hiding this comment

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

@oreporan , why getDefaultConfigurationFile()? Come on, it is a string like android.emu.release, ios.sim.debug, why require file? It is the second time I write it to you.

@noomorph
Copy link
Collaborator

noomorph commented Oct 3, 2018

@oreporan , yes, something like that. Maybe, at the end of the day, detox does not need arguments in detox.init() at all, if you are able to figure out that from the launch args (see detox/src/utils/argparse.js)

@oreporan
Copy link
Contributor Author

oreporan commented Oct 4, 2018

@noomorph
I think removing the param from init() would be a breaking change wouldn't it?
Because if a user does choose to put the param, should it be stronger than the CLI command? should it throw an error?

Maybe this is a separate PR?

@@ -204,8 +207,9 @@ function clearDeviceRegistryLockFile() {
}

function getDefaultConfiguration() {
if (_.size(config.configurations) === 1) {
return _.keys(config.configurations)[0];
const file = new ConfigurationResolver().getDetoxConfiguration();
Copy link
Collaborator

@noomorph noomorph Oct 4, 2018

Choose a reason for hiding this comment

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

Why instantiate ConfigurationResolver many times? I see there is already ConfigurationResolver.default in the code, so you can require it.

@@ -0,0 +1,57 @@
const fs = require('fs');
Copy link
Collaborator

Choose a reason for hiding this comment

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

You know... since the number of possible run environments is limited to 4, it would make sense to create four folders in __mocks__/configuration-resolver-it/, e.g.:

  • __mocks__/configuration-resolver-it/detoxrc-and-package/
  • __mocks__/configuration-resolver-it/detoxrc/
  • __mocks__/configuration-resolver-it/package/
  • __mocks__/configuration-resolver-it/blank/

I think tests would be more readable then, with less hassle about creating the environment dynamically.
Also, there are no tests for unhappy paths when a resolved file is not found or is malformed.

}

loadDetoxrcConfiguration() {
var data = fs.readFileSync(this.resolvePath(detoxRc)).toString();
Copy link
Collaborator

@noomorph noomorph Oct 4, 2018

Choose a reason for hiding this comment

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

Is there a specific consideration of why you want to limit .detoxrc to JSON format only?
Personally, I'd love to be able to evaluate it as JS, I'm confident that some people would be happy too and sure they'll find their way how to leverage that.

Copy link
Member

Choose a reason for hiding this comment

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

So what do you suggest ? this can (and should) be separated and added in a later PR IMO.

Copy link
Member

Choose a reason for hiding this comment

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

this == js evaluated config (.detoxrc.js, detox.config.js, etc)

Copy link
Collaborator

@noomorph noomorph Oct 8, 2018

Choose a reason for hiding this comment

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

@rotemmiz , I suggest using plain require() instead of JSON.parse(fs.readFileSync...

@noomorph
Copy link
Collaborator

noomorph commented Oct 4, 2018

@oreporan , I think if you make this place less stricter...

https://github.com/wix/Detox/blob/master/detox/src/index.js#L41

...then it won't quite be a breaking change, rather a new feature.

You can use argparse.getArgValue('config-path') and if it is not there, there is still ConfigurationResolver who is smart enough to figure out it needs to be package.json, since you have already implemented in that class the fallback logic to load .detoxrc or package.json.

@noomorph
Copy link
Collaborator

noomorph commented Oct 4, 2018

@oreporan, because, otherwise... what is the sense in this pull request - without config resolution on the test runner side? I don't see scenarios where it can be helpful while being half-baked... if I am correct, then it would just always get overridden by what's in package.json.

As for the situation where the detox.init() is called with a hardcoded config, it should be more or less trivial - you load a configuration specified in --config-path and if it is not equal to config passed into the detox.init(config), you print an error that helps the user to figure out that if they want to use .detoxrc or --config-path feature, then they should remove their detox.init(packageJson.detox, settings) in favor of detox.init(null, settings) to enable automatic config resolution.

@rotemmiz
Copy link
Member

Hey! Can we wake this PR up? I want to see it passes CI so we can accept it! There's so much work here, would be shame if it goes to waste.

@noomorph
Copy link
Collaborator

@rotemmiz, I like this PR as well, but it's not finished. There's still detox.init() rewrite pending.

I'm wondering if I might continue the work to complete it. 😕

@oreporan
Copy link
Contributor Author

sorry, been busy - didn't have much time to work on it

@stale
Copy link

stale bot commented Jan 1, 2019

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the 🏚 stale label Jan 1, 2019
@jgreen210
Copy link

jgreen210 commented Jan 2, 2019

Commenting to keep the PR alive...

Improving detox's configurability would be very useful. Having to hard code things in package.json is often inconvenient.

@stale
Copy link

stale bot commented Jan 11, 2019

The issue has been closed for inactivity.

@rotemmiz
Copy link
Member

Reopening.
@oreporan do you need help finishing this?

@stale stale bot removed the 🏚 stale label Jan 13, 2019
@stale
Copy link

stale bot commented Feb 27, 2019

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the 🏚 stale label Feb 27, 2019
@stale
Copy link

stale bot commented Mar 6, 2019

The issue has been closed for inactivity.

@stale stale bot closed this Mar 6, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Mar 9, 2019
@noomorph noomorph reopened this Mar 20, 2019
@stale stale bot removed the 🏚 stale label Mar 20, 2019
@LeoNatan
Copy link
Contributor

This seems dead and there is another PR (#1238) on this subject. Closing

@LeoNatan LeoNatan closed this Apr 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants