i have a server installation of redmine, i have installed shady mode plugin with 3.4 version and it is working but now i have update to 4.1 and doesn't work. This plugin allow me to enable shady mode and stop sending notification.
I found the problem of plugin code, I found two files where in both it does the check to see if the mode is active by going to retrieve the user's properties, in one file the check actually works and the condition returns the correct value, in the other file (the one that decides if to actually send the email or not) this setting is always false (or null).
I guess with the new version of redmine the plugin in that piece of code can't find the variables.
this is the file that work hook.rb:
module RedmineShady
module Hook
class ViewListener < Redmine::Hook::ViewListener
# necessary for using content_tag in Listener
attr_accessor :output_buffer
# If shady, show message on the top
def view_layouts_base_html_head(context = {})
session = context[:controller].session
if User.current.pref[:shady]
style = 'margin: 0; padding: 10px; border-width: 0 0 2px; background-image: none'
content_tag :div, id: 'shady-bar', class: 'flash error', style: style do
concat link_to l(:button_cancel), { controller: 'shady', action: 'destroy' },
method: :delete, style: 'float: right'
concat l(:notice_shady_mode)
end
end
end
end
end
end
and this is the file that doesn't work: mail_interceptor.rb
module RedmineShady
class MailInterceptor
def self.delivering_email(message)
message.perform_deliveries = false if User.current.pref[:shady]
end
end
end
Why does User.current.pref[:shady] work in hook.rb but not in mail_interceptor.rb?
Between Redmine 3.4 and Redmine 4.1, the way how email notifications are send has changed significantly.
Specifically, Redmine now renders and sends notification mails in the background rather than waiting in the update request. Also, a unique mail is now rendered for each recipient. While rendering the mail, User.current will be set to the respective recipient (rather than the sending user as in Redmine 3.4).
As such, the plugin needs to be updated for Redmine 4.1 and likely needs a significant re-architecture due to those Redmine changes.
Related
Newbie engineer question here, but I've searched and can't find a solution.
Environment: Mac OS, Chrome, Capybara with Selenium Chrome-driver, Ruby with Rspec running the test.
Situation:
Testing a React app where the user logs in using a username and password, followed by clicking on a sidebar nav link that loads up....followed by other actions. Capybara continues to fail to find the sidebar nav link to click on. I believe the sidebar nav is its own React component and loads asynchronously
App & Test Behavior:
Sometimes Capybara finds the link element, clicks the link and the test passes. Other times it completely fails to find the element and fails the test.
Solutions I've tried:
Upping the default time for finder methods to continue to search to 15+ seconds(I've never noticed the app take more than 5 seconds on anything)
I only have used finder methods that SHOULD be repeat-searching for the default time for the element to appear (page.find, page.has_css?, etc)before attempting the .click action. What I have found is that after the login happens, and while the nav is loading, the test just seems to fail with element not found. The page.find does NOT seem to continue to search for 15 seconds before failing - instead, the login happens, then a second later I get a fail with element not found.
I have tried passing a wait into the find (example: page.find(some element, wait:15).click . This runs into the same problem as above where it doesn't seem to continue searching for 15 seconds for the element to appear and then click it.
What does seem to work is adding in sleeps before searching for an element (example: login, sleep(5), page.find(something).click).
Unfortunately I'm having this same problem with other elements all over in the app - for example a div may have a bunch of cards in it. When a new card is added it takes 2-3 seconds to show up in the list (probably due to sending out the card info to the database, and refreshing the cards on the page). If I try and page.find immediately after adding a card, the test will almost immediately fail with an element not found message. If I add the card, sleep(3), THEN try page.find, it will find it.
I can't just add sleep all over the place in the app, because its huge and it would slow down the tests immensely. I think I've tried all the typically suggested fixes for asynchronous loading. Any idea what is going on here and what I can do to fix it
editing to add some requested code.
I'm using capybara 3.2.
We are using a bit of a page object style framework so I"ll try and post the actual test with its methods in bold and helper methods nested in it.
Its getting caught in the before action of this particular feature on the final method to click on the sidebar. I'm a little limited on what I can show, but I think this will make sense....
The actual before action:
before do
**app.launch_app(app.url)**
# this instantiates an instance of the framework and helper methods and # goes to the app url
**app.login.full_login(app.username('Some User'), app.password)**
# def full_login(user, pass)
# enter_email(user)
# def enter_email(user)
# return if already_logged_in?
# def already_logged_in?
# page.has_css?("a[href*='/me']", wait: false)
# end
# fill_field('email', user)
# def fill_field(field, text)
# sleep 0.1
# page.find("input[type=#{field}]").send_keys text
# end
# click_button 'Log In'
# def click_button(text)
# page.click_on text
# end
# end
# login_using_second_auth(user, pass)
# def login_using_second_auth(user, pass)
# page.fill_in 'username', with: user
# page.fill_in 'password', with: pass
# click_button 'Sign In'
# end
# end
app.nav.click_sidebar_link('Admin Account', 'Admin')
# def click_sidebar_link(link, section)
# sleep(2)
# page.find('div[class^=app__wrapper] > div > div > div', text:
# section)
# .find('span[class^=nav-item]', text: link).click
# end
end
Sorry that looks so messy, but I think you guys can make sense of it.
The test is flaky so after running it a few times I can't get the exact error, but its usually element not found on the span with the text Admin
Recently we upgraded our selenium web driver from 2.47.1 to 2.48.0.
With this upgrade I need to add sleep for a few seconds in rspec to pass. Spec was working properly without sleep with the older version.
sleep(inspection_time=5) // why do I need this?
my_form_page.save_button.click
// some assertion here
Edit
I tried using implicit wait instead of sleep.But it's not working. Is there any specific reason behind it?
Capybara.current_session.driver.browser.manage.timeouts.implicit_wait = 50
Generally speaking, rspec selenium tests are known to be "flakey". Sometimes rspec tries to search for an element before it appears on page due to many reasons (ie: element appears upon ajax response).
Here's a tip that may help you solve this, if you will wrap your capybara finders inside of a within block, your tests will wait until it finds that within selector FIRST before trying to run the code inside of it.
This more-often-than-not will help solve a test running too fast on a page that takes a while to load and your button or selector or whatever isn't actually on the page yet (which is why it fails).
So take a look at these 2 examples and try the within method...
# spec/features/home_page_spec.rb
require "spec_helper"
describe "the home page", type: :feature do
context "form" do
# THIS MIGHT FAIL!!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
find("#submit_button").click
end
# THIS PROBABLY WILL PASS!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
within "form" do
find("#submit_button").click
end
end
end
end
I am following a sample located here in the samples folder on the official Shoes github repo. I saw that the programmer defined a class Book which inherited from Shoes. I have a relatively large program coming along with shoes that I'm porting for 3.x, and I wanted to split all of my different classes into smaller files to make it easier on me. I have a file like so
#this class essentially sets up user interface
class Interface < Shoes
def initialize
flow do
#shed = button "New"
#editbutton = button "Edit"
#employees = button "Employees"
#sdays = button "Special Days"
#makenote = button "Make Note"
#backbutton = button "Go Back"
end
end
end
My main file looks like so
$LOAD_PATH << "."
require 'loader' #all of these are other classes i have defined
require 'interface' #contains the interface class
require 'schutil'
Shoes.app title: "Baesler's Scheduling Application", width: 1024, height: 768, resizable: true do
Interface.new
end
First of all, in the sample I provided, the programmer never had to use a block with Shoes.app. I don't know how, but his class got initialized with shoes when it was ran. That was my original intention, but when I try that (the code above without ever calling Interface.init), nothing shows up in Shoes, but it does load. However, using the above code as-is, I get the following error:
NoMethodError: undefined method 'flow' for nil:NilClass
If it helps at all, I am using the Shoes 4 preview 3 gem and am running Windows 8.1 64 bit. What am I doing wrong? Is this a bug in the Shoes codebase, or am I doing this wrong? Any help would be greatly appreciated.
You are overwriting the initialize method which breaks the whole setup of shoes (it needs to get an app instance on which to call the flow method for instance).
You are also following a url sample without using any actual url calls.
A widget might suit your use case better.
Personally I rather resort to defining methods within an app and then calling those :)
What would be the simplest approach to streaming the contents of a file to the web page, as it gets updated.
I currently have a .txt file that is constantly updated while a script is running, and I want to display that on the page for the users as it is updated.
Is there a simple gem or technology out there to accomplish this? Or is there an excellent pure Ruby approach?
My first thought was to use some kind of AJAX request to return diffs of the file, but I feel that would be a bad approach.
I used Celluloid's Reel by Tony Arcieri to accomplish this.
I run this in the background (received a lot of help from Adam Dalton on this part):
my_reel.rb
require 'reel'
CONNECTIONS = []
Reel::Server.supervise("0.0.0.0", 5000) do |connection|
while request = connection.request
case request
when Reel::Request
puts "Client requested: #{request.method} #{request.url} #{request.body}"
CONNECTIONS.each do |c|
c << request.body
end
request.respond :ok, 'YES! YOU GOT IT!'
when Reel::WebSocket
puts "Client made a WebSocket request to: #{request.url}"
CONNECTIONS << request
break
end
end
end
sleep
Then I wrote a command line script to send post requests to the Reel server. Had a lot of help from Writing Ruby Scripts That Respect Pipelines by Jesse Storimer.
~/bin/serve_it_up
#!/usr/bin/env ruby
require 'httparty'
ARGF.each_line do |line|
output_line = line.chop
HTTParty.post 'http://localhost:5000', body: output_line
end
Then to make it work, my Rails application uses Sidekiq (bundle exec sidekiq), and runs a script in the background when a button is clicked, which sends the output to a file, output.txt. So I run a forced tail and pipe it's output to my command line script.
tail -f output.txt | serve_it_up
In my web app, I have some JavaScript (CoffeeScript in this case) that hooks up to the web socket and puts the output on the page:
connection = new WebSocket('ws://localhost:5000')
connection.onmessage = (event) ->
$('#prompt').append(event.data + '<br/>')
prompt = document.getElementById('prompt')
prompt.scrollTop = prompt.scrollHeight
So anytime that output.txt changes, it'll take the output from tail -f and put it in the web browser. I also style the #prompt div to have a limited height, and I keep it always scrolled to the bottom.
Here is the style for it:
#prompt {
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
height: 200px;
overflow: auto;
}
You could look into using something like Faye or the gem private_pub (it makes Faye channels private) which allows you to make use of web sockets or long polling to push new data to the client. There is a lot of documentation on the Github page and also a RailsCast.
In your app or script you could then publish to the server which will push the new data to all subscribed channels.
I have been trying to create beta invites that each existing user can send out and was hoping to be able to use a plugin called acts_as_inviteable http://github.com/brianjlandau/acts_as_inviteable
I was wondering if anyone had direct experience with it. When I checked the console, it appears to be creating the right queries, but no email or email related errors come up.
I am tempted to just use Ryan Bates' excellent tutorial on beta invites and write it up myself, but I'd love to have something working. We just can't seem to figure it out.
There's a number of problems you need to fix:
Add this line to one of your config blocks (either in environment.rb or each of the files in config/environment):
config.action_mailer.default_url_options = {:host => 'somewhere.com'}
In app/models/invitation.rb on line 3 you have call attr_accessible :recipient_email this will prevent you from mass assigning the sender. You should change it to this:
attr_accessible :recipient_email, :sender, :sender_id
Also invitations_controller.rb should look like this:
class InvitationsController < ApplicationController
before_filter :require_analyst
def new
#invitation = Invitation.new
end
def create
#invitation = Invitation.new(params[:invitation])
#invitation.sender = current_analyst
if #invitation.save
flash[:notice] = "Thank you, invitation sent."
redirect_to root_url
else
render :action => 'new'
end
end
end
You really can't send an invitation unless you're logged in (because you need a sender, which in this case is an current_analyst not #current_user), so the lines having different logic depending on being logged in or not has been removed.
Also, the email will be automatically sent by the Invitation model so calling Mailer.deliver_invitation(#invitation, signup_url(#invitation.token)) is unnecessary (and actually it would have to be AnalystInvitationMailer.deliver_invitation(#invitation))
You can see a full working patch here: http://gist.github.com/290911