Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Fix adding config hooks to existing example groups #2280

Merged

Conversation

eugeneius
Copy link
Contributor

Followup to #2189.

When an example group is created, the existing config hooks are added to it if their metadata filters match and none of the new example group's parent groups already have the hook added.

The current implementation adds new config hooks to all existing example groups, which means they can be run multiple times if several nested example groups all match their metadata filters, which doesn't happen if the config hook is defined first.

To get the same behaviour regardless of the order in which hooks and groups are defined, we can walk the inheritance hierarchy starting from the top level example groups, and only add the new hook to the first matching group on each branch.

@myronmarston
Copy link
Member

Can you rebase this against master? #2279 fixes the build failures you are seeing here.

@@ -2033,6 +2032,12 @@ def on_existing_matching_groups(meta)
end
end

def add_hook_to_existing_groups(prepend_or_append, position, *meta, &block)
Copy link
Member

Choose a reason for hiding this comment

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

Instead of adding a hook-specific method (which in turn delegates to some new logic added to the Hooks module for this case), is there a way to make on_existing_matching_groups handle nested groups properly? It would be nice if the generic logic in configuration for applying metadata-based config to existing groups worked with nested groups so we don't have to solve issues like this in an ad-hoc manner for each metadata-based config 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.

I thought the behaviour of helper modules and hooks were too different to use the same logic - helper modules are currently applied to every existing matching group, whereas hooks need to only be applied to the highest level matching groups.

However it looks like when creating a new example group, helper modules work that way too: https://github.com/rspec/rspec-core/blob/v3.5.0/lib/rspec/core/configuration.rb#L2044

I pushed a new commit that updates the behaviour of on_existing_matching_groups, and uses it to apply both helper modules and hooks. I'm not happy with some things about the implementation - I'll comment inline where I suspect there might be a better way to do something.

If we want to go in this direction, I think we should fix the behaviour of helper modules separately, and then rebase this change to just fix the issues with hooks afterwards.

When an example group is created, the existing config hooks are added to
it if their metadata filters match and none of the new example group's
parent groups already have the hook added.

The current implementation adds new config hooks to all existing example
groups, which means they can be run multiple times if several nested
example groups all match their metadata filters, which doesn't happen if
the config hook is defined first.

To get the same behaviour regardless of the order in which hooks and
groups are defined, we can walk the inheritence heirarchy starting from
the top level example groups, and only add the new hook to the first
matching group on each branch.
@eugeneius eugeneius force-pushed the fix_adding_hooks_to_existing_groups branch 2 times, most recently from 639c720 to 93b16b2 Compare July 5, 2016 02:08
For the behaviour when apploying helper modules to existing example
groups to be fully consistent with the behaviour for new groups, we
shouldn't apply the module if any of the example group's parent groups
already have the module applied.

Also refactor how we add hooks to existing groups to use the same code.
@eugeneius eugeneius force-pushed the fix_adding_hooks_to_existing_groups branch from 93b16b2 to 7e1799d Compare July 5, 2016 02:16
until groups.empty?
group = groups.shift

if scope == :example || scope == :each || scope.nil? ||
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This duplicates some very specific hook-related logic:

In the previous implementation this logic were still duplicated, but at least it was still in the Hooks module.

@myronmarston
Copy link
Member

Thanks for pushing your updates, @eugeneius! I'm going to try to review it tomorrow.

@JonRowe
Copy link
Member

JonRowe commented Jul 6, 2016

I ran into the same problem today and I can confirm this branch fixes the issue FWIW

@myronmarston
Copy link
Member

Great work, @eugeneius!

@myronmarston myronmarston merged commit c1d092d into rspec:master Jul 6, 2016
myronmarston added a commit that referenced this pull request Jul 7, 2016
@eugeneius
Copy link
Contributor Author

Thanks for the review @myronmarston! 🙏

@myronmarston myronmarston mentioned this pull request Jul 7, 2016
myronmarston added a commit that referenced this pull request Jul 7, 2016
MatheusRich pushed a commit to MatheusRich/rspec-core that referenced this pull request Oct 30, 2020
…ting_groups

Fix adding config hooks to existing example groups
MatheusRich pushed a commit to MatheusRich/rspec-core that referenced this pull request Oct 30, 2020
yujinakayama pushed a commit to yujinakayama/rspec-monorepo that referenced this pull request Oct 6, 2021
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.

3 participants