Locator feature
added marker image for publisher, showing div for address, and added functionality to close it when clicking 'X' image showing marker image in publisher renamed map-marker to locator fixed style for map marker image in publisher added locator.js to get user's location loading google maps api removed unecessary append and showing location next to publisher moved location address inside div and added image to close location styled div location address an image to close location removing location when clicking close image cleaned code cleaned code showing loader while location is being obtained, translated normal js to backbone structure, created locations db stuff, and removing location div when clicking 'share' refactored code; started to move code to backbone refactored js code; moving functionality to backbone structure created address function to make accessible address variable value refactored locator.js showing and removing location div from dom created location; it belongs_to status_message added location model and created association with status_message added hidden field for location address and added respective code on js files to retrieve it on ajax call saving location for status_message (post) removing location when sharing renamed locator backbone view to location, added template, showing location, and saving lat and lng prepared and added template to show location added location to post model in order to have it accessible in backbone retrieving location to show it in template removed console.log XD fixes when removing location cleanind location_address hidden field when location is removed more fixes; showing location when sharing saving location just when it exists created method to retrieve location address just when location was created fixed issue about showing 'Near from' message when there was not any location added style for location cleaned code renamed locator view retrieving lat and lng from locator.js saving lat and lng in location_coords saving lat and lng added style for input location_address removed location_address hidden field; the value will be taken directly from input with the location replaced div with location for input; the user will be able to edit the place avoiding submitting the form when pressing Enter key on new input for location added missed spec file for location model refactored location_view code refactored location_view code cleaned code added sinon library for testing added describes for new publisher's view functions created test for destroyLocation function added test for showLocation publisher view function created test for avoidEnter publisher view function removed unnecessary div Created first test for locations view, added more specs, added Sinon.js, and fixed issue with assets loading locator.js for tests moved location stuff to app/assets moved locator.js and sinon.js to app/assets fixed route for images included locator.js to assets fixed issue when post object is different than StatusMessage; also fixed issue with lat and lng loading Sinon for specs refactoring locator errorGettingposition and start replacing google maps stuff with OSM added OpenLayers JS, osmlocator, and added them into the main js changing the locator from Google to OSM instance changing lat and lng value in the backbone view removing google javascript tag in application layout adding jasmine to locator test and removed locator.js adding jasmine to locator test using OSM adding Jasmine test to OSM locator removed locator.js removed require locator and updated schema fixed js response; added location since we are using OSM Locator we don't need locator-spec test fixed spec for location view; we are not using google maps anymore changed description of osmlocator-spec fixed issue with status-message-location template fixed style for location_address textbox fixed tests for locator moved split function to model created test for location model removed puts added effect for location marker added translations for locator removed conflicting-unnecessary lines that were loading files for specs removed sinon library; using sinon-rails gem removed useless code removed puts; added Rails.logger.error added sinon.js file added specific version of sinon-rails gem improving validations sintax using openlayers-rails gem removed 'google API' text using sinon gem isolating LocationStream view refactored validation getting location when post is a Reshare refactored code fixed aligment for elements under location message improved styling for location message refactored begin-rescue block getting absolute root instead of just the root added address method to retrive address of location removed code from Post model; also added descriptinon why it was removed removed validation when retrieving address; with latest refactorizations we dont need them any more interpolated location; using file in locales fixed width for div of location moved Sinon gem into development and test group fixed method's description added missed indexes updated schema with locations table removed openlayers-rails gem preventing location to be saved if there are not coordinates fixed spec; wrong closing tag
This commit is contained in:
parent
3cd60c3061
commit
4aab8762fa
29 changed files with 347 additions and 12 deletions
3
Gemfile
3
Gemfile
|
|
@ -160,7 +160,7 @@ group :development do
|
|||
gem 'guard-rspec', '2.5.3'
|
||||
gem 'rb-fsevent', '0.9.3', :require => false
|
||||
gem 'rb-inotify', '0.9.0', :require => false
|
||||
|
||||
|
||||
# Preloading environment
|
||||
|
||||
gem 'guard-spork', '1.5.0'
|
||||
|
|
@ -197,4 +197,5 @@ group :development, :test do
|
|||
|
||||
# Jasmine (client side application tests (JS))
|
||||
gem 'jasmine', '1.3.2'
|
||||
gem 'sinon-rails', '1.4.2.1'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -211,7 +211,6 @@ GEM
|
|||
rails
|
||||
multi_json (1.7.2)
|
||||
multipart-post (1.2.0)
|
||||
mysql2 (0.3.11)
|
||||
nested_form (0.3.2)
|
||||
net-scp (1.1.0)
|
||||
net-ssh (>= 2.6.5)
|
||||
|
|
@ -241,6 +240,7 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
omniauth-oauth (~> 1.0)
|
||||
orm_adapter (0.4.0)
|
||||
pg (0.15.1)
|
||||
polyglot (0.3.3)
|
||||
pry (0.9.12)
|
||||
coderay (~> 1.0.5)
|
||||
|
|
@ -357,6 +357,8 @@ GEM
|
|||
rack (~> 1.3, >= 1.3.6)
|
||||
rack-protection (~> 1.2)
|
||||
tilt (~> 1.3, >= 1.3.3)
|
||||
sinon-rails (1.4.2.1)
|
||||
railties (>= 3.1)
|
||||
slim (1.3.8)
|
||||
temple (~> 0.6.3)
|
||||
tilt (~> 1.3.3)
|
||||
|
|
@ -441,12 +443,12 @@ DEPENDENCIES
|
|||
messagebus_ruby_api (= 1.0.3)
|
||||
mini_magick (= 3.5)
|
||||
mobile-fu (= 1.1.1)
|
||||
mysql2 (= 0.3.11)
|
||||
nokogiri (= 1.5.9)
|
||||
omniauth (= 1.1.4)
|
||||
omniauth-facebook (= 1.4.1)
|
||||
omniauth-tumblr (= 1.1)
|
||||
omniauth-twitter (= 0.0.16)
|
||||
pg (= 0.15.1)
|
||||
rack-cors (= 0.2.7)
|
||||
rack-google-analytics (= 0.11.0)
|
||||
rack-piwik (= 0.2.2)
|
||||
|
|
@ -470,6 +472,7 @@ DEPENDENCIES
|
|||
selenium-webdriver (= 2.32.1)
|
||||
sidekiq (= 2.11.1)
|
||||
sinatra (= 1.3.3)
|
||||
sinon-rails (= 1.4.2.1)
|
||||
slim (= 1.3.8)
|
||||
spork (= 1.0.0rc3)
|
||||
timecop (= 0.6.1)
|
||||
|
|
|
|||
BIN
app/assets/images/icons/marker.png
Normal file
BIN
app/assets/images/icons/marker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 969 B |
|
|
@ -7,7 +7,8 @@ app.views.Content = app.views.Base.extend({
|
|||
return _.extend(this.defaultPresenter(), {
|
||||
text : app.helpers.textFormatter(this.model.get("text"), this.model),
|
||||
largePhoto : this.largePhoto(),
|
||||
smallPhotos : this.smallPhotos()
|
||||
smallPhotos : this.smallPhotos(),
|
||||
location: this.location()
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -34,12 +35,16 @@ app.views.Content = app.views.Base.extend({
|
|||
$(evt.currentTarget).hide();
|
||||
},
|
||||
|
||||
location: function(){
|
||||
var address = this.model.get('address')? this.model.get('address') : '';
|
||||
return address;
|
||||
},
|
||||
|
||||
collapseOversized : function() {
|
||||
var collHeight = 200
|
||||
, elem = this.$(".collapsible")
|
||||
, oembed = elem.find(".oembed")
|
||||
, addHeight = 0;
|
||||
|
||||
if($.trim(oembed.html()) != "") {
|
||||
addHeight = oembed.height();
|
||||
}
|
||||
|
|
@ -100,4 +105,4 @@ app.views.OEmbed = app.views.Base.extend({
|
|||
insertHTML.attr("src", insertHTML.attr("src") + paramSeparator + "autoplay=1");
|
||||
this.$el.html(insertHTML);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
|||
3
app/assets/javascripts/app/views/location_stream.js
Normal file
3
app/assets/javascripts/app/views/location_stream.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
app.views.LocationStream = app.views.Content.extend({
|
||||
templateName: "status-message-location"
|
||||
});
|
||||
25
app/assets/javascripts/app/views/location_view.js
Normal file
25
app/assets/javascripts/app/views/location_view.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
app.views.Location = Backbone.View.extend({
|
||||
|
||||
el: "#location",
|
||||
|
||||
initialize: function(){
|
||||
this.render();
|
||||
this.getLocation();
|
||||
},
|
||||
|
||||
render: function(){
|
||||
$(this.el).append('<img alt="delete location" src="/assets/ajax-loader.gif">');
|
||||
},
|
||||
|
||||
getLocation: function(e){
|
||||
element = this.el;
|
||||
|
||||
locator = new OSM.Locator();
|
||||
locator.getAddress(function(address, latlng){
|
||||
$(element).html('<input id="location_address" value="' + address + '"/>');
|
||||
$('#location_coords').val(latlng.latitude + "," + latlng.longitude);
|
||||
$(element).append('<a id="hide_location"><img alt="delete location" src="/assets/deletelabel.png"></a>');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -23,7 +23,10 @@ app.views.Publisher = Backbone.View.extend(_.extend(
|
|||
"click .post_preview_button" : "createPostPreview",
|
||||
"click .service_icon": "toggleService",
|
||||
"textchange #status_message_fake_text": "handleTextchange",
|
||||
"click .dropdown .dropdown_list li": "toggleAspect"
|
||||
"click .dropdown .dropdown_list li": "toggleAspect",
|
||||
"click #locator" : "showLocation",
|
||||
"click #hide_location" : "destroyLocation",
|
||||
"keypress #location_address" : "avoidEnter"
|
||||
},
|
||||
|
||||
tooltipSelector: ".service_icon",
|
||||
|
|
@ -79,7 +82,9 @@ app.views.Publisher = Backbone.View.extend(_.extend(
|
|||
},
|
||||
"aspect_ids" : serializedForm["aspect_ids[]"],
|
||||
"photos" : serializedForm["photos[]"],
|
||||
"services" : serializedForm["services[]"]
|
||||
"services" : serializedForm["services[]"],
|
||||
"location_address" : $("#location_address").val(),
|
||||
"location_coords" : serializedForm["location[coords]"]
|
||||
}, {
|
||||
url : "/status_messages",
|
||||
success : function() {
|
||||
|
|
@ -94,6 +99,30 @@ app.views.Publisher = Backbone.View.extend(_.extend(
|
|||
|
||||
// clear state
|
||||
this.clear();
|
||||
|
||||
// clear location
|
||||
this.destroyLocation();
|
||||
},
|
||||
|
||||
// creates the location
|
||||
showLocation: function(){
|
||||
if($('#location').length == 0){
|
||||
$('#publisher_textarea_wrapper').after('<div id="location"></div>');
|
||||
app.views.location = new app.views.Location();
|
||||
}
|
||||
},
|
||||
|
||||
// destroys the location
|
||||
destroyLocation: function(){
|
||||
if(app.views.location){
|
||||
app.views.location.remove();
|
||||
}
|
||||
},
|
||||
|
||||
// avoid submitting form when pressing Enter key
|
||||
avoidEnter: function(evt){
|
||||
if(evt.keyCode == 13)
|
||||
return false;
|
||||
},
|
||||
|
||||
createPostPreview : function(evt) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
".likes" : "likesInfoView",
|
||||
".comments" : "commentStreamView",
|
||||
".post-content" : "postContentView",
|
||||
".oembed" : "oEmbedView"
|
||||
".oembed" : "oEmbedView",
|
||||
".status-message-location" : "postLocationStreamView"
|
||||
},
|
||||
|
||||
events: {
|
||||
|
|
@ -47,6 +48,10 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
return new postClass({ model : this.model })
|
||||
},
|
||||
|
||||
postLocationStreamView : function(){
|
||||
return new app.views.LocationStream({ model : this.model});
|
||||
},
|
||||
|
||||
removeNsfwShield: function(evt){
|
||||
if(evt){ evt.preventDefault(); }
|
||||
this.model.set({nsfw : false})
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@
|
|||
//= require mobile
|
||||
//= require profile
|
||||
//= require people
|
||||
//= require photos
|
||||
//= require photos
|
||||
//= require sinon
|
||||
|
|
|
|||
|
|
@ -42,3 +42,4 @@
|
|||
//= require bootstrap-popover
|
||||
//= require bootstrap-dropdown
|
||||
//= require bootstrap-scrollspy-custom
|
||||
//= require osmlocator
|
||||
|
|
|
|||
23
app/assets/javascripts/osmlocator.js
Normal file
23
app/assets/javascripts/osmlocator.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
OSM = {};
|
||||
|
||||
OSM.Locator = function(){
|
||||
|
||||
var geolocalize = function(callback){
|
||||
navigator.geolocation.getCurrentPosition(function(position) {
|
||||
lat=position.coords.latitude;
|
||||
lon=position.coords.longitude;
|
||||
var display_name =$.getJSON("http://nominatim.openstreetmap.org/reverse?format=json&lat="+lat+"&lon="+lon+"&addressdetails=3", function(data){
|
||||
return callback(data.display_name, position.coords);
|
||||
});
|
||||
},errorGettingPosition);
|
||||
};
|
||||
|
||||
function errorGettingPosition(err) {
|
||||
$("#location").remove();
|
||||
};
|
||||
|
||||
return {
|
||||
getAddress: geolocalize
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -573,9 +573,22 @@ ul.as-selections
|
|||
& > .likes, & > .comments
|
||||
:margin-right 15px
|
||||
|
||||
.status-message-location
|
||||
.near-from
|
||||
:font-size smaller
|
||||
:color #aaa
|
||||
:width 100%
|
||||
:float left
|
||||
.address
|
||||
:font-size 11px
|
||||
:color #bbb
|
||||
|
||||
.stream_element .post-content .reshare
|
||||
:border-left 2px solid #ddd
|
||||
|
||||
.stream_element.loaded .media .bd .feedback
|
||||
:clear both
|
||||
|
||||
form.new_comment
|
||||
input
|
||||
:display none
|
||||
|
|
@ -697,6 +710,8 @@ form p.checkbox_select
|
|||
:height 100%
|
||||
:width 100%
|
||||
:cursor pointer
|
||||
img
|
||||
:margin-right 20px
|
||||
|
||||
#publisher
|
||||
:z-index 1
|
||||
|
|
@ -876,6 +891,8 @@ form p.checkbox_select
|
|||
:position absolute
|
||||
:bottom 0
|
||||
:right 35px
|
||||
:width 430px
|
||||
:left 5px
|
||||
:padding 0
|
||||
|
||||
li
|
||||
|
|
@ -3120,3 +3137,46 @@ body
|
|||
:bottom 3px solid #3f8fba !important
|
||||
:background
|
||||
:color #e8f7ff
|
||||
|
||||
#publisher-images
|
||||
#locator
|
||||
:bottom 1px !important
|
||||
:display inline-block
|
||||
:margin 0
|
||||
:position absolute !important
|
||||
:right 30px
|
||||
:cursor pointer
|
||||
img
|
||||
:padding-top 2px
|
||||
@include opacity(0.4)
|
||||
&:hover
|
||||
:color #666
|
||||
:cursor pointer
|
||||
img
|
||||
@include opacity(0.8)
|
||||
.btn
|
||||
:height 19px
|
||||
:width 19px
|
||||
|
||||
#location
|
||||
:border 1px solid #999
|
||||
:height 20px
|
||||
#location_address
|
||||
:border none
|
||||
:color #aaa
|
||||
:height 10px
|
||||
:width 430px
|
||||
:float left
|
||||
a#hide_location
|
||||
:position absolute
|
||||
:right 22px
|
||||
:filter alpha(opacity=30)
|
||||
:-moz-opacity 0.3
|
||||
:-khtml-opacity 0.3
|
||||
:opacity 0.3
|
||||
:z-index 5
|
||||
a#hide_location:hover
|
||||
@include opacity(0)
|
||||
:-khtml-opacity 1
|
||||
:opacity 1
|
||||
:cursor pointer
|
||||
|
|
|
|||
5
app/assets/templates/status-message-location_tpl.jst.hbs
Normal file
5
app/assets/templates/status-message-location_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{{#if location}}
|
||||
<div class='near-from'>
|
||||
{{ t "publisher.near_from" location=location}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
<div class="post-content"> </div>
|
||||
<div class="status-message-location"> </div>
|
||||
|
||||
<div class="feedback"> </div>
|
||||
<div class="likes"> </div>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class StatusMessagesController < ApplicationController
|
|||
services = [*params[:services]].compact
|
||||
|
||||
@status_message = current_user.build_post(:status_message, params[:status_message])
|
||||
@status_message.build_location(:address => params[:location_address], :coordinates => params[:location_coords]) if params[:location_address].present?
|
||||
@status_message.attach_photos_by_ids(params[:photos])
|
||||
|
||||
if @status_message.save
|
||||
|
|
|
|||
12
app/models/location.rb
Normal file
12
app/models/location.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
class Location < ActiveRecord::Base
|
||||
|
||||
before_validation :split_coords, :on => :create
|
||||
|
||||
attr_accessor :coordinates
|
||||
|
||||
belongs_to :status_message
|
||||
|
||||
def split_coords
|
||||
coordinates.present? ? (self.lat, self.lng = coordinates.split(',')) : false
|
||||
end
|
||||
end
|
||||
|
|
@ -66,6 +66,10 @@ class Post < ActiveRecord::Base
|
|||
def mentioned_people; []; end
|
||||
def photos; []; end
|
||||
|
||||
#prevents error when trying to access @post.address in a post different than Reshare and StatusMessage types;
|
||||
#check PostPresenter
|
||||
def address
|
||||
end
|
||||
|
||||
def self.excluding_blocks(user)
|
||||
people = user.blocks.map{|b| b.person_id}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ class Reshare < Post
|
|||
current
|
||||
end
|
||||
|
||||
def address
|
||||
absolute_root.location.try(:address)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def after_parse
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class StatusMessage < Post
|
|||
|
||||
has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid
|
||||
|
||||
has_one :location
|
||||
|
||||
# a StatusMessage is federated before its photos are so presence_of_content() fails erroneously if no text is present
|
||||
# therefore, we put the validation in a before_destory callback instead of a validation
|
||||
before_destroy :presence_of_content
|
||||
|
|
@ -164,6 +166,10 @@ class StatusMessage < Post
|
|||
self.oembed_url = urls.find{ |url| !TRUSTED_OEMBED_PROVIDERS.find(url).nil? }
|
||||
end
|
||||
|
||||
def address
|
||||
location.try(:address)
|
||||
end
|
||||
|
||||
protected
|
||||
def presence_of_content
|
||||
unless text_and_photos_blank?
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class PostPresenter
|
|||
:title => title,
|
||||
:next_post => next_post_path,
|
||||
:previous_post => previous_post_path,
|
||||
:address => @post.address,
|
||||
|
||||
:interactions => {
|
||||
:likes => [user_like].compact,
|
||||
|
|
|
|||
|
|
@ -26,8 +26,12 @@
|
|||
= status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}..."
|
||||
= status.hidden_field :text, :value => h(publisher_hidden_text), :class => 'clear_on_submit'
|
||||
|
||||
#file-upload{:title => t('.upload_photos')}
|
||||
= image_tag 'icons/camera.png', :alt => t('.upload_photos').titleize
|
||||
#publisher-images
|
||||
#locator.btn{:title => t('.get_location')}
|
||||
= image_tag 'icons/marker.png', :alt => t('.get_location').titleize, :class => 'publisher_image'
|
||||
#file-upload.btn{:title => t('.upload_photos')}
|
||||
= image_tag 'icons/camera.png', :alt => t('.upload_photos').titleize, :class => 'publisher_image'
|
||||
= hidden_field :location, :coords
|
||||
|
||||
- if publisher_public
|
||||
= hidden_field_tag 'aspect_ids[]', "public"
|
||||
|
|
|
|||
|
|
@ -794,6 +794,7 @@ en:
|
|||
make_public: "make public"
|
||||
all: "all"
|
||||
upload_photos: "Upload photos"
|
||||
get_location: "Get your location"
|
||||
all_contacts: "all contacts"
|
||||
share_with: "share with"
|
||||
whats_on_your_mind: "What's on your mind?"
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ en:
|
|||
at_least_one_aspect: "You must publish to at least one aspect"
|
||||
limited: "Limited - your post will only be seen by people you are sharing with"
|
||||
public: "Public - your post will be visible to everyone and found by search engines"
|
||||
near_from: "Near from: <%= location %>"
|
||||
infinite_scroll:
|
||||
no_more: "No more posts."
|
||||
no_more_contacts: "No more contacts."
|
||||
|
|
|
|||
12
db/migrate/20120405170105_create_locations.rb
Normal file
12
db/migrate/20120405170105_create_locations.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
class CreateLocations < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :locations do |t|
|
||||
t.string :address
|
||||
t.string :lat
|
||||
t.string :lng
|
||||
t.integer :status_message_id
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -151,6 +151,15 @@ ActiveRecord::Schema.define(:version => 20130404211624) do
|
|||
add_index "likes", ["target_id", "author_id", "target_type"], :name => "index_likes_on_target_id_and_author_id_and_target_type", :unique => true
|
||||
add_index "likes", ["target_id"], :name => "index_likes_on_post_id"
|
||||
|
||||
create_table "locations", :force => true do |t|
|
||||
t.string "address"
|
||||
t.string "lat"
|
||||
t.string "lng"
|
||||
t.integer "status_message_id"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "mentions", :force => true do |t|
|
||||
t.integer "post_id", :null => false
|
||||
t.integer "person_id", :null => false
|
||||
|
|
|
|||
17
spec/javascripts/app/views/location_view_spec.js
Normal file
17
spec/javascripts/app/views/location_view_spec.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
describe("app.views.Location", function(){
|
||||
beforeEach(function(){
|
||||
OSM = {};
|
||||
OSM.Locator = function(){return { getAddress:function(){}}};
|
||||
|
||||
this.view = new app.views.Location();
|
||||
});
|
||||
|
||||
describe("When it gets instantiated", function(){
|
||||
it("creates #location_address", function(){
|
||||
|
||||
expect($("#location_address")).toBeTruthy();
|
||||
expect($("#location_coords")).toBeTruthy();
|
||||
expect($("#hide_location")).toBeTruthy();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
@ -292,4 +292,66 @@ describe("app.views.Publisher", function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
context("locator", function() {
|
||||
beforeEach(function() {
|
||||
// should be jasmine helper
|
||||
loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}});
|
||||
|
||||
spec.loadFixture("aspects_index");
|
||||
this.view = new app.views.Publisher();
|
||||
});
|
||||
|
||||
describe('#showLocation', function(){
|
||||
it("Show location", function(){
|
||||
|
||||
// inserts location to the DOM; it is the location's view element
|
||||
setFixtures('<div id="publisher_textarea_wrapper"></div>');
|
||||
|
||||
// creates a fake Locator
|
||||
OSM = {};
|
||||
OSM.Locator = function(){return { getAddress:function(){}}};
|
||||
|
||||
// validates there is not location
|
||||
expect($("#location").length).toBe(0);
|
||||
|
||||
// this should create a new location
|
||||
this.view.showLocation();
|
||||
|
||||
// validates there is one location created
|
||||
expect($("#location").length).toBe(1);
|
||||
})
|
||||
});
|
||||
|
||||
describe('#destroyLocation', function(){
|
||||
it("Destroy location if exists", function(){
|
||||
|
||||
// inserts location to the DOM; it is the location's view element
|
||||
setFixtures('<div id="location"></div>');
|
||||
|
||||
// creates a new Location view with the #location element
|
||||
app.views.Location = new Backbone.View({el:"#location"});
|
||||
|
||||
// creates the mock
|
||||
app.views.location = sinon.mock(app.views.Location).object;
|
||||
|
||||
// calls the destroy function and test the expected result
|
||||
this.view.destroyLocation();
|
||||
expect($("#location").length).toBe(0);
|
||||
})
|
||||
});
|
||||
|
||||
describe('#avoidEnter', function(){
|
||||
it("Avoid submitting the form when pressing enter", function(){
|
||||
// simulates the event object
|
||||
evt = {};
|
||||
evt.keyCode = 13;
|
||||
|
||||
// should return false in order to avoid the form submition
|
||||
expect(this.view.avoidEnter(evt)).toBeFalsy();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
24
spec/javascripts/osmlocator-spec.js
Normal file
24
spec/javascripts/osmlocator-spec.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
describe("Locator", function(){
|
||||
navigator.geolocation['getCurrentPosition'] = function(myCallback){
|
||||
lat = 1;
|
||||
lon = 2;
|
||||
position = { coords: { latitude: lat, longitude: lon} }
|
||||
return myCallback(position);
|
||||
};
|
||||
|
||||
$.getJSON = function(url, myCallback){
|
||||
if(url == "http://nominatim.openstreetmap.org/reverse?format=json&lat=1&lon=2&addressdetails=3")
|
||||
{
|
||||
return myCallback({ display_name: 'locator address' })
|
||||
}
|
||||
}
|
||||
|
||||
var osmlocator = new OSM.Locator();
|
||||
|
||||
it("should return address, latitude, and longitude using getAddress method", function(){
|
||||
osmlocator.getAddress(function(display_name, coordinates){
|
||||
expect(display_name, 'locator address')
|
||||
expect(coordinates, { latitude: 1, longitude: 2 })
|
||||
})
|
||||
});
|
||||
});
|
||||
15
spec/models/location_spec.rb
Normal file
15
spec/models/location_spec.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Location do
|
||||
describe 'before validation' do
|
||||
it 'should create new location when it has coordinates' do
|
||||
location = Location.new(coordinates:'1,2')
|
||||
location.save.should be true
|
||||
end
|
||||
|
||||
it 'should not create new location when it does not have coordinates' do
|
||||
location = Location.new()
|
||||
location.save.should be false
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue