Reset iOS app in calabash-ios - calabash

How to change code in hooks to reset (iOS) app at specific scenario ?
means only to those scenario where tags mention as #reset

https://github.com/cucumber/cucumber/wiki/Hooks#tagged-hooks
UPDATED for Calabash 0.17 and run-loop 2.0.2
This project contains an example of how to use Cucumber tags and Before hooks to re-install apps and clear application data on simulators and devices.
https://github.com/calabash/ios-smoke-test-app/
In particular, see these two files:
ideviceinstaller wrapper
support/01_launch.rb
I won't reproduce the entire 01_launch.rb example here, but here are the hooks:
Before("#no_relaunch") do
#no_relaunch = true
end
Before('#reset_app_btw_scenarios') do
if xamarin_test_cloud? || LaunchControl.target_is_simulator?
ENV['RESET_BETWEEN_SCENARIOS'] = '1'
else
LaunchControl.install_on_physical_device
end
end
Before('#reset_device_settings') do
if xamarin_test_cloud?
ENV['RESET_BETWEEN_SCENARIOS'] = '1'
elsif LaunchControl.target_is_simulator?
target = LaunchControl.target
instruments = RunLoop::Instruments.new
xcode = instruments.xcode
device = instruments.simulators.find do |sim|
sim.udid == target || sim.instruments_identifier(xcode) == target
end
RunLoop::CoreSimulator.erase(device)
else
LaunchControl.install_on_physical_device
end
end
Before do |scenario|
launcher = LaunchControl.launcher
options = {
#:uia_strategy => :host
#:uia_strategy => :shared_element
:uia_strategy => :preferences
}
relaunch = true
if #no_relaunch
begin
launcher.ping_app
attach_options = options.dup
attach_options[:timeout] = 1
launcher.attach(attach_options)
relaunch = launcher.device == nil
rescue => e
RunLoop.log_info2("Tag says: don't relaunch, but cannot attach to the app.")
RunLoop.log_info2("#{e.class}: #{e.message}")
RunLoop.log_info2("The app probably needs to be launched!")
end
end
if relaunch
launcher.relaunch(options)
launcher.calabash_notify(self)
end
ENV['RESET_BETWEEN_SCENARIOS'] = '0'
# Re-installing the app on a device does not clear the Keychain settings,
# so we must clear them manually.
if scenario.source_tag_names.include?('#reset_device_settings')
if xamarin_test_cloud? || LaunchControl.target_is_physical_device?
keychain_clear
end
end
end
The key is recognize the difference between testing on simulators and devices and testing on the Test Cloud and locally.
You can reset the application settings and content before every Scenario using the RESET_BETWEEN_SCENARIOS env variable.
$ RESET_BETWEEN_SCENARIOS=1 cucumber
You can also implement a backdoor method to reset your app to a good known state. This example is a bit wonky and out of date, but I have used it to great effect in the past - it really speeds up tests - briar-ios-example You can do all kinds of things with backdoors: log users in/out, reset databases, wipe user preferences, add/remove files from the sandbox.

Related

Grails Locale not set for Spock unit tests

In my Grails 2.2 application I make some calculations which requires Locale to be set correctly. Therefore I provide this configuration block in my application, as mentioned elsewhere.
grails-app/config/spring/resources.groovy:
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("da","DK")
java.util.Locale.setDefault(defaultLocale)
}
}
Now, as also suggested by other questions and answers, this works in my context for the running application but not for unit tests.
I made this snippet to verify (on a page in the application):
<h2>Locale settings</h2>
<p>The following properties relevant to Locale is configured:</p>
<pre>
LocaleContextHolder.locale: '${org.springframework.context.i18n.LocaleContextHolder.locale}'
java.util.Locale.getDefault(): '${java.util.Locale.getDefault()}'
RequestContextUtils.getLocale(request): '${org.springframework.web.servlet.support.RequestContextUtils.getLocale(request)}'
session['SessionLocaleResolver.LOCALE']: '${session['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE']}'
</pre>
which renders
Locale settings
The following properties relevant to Locale is configured:
LocaleContextHolder.locale: 'da_DK'
java.util.Locale.getDefault(): 'da_DK'
RequestContextUtils.getLocale(request): 'da_DK'
session['SessionLocaleResolver.LOCALE']: ''
But for unit testing it does not work
The problem occurs for my unit test (I need java.util.Calendar weeks to start on Mondays (default for da_DK, but the week starts on Sunday (default for en_* locales).
In this case I made two test cases:
In test/unit/DefaultLocaleSpec.groovy:
import grails.test.mixin.TestMixin
import grails.test.mixin.web.ControllerUnitTestMixin
import org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest
import org.springframework.web.servlet.support.RequestContextUtils
import spock.lang.Specification
#TestMixin(ControllerUnitTestMixin)
class DefaultLocaleSpec extends Specification {
// ---------------------------------
// Locale verification (affects java Calendar calculations)
// ---------------------------------
def "locale (request) should be set to Danish, so that week starts Monday"() {
given:
GrailsMockHttpServletRequest request = new GrailsMockHttpServletRequest()
when:
Locale result = RequestContextUtils.getLocale(request)
then:
result == new Locale("da", "DK")
}
def "locale (default) should be set to Danish, so that week starts Monday"() {
when:
Locale result = java.util.Locale.getDefault()
then:
result == new Locale("da", "DK")
}
The two tests fail with the following messages:
Condition not satisfied:
result == new Locale("da", "DK")
| | |
en | da_DK
false
at DefaultLocaleSpec.locale (request) should be set to Danish, so that week starts Monday(DefaultLocaleSpec.groovy:27)
Condition not satisfied:
result == new Locale("da", "DK")
| | |
en_US | da_DK
false
<Click to see difference>
at DefaultLocaleSpec.locale (default) should be set to Danish, so that week starts Monday(DefaultLocaleSpec.groovy:35)
One workaround I found was to add the following to the unit test file:
def setupSpec() {
java.util.Locale.setDefault(new Locale("da", "DK"))
}
I feel tempted to pick that as a solution, but then I may have to add it to all my unit test file to fix the locale. And it seems like repeated work. I prefer my code more DRY (don't repeat yourself).
Option to change my machine's default Locale.
This I like to avoid, since everything I have to do to modify my setup, my colleagues also have to learn. Less customization is better. The more I can put inside the application, the better for me, my colleagues and any maintainers of the code :)
Question
This pinpoints my actual problem: I want to set up correct (default) locale also for the unit testing environment. How to do that – in a DRY way?
I prefer to make one change in one file which globally affects my app.
Related questions
These related questions do not quite answer or solve my problem (but have related ideas)
SO: How can I force Grails to use only one language? – suggests all problems are solved by setting locale in resources.groovy but does not address unit testing
SO: Retrieve active locale in Grails application – suggestions to read and change locale and default locale (does not address unit testing)

Rails 4 and paperclip - Stop the :original style file upload to copy it from an S3 remote directory

I use Paperclip 4.0.2 and in my app to upload pictures.
So my Document model has an attached_file called attachment
The attachment has few styles, say :medium, :thumb, :facebook
In my model, I stop the styles processing, and I extracted it inside a background job.
class Document < ActiveRecord::Base
# stop paperclip styles generation
before_post_process
false
end
But the :original style file is still uploaded!
I would like to know if it's possible to stop this behavior and copy the file inside the :original/filename.jpg from a remote directory
My goal being to use a file that has been uploaded in a S3 /temp/ directory with jQuery File upload, and copy it to the directory where Paperclip needs it to generate the others styles.
Thank you in advance for your help!
New Answer:
paperclip attachments get uploaded in the flush_writes method which, for your purposes, is part of the Paperclip::Storage::S3 module. The line which is responsible for the uploading is:
s3_object(style).write(file, write_options)
So, by means of monkey_patch, you can change this to something like:
s3_object(style).write(file, write_options) unless style.to_s == "original" and #queued_for_write[:your_processed_style].present?
EDIT: this would be accomplished by creating the following file: config/initializers/decorators/paperclip.rb
Paperclip::Storage::S3.class_eval do
def flush_writes #:nodoc:
#queued_for_write.each do |style, file|
retries = 0
begin
log("saving #{path(style)}")
acl = #s3_permissions[style] || #s3_permissions[:default]
acl = acl.call(self, style) if acl.respond_to?(:call)
write_options = {
:content_type => file.content_type,
:acl => acl
}
# add storage class for this style if defined
storage_class = s3_storage_class(style)
write_options.merge!(:storage_class => storage_class) if storage_class
if #s3_server_side_encryption
write_options[:server_side_encryption] = #s3_server_side_encryption
end
style_specific_options = styles[style]
if style_specific_options
merge_s3_headers( style_specific_options[:s3_headers], #s3_headers, #s3_metadata) if style_specific_options[:s3_headers]
#s3_metadata.merge!(style_specific_options[:s3_metadata]) if style_specific_options[:s3_metadata]
end
write_options[:metadata] = #s3_metadata unless #s3_metadata.empty?
write_options.merge!(#s3_headers)
s3_object(style).write(file, write_options) unless style.to_s == "original" and #queued_for_write[:your_processed_style].present?
rescue AWS::S3::Errors::NoSuchBucket
create_bucket
retry
rescue AWS::S3::Errors::SlowDown
retries += 1
if retries <= 5
sleep((2 ** retries) * 0.5)
retry
else
raise
end
ensure
file.rewind
end
end
after_flush_writes # allows attachment to clean up temp files
#queued_for_write = {}
end
end
now the original does not get uploaded. You could then add some lines, like those of my origninal answer below, to your model if you wish to transfer the original to its appropriate final location if it was uploaded to s3 directly.
Original Answer:
perhaps something like this placed in your model executed with the after_create callback:
paperclip_file_path = "relative/final/destination/file.jpg"
s3.buckets[BUCKET_NAME].objects[paperclip_file_path].copy_from(relative/temp/location/file.jpg)
thanks to https://github.com/uberllama

How do I access sinatra settings in custom extension specs?

I have an email helper extension I have written for my application. I use settings I have defined on the application like so:
set :mailgun_options, JSON.parse(File.open('config/mailer.json').read)[ENV['RACK_ENV']]
which reads configuration settings from a json file into the global Sinatra settings.
I then have my email helper which references these settings to create connections and what not.
require 'sinatra/base'
require 'faraday'
module Sinatra
module EmailHelper
def connect opts={}
connection = Faraday.new(:url => settings.mailgun_options['mailgun_url']) do |faraday|
if settings.mailgun_options['test']
faraday.adapter :test do |stubs|
stubs.post(settings.mailgun_options['domain'] + '/messages') {[ 200, {}, 'success' ]}
end
else
faraday.request :url_encoded
faraday.adapter Faraday.default_adapter
end
end
connection.basic_auth('api', settings.mailgun_options['key'])
return connection
end
def send_email params={}
connect.post((settings.mailgun_options['domain'] + '/messages'), params)
end
def send_password_reset_email email
template = File.open( File.expand_path( '../../helpers/email_helper/templates/password_reset.erb', __FILE__ ), 'r' ).read
send_email({
:from => 'REscour <noreply#' + settings.mailgun_options['domain'] + '>',
:to => email,
:subject => 'REscour.com Password Reset',
:text => ERB.new(template).result(binding)
})
end
end
end
So, when I am trying to write my specs to test the "connect" method, I get the following error:
undefined local variable or method `settings' for #<Class:0x007faaf9c9bd18>
My spec code is as follows:
module Sinatra
describe EmailHelper
let(:dummy_class) { Class.new { extend EmailHelper } }
it 'should connect to mailgun\'s api' do
app.set :mailgun_options, ::JSON.parse(File.open('config/mailer.json').read)['test']
puts dummy_class.connect
end
end
end
I'm not sure how to interact with the global Sinatra settings from my specs to have the local "settings" variable be defined during execution of the helper code.
I could have the architecture of my application wrong here for all I know. Does anyone have any experience in writing Sinatra extensions using the global settings and write specs for them?
The spec you've written seems to want to be a unit test, because you've not run the extension the way it would be used in an app. In the specs, try something like:
describe "connect" do
let(:app) { Sinatra.new do
helpers Sinatra::EmailHelper
configure do
:mailgun_options, ::JSON.parse(File.open('config/mailer.json')
end
get "/" do
connect
end
end
}
# now write specs for the `connect` helper
end
Using an anonymous class (Sinatra.new do…) lets you quickly set up an app that's convenient for a small test, but there are other ways too.
In the extension, you need to add:
helpers EmailHelper
as per the example in the docs.

Image file extension randomly is missing in sitecore

I'm experiencing an strange behaviour in our production servers.
We have three servers and It seems sometimes MediaManager.GetMediaUrl doesn't return the file extension. First I thought one server might have different settings. I compared all the configs on the three servers and they are identical.
Surprisingly, I notice If I browse the same page from the same server I can replicate issue.
I checked the value of Media.RequestExtension and for all three is same as following
<setting name="Media.RequestExtension" value=""/>
I cannot replicate the issue on none of our environments( local,test, staging )
I added the metatag and hardcoded the server name and I set the Cacheable property of usercontrol to false and I'm sure it's not Caching issue.
var images = new List<string>();
var imageField1 = (Sitecore.Data.Fields.ImageField)Sitecore.Context.Item.Fields["og Image1"];
if (imageField1 != null && imageField1.MediaItem != null)
{
var image1Url = MediaManager.GetMediaUrl(imageField1.MediaItem);
images.Add(image1Url);
}
Has anyone experienced the same issue?
Even I have faced this issue of extension in media item urls.
Workaround for this issue would be to make use of IncludeExtension property of MediaUrlOptions object.
MediaUrlOptions mediaUrlOpts = new MediaUrlOptions();
mediaUrlOpts.IncludeExtension = false;
Response.Write(MediaManager.GetMediaUrl(item, mediaUrlOpts ));
If you want to always add extension to URL, then set IncludeExtension to true.

Location for Traffic tracking on an FW/1 site

I am currenting using FW/1 and tracking traffic via the following function call
this.wsTraffic.add(action =
{
SubSystem = getSubSystem(),
Section = getSection(),
Item = rc.slug != "" ? rc.slug : getItem()
},
isPost = (cgi.request_method == "POST" ? 1 : 0),
http_user_agent = cgi.http_user_agent,
Remote_addr = cgi.remote_addr,
http_referer = cgi.http_referer,
http_accept_language = cgi.http_accept_language,
url_vars = Duplicate(url)
);
Currently it is ran on setupRequest() in application.cfc. I have two subsystems: home and admin. home will always have it traffic tracked. Admin will never have its traffic tracked.
I am considering moving the function call to home/layouts/default.cfm because only the home subsystem is tracked. I don't want to move the traffic tracker there because this has nothing to do with layouts.
Where should traffic logging be done on an FW/1 site?
It would be done in setupRequest, (where you are currently doing it).
To avoid it occurring for the Admin subsystem, wrap it in a conditional check for getSubSystem() NEQ 'admin' before running it.
Alternatively, if you forsee adding multiple subsystems with different statuses, you could implement it instead by creating a TrackedSubsystems (or UntrackedSubsystems) item in Variables.Framework, with a list of subsystem names, then check for:
ListFind( Variables.Framework.TrackedSubSystems , getSubSystem() )