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

Bugs/aperta 12001 cancel passive events on rr submit #3820

Merged

Conversation

benjaminkreen
Copy link
Contributor

@benjaminkreen benjaminkreen commented Dec 1, 2017

JIRA issue: https://jira.plos.org/jira/browse/APERTA-12001

What this PR does:

Submitting a reviewer report should cancel scheduled events in the passive state as well.

Special instructions for Review or PO:

See ticket for issue repro instructions.


Code Review Tasks:

Author tasks (delete tasks that don't apply to your PR, this list should be finished before code review):

  • I have ensured that the Heroku Review App has successfully deployed and is ready for PO UAT.

Reviewer tasks (these should be checked or somehow noted before passing on to PO):

  • I read through the JIRA ticket's AC before doing the rest of the review
  • I ran the code (in the review environment or locally). I agree the running code fulfills the Acceptance Criteria as stated on the JIRA ticket
  • I read the code; it looks good
  • I have found the tests to be sufficient for both positive and negative test cases

@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 1, 2017 22:30 Inactive
@benjaminkreen benjaminkreen force-pushed the bugs/APERTA-12001-cancel-passive-events-on-rr-submit branch from 601dd39 to f59ab5d Compare December 1, 2017 22:34
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 1, 2017 22:35 Inactive
@benjaminkreen benjaminkreen force-pushed the bugs/APERTA-12001-cancel-passive-events-on-rr-submit branch from f59ab5d to 97ec21b Compare December 1, 2017 22:53
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 1, 2017 22:53 Inactive
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 2, 2017 00:01 Inactive
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 2, 2017 00:18 Inactive
@@ -18,8 +18,9 @@ export default DS.Model.extend({

updateState: function(newState) {
const url = `/api/scheduled_events/${this.get('id')}/update_state`;
return this.get('restless').put(url, {state: newState}).then(() => {
this.set('state', newState);
return this.get('restless').put(url, {state: newState}).then((data) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the UI wasn't refreshing because the object was dirty and not reloading.

Copy link

Choose a reason for hiding this comment

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

Just a drive-by comment/question. I could not tell from the ember code: does pushing the payload update the state? If not, is the this.set still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

indeed this.store.pushPayload will update this ember object's state, hence I removed the this.set('state', newState);

Copy link
Contributor

Choose a reason for hiding this comment

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

What you did seems like an improvement to me, but I get the willies from this type of un-restful stuff in ember. Every call to 'restless' seems like tech debt to me, especially since the semantics are almost identical to a model update. Something like this would make me feel a lot better:

updateState(newState) {
  this.set('state', 'newState'})
  return this.save();
}

which is trivial to the point of being unnecessary (hence an indication that we're actually using ember data properly.

I wont insist that you change it, but just wanted to express my reservations about the pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agreed, I'm not sure why the scheduled_events_controller.rb was setup that way... I'd be down to refactor that in an empowerment ticket.

Copy link

Choose a reason for hiding this comment

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

Just a note that my question about whether the state was updated would have been unnecessary with this implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, i've fixed this, gonna push.

@@ -170,6 +170,6 @@ def thank_reviewer
end

def cancel_reminders
scheduled_events.active.map(&:cancel!)
scheduled_events.cancelable.each(&:cancel!)
Copy link
Contributor

Choose a reason for hiding this comment

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

props on spelling cancelable correctly. I definitely did not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

subject.scheduled_events.first.switch_off! # passive state
subject.scheduled_events.last.cancel! # cancel state
cancelable = subject.scheduled_events.select(&:may_cancel?) # omg it compares object ids and not row id.
allow(subject.scheduled_events).to receive(:cancelable).and_return(cancelable)
Copy link
Contributor

@JackLaBarba JackLaBarba Dec 4, 2017

Choose a reason for hiding this comment

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

What's the motivation behind stubbing this instead of using the real scope? If it's so you can test the scope in a non-tautological way it's probably worth breaking out a separate test for the scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@egh watched me struggle with this, basically when cancelable gets called, it returns an array of objects that while containing the same active record objects, they have different ruby object ids, which screws with rspec. so this ensures they have the right object ids.

Copy link
Contributor

Choose a reason for hiding this comment

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

ah yeah, I just talked to @egh. I understand now that this was necessary for the subsequent message expectations to be set up properly (otherwise they're set up on different objects than those used inside of cancel_reminders).

However, if you ditch those expectations (my comment below), you can also ditch this stubbing and make the test a lot more clear.

allow(subject.scheduled_events).to receive(:cancelable).and_return(cancelable)
subject.scheduled_events.each do |event|
count = event.canceled? ? 0 : 1
expect(event).to receive(:cancel!).exactly(count).times
Copy link
Contributor

@JackLaBarba JackLaBarba Dec 4, 2017

Choose a reason for hiding this comment

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

WDYTA setting up expectations about the ending data state rather than setting up message expectations? I think a test that essentially said "all three scheduled events should be cancelled" rather than "some number of models should have the cancel! messaged passed to them" is easier to follow, and more resilient to implementation changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

In my old age, I've started to shy away from test mocks and stubs unless there's a really good reason to use them (test speed, or an external service). I find that it's nice to get the extra coverage of integrations where you're able.

I'm going to paste this article without reading it: https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c hopefully it supports my point.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

diff --git a/spec/models/reviewer_report_spec.rb b/spec/models/reviewer_report_spec.rb
index ff46118346..79079bd9d0 100644
--- a/spec/models/reviewer_report_spec.rb
+++ b/spec/models/reviewer_report_spec.rb
@@ -173,13 +173,8 @@ describe ReviewerReport do
       subject.set_due_datetime # makes 3 scheduled events with active state
       subject.scheduled_events.first.switch_off! # passive state
       subject.scheduled_events.last.cancel! # cancel state
-      cancelable = subject.scheduled_events.select(&:may_cancel?) # omg it compares object ids and not row id.
-      allow(subject.scheduled_events).to receive(:cancelable).and_return(cancelable)
-      subject.scheduled_events.each do |event|
-        count = event.canceled? ? 0 : 1
-        expect(event).to receive(:cancel!).exactly(count).times
-      end
       subject.send(:cancel_reminders)
+      expect(subject.scheduled_events.all?(&:canceled?)).to be(true)
     end
   end
 end

does that look good?

Copy link
Contributor

Choose a reason for hiding this comment

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

love it. Thanks ben!

@@ -8,7 +8,8 @@ export default Ember.Component.extend({
actions: {
changeEventState(newVal) {
const state = newVal ? 'active' : 'passive';
this.get('event').updateState(state);
this.set('event.state', state);
this.get('event').save();
Copy link
Contributor

Choose a reason for hiding this comment

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

yay, we're using ember now :)

@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 4, 2017 19:59 Inactive
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 4, 2017 20:38 Inactive
Copy link
Contributor

@JackLaBarba JackLaBarba left a comment

Choose a reason for hiding this comment

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

Great changes here. In particular, thanks for the changes to make updating scheduled_events more restful. 👍

@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 4, 2017 22:19 Inactive
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 5, 2017 23:44 Inactive
@benjaminkreen benjaminkreen force-pushed the bugs/APERTA-12001-cancel-passive-events-on-rr-submit branch from 4f95a60 to 518f0ea Compare December 5, 2017 23:48
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 5, 2017 23:49 Inactive
@benjaminkreen benjaminkreen force-pushed the bugs/APERTA-12001-cancel-passive-events-on-rr-submit branch from 518f0ea to 0b33211 Compare December 6, 2017 00:08
@plos-ci-agent plos-ci-agent temporarily deployed to plos-ciagent-pr-3820 December 6, 2017 00:08 Inactive
@benjaminkreen
Copy link
Contributor Author

[60] pry(main)> ReviewerReport.joins(:due_datetime).where(state: ['submitted', 'invitation_not_accepted']).select { |x| x.scheduled_events.any?(&:may_cancel?) }.count
=> 1

So from my somewhat recent prod snapshot, there's only one outstanding reviewer report that would need migrating. If that's still the case, i'd just sweep it under the rug, it will go away once that decision is made (I think).


before_save :deactivate, if: :should_deactivate?
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 grepped pretty hard, I think this event is only used internally.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe you

@egh
Copy link
Contributor

egh commented Dec 6, 2017

@benjaminkreen "on hold" or "merge when green"? :)

@benjaminkreen
Copy link
Contributor Author

its good from a PO stance, I just wanted to run my last commit by @slimeate

@@ -38,12 +41,13 @@ def finished?
state :errored
state :passive
state :canceled # Canceled automatically after a qualifying event, e.g., a review is submitted
state :deactivated

event(:reactivate) do
transitions from: [:completed, :inactive], to: :active
Copy link
Contributor

Choose a reason for hiding this comment

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

We'll probably want to add the ability to reactivate disabled events. Ensure that we haven't reintroduced APERTA-11985.

Btw, check out my comment here: https://jira.plos.org/jira/browse/APERTA-11985?focusedCommentId=193071&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-193071 seems related to the issue you're dealing with now. Specifically, it may be possible to reactivate events to have the correct toggle state now that we have the new deactivated state.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need addressing before we merge this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we chatted offline, its resolved :)

subject.scheduled_events.first.switch_off! # passive state
subject.scheduled_events.last.cancel! # cancel state
subject.send(:cancel_reminders)
expect(subject.scheduled_events.none?(&:may_cancel?)).to be(true)
Copy link
Contributor

Choose a reason for hiding this comment

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

might be good to be a bit more specific here--asserting the actual data states you expect, or asserting that the number of events which may_cancel? changes before and after cancel_reminders. It's possible that an error in the definition of may_cancel? would cause this test to pass when it actually shouldn't. For instance, if none of the events may_cancel? in the initial conditions, cancel_reminders would essentially no-op and this assertion would still pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

diff --git a/spec/models/reviewer_report_spec.rb b/spec/models/reviewer_report_spec.rb
index d7f5a99e6b..2dc8747ab0 100644
--- a/spec/models/reviewer_report_spec.rb
+++ b/spec/models/reviewer_report_spec.rb
@@ -173,8 +173,9 @@ describe ReviewerReport do
       subject.set_due_datetime # makes 3 scheduled events with active state
       subject.scheduled_events.first.switch_off! # passive state
       subject.scheduled_events.last.cancel! # cancel state
-      subject.send(:cancel_reminders)
-      expect(subject.scheduled_events.none?(&:may_cancel?)).to be(true)
+      old_states = subject.scheduled_events.map(&:state)
+      new_states = old_states.map { |x| x == 'passive' ? 'deactivated' : 'canceled' }
+      expect { subject.send(:cancel_reminders) }.to change { subject.scheduled_events.reload.map(&:state) }.from(old_states).to(new_states)
     end
   end

@JackLaBarba JackLaBarba merged commit bbe3aa4 into master Dec 7, 2017
@JackLaBarba JackLaBarba deleted the bugs/APERTA-12001-cancel-passive-events-on-rr-submit branch December 7, 2017 17:23
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants