Closed aberonni closed 7 years ago
what would be the use case for doing this?
Let's say I manage multiple websites that have a common structure. I develop some sort of common code base that contains complete tests and should cover all websites.
So for each website I create a separate project that imports this common codebase and needs to overwrite one of the custom commands because it has an exception compared to all of the other websites.
So I'd end up with something like this
├── common codebase
│ └── custom_commands
│ └── common1.js
│ └── common2.js
│ └── common3.js
└── specfiic website codebase
└── custom_commands
└── specific1.js
└── common1.js
custom_commands_path: [
'common codebase/custom_commands',
'specific website codebase/custom_commands'
]
I realise it isn't a normal scenario but I maybe someone else might find this useful for other reasons so I thought I might propose it. If it is integrated as a boolean in the configuration it doesn't change default behavior.
I like the idea of @aberonni, we also have to write integration tests for ~40 websites which share a common codebase, but some of them have some exceptions. So we would use this too! I think it's very useful. @beatfactor what do you think of making this a flag in the configuration file?
This isn't going to work. Custom commands are loaded during initialization and if you overwrite a custom command in another folder it will be overwritten for all your tests. What you could do is to use separate config files and define your custom_commands_path as needed. You can also use a .js file as the config file - nightwatch.conf.js will be loaded automatically and will take precedence over nightwatch.json.
I submitted a PR with a flag that enables this feature. I tested with my scenario and it works just as I need it to.
Just to be clear, in my case I launch nightwatch separately for each website so each website has a separate code base that imports the common one. This way I can overwrite specifics for each website.
Yes, so then I guess you are passing a separate config file for each website or a separate environment?
Yes exactly, and in each config file I have a custom_commands_path like the one in my second example..
Closed by mistake :smile:
I still think it is possible for you to structure your custom commands without the need for an additional setting added. For example:
├── custom_commands
│ └── command1.js
│ └── command3.js
├── other_custom_commands
│ └── command2.js
└── even_more_custom_commands
└── command2.js
And then use it as:
custom_commands_path: [
'common codebase/custom_commands',
'common codebase/other_custom_commands',
]
and
custom_commands_path: [
'common codebase/custom_commands',
'specific website codebase/even_more_custom_commands',
]
Wouldn't that work?
That wouldn't work for me because I want command2.js to be available to all projects that don't need specific adjustments without copy pasting the file into all projects.
With the file structure that you suggested, any change to the common command2.js would have to be copy pasted into all projects.
Just to recap, 99/100 of the projects are like this:
├── common/custom_commands
│ └── command1.js
│ └── command2.js
│ └── command3.js
├── specific_commands
└── specificCommand1.js
└── specificCommand2.js
└── specificCommandN.js
Then I have one single project that has this:
├── common/custom_commands
│ └── command1.js
│ └── command2.js
│ └── command3.js
├── specific_commands
└── specificCommand1.js
└── specificCommand2.js
└── specificCommandN.js
└── command2.js
Because it is the only project that needs to override the common custom command that all of the other projects are using. This way I could use the same exact steps for both projects and just overwrite the command that needs a behavior that is specific to only one project.
All of these projects have this configuration:
custom_commands_path: [
'common/custom_commands',
'specific_commands',
]
This way I don't pollute my common codebase adding files that are only relative to one single project.
One extra thing I forgot to mention: the people that handle the common codebase aren't necessarily the same people that handle the code for the specific projects.
So more often than not, the command that should overwrite the original will be defined in the specific project without the common codebase 'owners' even knowing it, nor caring about it.
Hi, any updates on this?
Only skimmed here, but would reversing the order of your paths work? Then the ones you want to override the others are added first and the originals are the ones that get blocked.
Hi @senocular, that is what I'm trying to achieve. The problem is that atm nightwatch throws an error if there are two conflicting commands with the same name.
My PR would allow users to decide whether they want an error to be thrown or if they want to allow commands to be overwritten.
@aberonni Oops, my mistake. I was missing the fact that a fatal error is thrown rather than it being something more like a warning with the run continuing just without the replacement happening. I'm with you now.
I'm a bit skeptical to this feature, as I feel it is a bit dangerous. The main reason is that custom commands share the same namespace as the core nightwatch api and so a nightwatch command could be easily overridden without the user realising it, even with the toggle. Maybe it would be ok if only you could overwrite custom commands but that's not really possible given the current architecture. Another concern is that a new nightwatch command could be added in a future version with the name of an existing custom command and the collision would create an unpredictable situation.
@beatfactor Incidentally, there is no protection for this with page objects and page object commands, as seen with:
https://groups.google.com/forum/#!topic/nightwatchjs/9KcQ9DVp_D4/discussion
Relevant command handling code:
https://github.com/nightwatchjs/nightwatch/blob/master/lib/page-object/page-utils.js#L80
Though pages do have a kind of fallback for this in that you can instead use page.api
, though you'll lose element support (and of course command chaining context has changed). I don't know if this was intended or an oversight ... ?
The namespace issue can be a complicated one. You not only have api, but extensions of that (in a way) with pages and sections. They also get access to custom commands but have a different interface for potential collisions (parent
, getUrl
, etc.). Combine that with page object commands (which are more like methods, since they're not added to the command queue like other custom commands), and how they stomp on whatever haphazardly and it gets a little more messy. Then you have something like #884 - one I've attempted to come up with a solution for but it didn't quite work out as nicely as I'd hoped.
That being said, as far as limiting custom commands overwrites, this can probably be achieved with a buffer target during command loading. Run through all of the custom command modules, adding those commands to the buffer, allowing overwrites, then copy from that buffer into the api, and only then, throwing on duplicates. It sounds simple enough in my head (don't they all?); maybe I'll try to shoot out a PR for it tonight.
About page objects not having protection against collisions it's probably an oversight and should work the same way. Limiting overwrites to custom commands might be a solution, although it will inevitably introduce some considerable complexity and given the fact that is probably not on everyone's top wish list of things to be added/fixed, it could be a while until it's accepted.
@aberonni Here is a branch you can try to see if it does what you need. I haven't tested it much (nor have I written any tests for it) but I'd thought I'd throw it your way first.
https://github.com/senocular/nightwatch/tree/960-replace-custom-commands
This only applies to custom commands, not anything else, like custom assertions. They're different code paths, but I'm assuming this is what you were after anyway.
@senocular I gave it a quick test and it seems to be working just like I imagined it would.
Closing this because I don't need the feature anymore. Will reopen if anyone mentions it.
Given a folder structure similar to this:
I insert in my config.js this:
I currently receive the error
The command "command2" is already defined!
.I would like to able to overwrite the command in the first folder with the command in the second folder. I guess ideally this could be a configurable option in the config.js file.
I've already seen where this option could be handled in the addCommand function, if this feature request is aplroved I would be happy to submit a Pull Request.