Merge branch 'master' into comments
* master: Display asciicast author and creation time Claiming asciicasts User#add_user_token Asciicast.assign_user User tokens for assigning asciicasts to users Better styles + pagination Conflicts: app/models/asciicast.rb db/schema.rb spec/factories/asciicasts.rb spec/factories/users.rb
This commit is contained in:
commit
c4f40322ed
1
Gemfile
1
Gemfile
@ -10,6 +10,7 @@ gem 'omniauth'
|
||||
gem 'omniauth-twitter'
|
||||
gem 'omniauth-github'
|
||||
gem 'bzip2-ruby'
|
||||
gem 'kaminari'
|
||||
|
||||
# Gems used only for assets and not required
|
||||
# in production environments by default.
|
||||
|
@ -98,6 +98,10 @@ GEM
|
||||
thor (~> 0.14)
|
||||
json (1.6.5)
|
||||
json_pure (1.6.5)
|
||||
kaminari (0.13.0)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
railties (>= 3.0.0)
|
||||
libnotify (0.7.2)
|
||||
linecache19 (0.5.12)
|
||||
ruby_core_source (>= 0.1.4)
|
||||
@ -221,6 +225,7 @@ DEPENDENCIES
|
||||
jasmine
|
||||
jasminerice
|
||||
jquery-rails
|
||||
kaminari
|
||||
libnotify
|
||||
mysql2
|
||||
omniauth
|
||||
|
@ -4,5 +4,6 @@
|
||||
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
||||
*= require_self
|
||||
*= require reset
|
||||
*= require main
|
||||
*= require_tree .
|
||||
*/
|
||||
|
@ -2,9 +2,31 @@
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||
|
||||
$color1: #00A0B0;
|
||||
$color2: #6A4A3C;
|
||||
$color3: #CC333F;
|
||||
$color4: #EB6841;
|
||||
$color5: #EDC951;
|
||||
|
||||
.asciicasts {
|
||||
list-style: none;
|
||||
|
||||
.asciicast-preview {
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
|
||||
a {
|
||||
color: $color1;
|
||||
}
|
||||
}
|
||||
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.asciicast {
|
||||
width: 100%;
|
||||
background-color: #222;
|
||||
// width: 100%;
|
||||
// background-color: #222;
|
||||
|
||||
.player {
|
||||
/* border: 1px solid #777;*/
|
||||
@ -12,7 +34,7 @@
|
||||
float: left;
|
||||
display: block;
|
||||
padding: 0px;
|
||||
margin: 0px 0px 30px 20px;
|
||||
// margin: 0px 0px 30px 20px;
|
||||
position: relative;
|
||||
|
||||
.terminal {
|
||||
@ -22,7 +44,7 @@
|
||||
font-family: 'Droid Sans Mono', Monospace;
|
||||
white-space: pre;
|
||||
background-color: black;
|
||||
line-height: 1.2em;
|
||||
// line-height: 1.2em;
|
||||
color: #ccc;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
@ -53,37 +75,39 @@
|
||||
bottom: 0px;
|
||||
height: 30px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
|
||||
-webkit-transition: opacity 0.3s ease-in-out;
|
||||
|
||||
.toggle {
|
||||
background-color: blue;
|
||||
background-color: $color1;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
|
||||
&.paused {
|
||||
background-color: orange;
|
||||
background-color: $color4;
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-color: black;
|
||||
background-color: $color2;
|
||||
width: 60%;
|
||||
height: 100%;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
// cursor: pointer;
|
||||
|
||||
.gutter {
|
||||
background-color: #333;
|
||||
background-color: $color5;
|
||||
width: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
background-color: green;
|
||||
background-color: $color3;
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
float: left;
|
||||
@ -635,14 +659,19 @@
|
||||
.bg254 { background-color: #e4e4e4 }
|
||||
.bg255 { background-color: #eeeeee }
|
||||
|
||||
.description {
|
||||
color: #666;
|
||||
font-family: arial, helvetica;
|
||||
font-size: 16px;
|
||||
margin: 20px;
|
||||
.meta {
|
||||
.avatar {
|
||||
width: 24px;
|
||||
padding: 1px;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.description p {
|
||||
margin-bottom: 20px;
|
||||
.description {
|
||||
color: #3e3e3e;
|
||||
font-family: arial, helvetica;
|
||||
font-size: 18px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
}
|
||||
|
@ -4,86 +4,109 @@
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
// color pallette: http://www.colourlovers.com/palette/580974/Adrift_in_Dreams
|
||||
|
||||
$color1: #00A0B0;
|
||||
$color2: #6A4A3C;
|
||||
$color3: #CC333F;
|
||||
$color4: #EB6841;
|
||||
$color5: #EDC951;
|
||||
|
||||
body {
|
||||
background-color: #E7E7DE;
|
||||
background-color: #f0f0f0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body, div, p {
|
||||
font-family: arial, helvetica;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 325A66 */
|
||||
/* DEA140 */
|
||||
/* A32B26 */
|
||||
/* 590D0B */
|
||||
header {
|
||||
background-color: $color5;
|
||||
height: 40px;
|
||||
|
||||
h1 {
|
||||
color: #3e3e3e;
|
||||
font-family: 'Trebuchet MS';
|
||||
font-size: 42px;
|
||||
padding: 15px 0;
|
||||
nav {
|
||||
height: 100%;
|
||||
|
||||
h1 {
|
||||
height: 100%;
|
||||
float: left;
|
||||
background-color: black;
|
||||
font-family: 'Trebuchet MS';
|
||||
font-size: 26px;
|
||||
padding-right: 10px;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
vertical-align: middle;
|
||||
margin: 6px 0 0 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
height: 100%;
|
||||
float: right;
|
||||
background-color: $color1;
|
||||
|
||||
li {
|
||||
color: #eee;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: $color2;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
// a.logout {
|
||||
// background-image: url(image-path("logout.png"));
|
||||
// background-repeat: no-repeat;
|
||||
// }
|
||||
|
||||
.flash {
|
||||
vertical-align: middle;
|
||||
padding: 10px 0 10px 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.flash#notice {
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.flash#alert {
|
||||
color: red;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #3e3e3e;
|
||||
font-family: 'Trebuchet MS';
|
||||
font-size: 26px;
|
||||
padding: 15px 15px 40px 15px;
|
||||
// color: #3e3e3e;
|
||||
color: $color3;
|
||||
font-family: monospace;
|
||||
font-size: 20px;
|
||||
padding: 15px 0px 30px 0px;
|
||||
}
|
||||
|
||||
#top {
|
||||
position: relative;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
#logo {
|
||||
display: block;
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#topnav {
|
||||
display: block;
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 11px;
|
||||
font-family: Verdana;
|
||||
}
|
||||
|
||||
#session-info {
|
||||
background-color: #172322;
|
||||
list-style: none;
|
||||
padding: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
|
||||
li {
|
||||
color: #eee;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
#all {
|
||||
margin: 0 auto;
|
||||
width: 980px;
|
||||
#content {
|
||||
width: 960px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: white;
|
||||
width: 980px;
|
||||
font-size: 11px;
|
||||
border-top-left-radius: 10px;
|
||||
font-size: 12px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
class AsciicastsController < ApplicationController
|
||||
PER_PAGE = 20
|
||||
|
||||
respond_to :html, :json
|
||||
|
||||
def index
|
||||
@asciicasts = Asciicast.order("created_at DESC")
|
||||
@asciicasts = Asciicast.order("created_at DESC").page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
|
21
app/controllers/user_tokens_controller.rb
Normal file
21
app/controllers/user_tokens_controller.rb
Normal file
@ -0,0 +1,21 @@
|
||||
class UserTokensController < ApplicationController
|
||||
# before_filter :ensure_authenticated!
|
||||
|
||||
def create
|
||||
ut = current_user.add_user_token(params[:user_token])
|
||||
|
||||
if ut.valid?
|
||||
claimed_num = Asciicast.assign_user(ut.token, current_user)
|
||||
|
||||
if claimed_num > 0
|
||||
notice = "Claimed #{claimed_num} asciicasts, yay!"
|
||||
else
|
||||
notice = "Authenticated successfully, yippie!"
|
||||
end
|
||||
|
||||
redirect_to root_path, :notice => notice
|
||||
else
|
||||
render :error
|
||||
end
|
||||
end
|
||||
end
|
@ -1,5 +1,25 @@
|
||||
module AsciicastsHelper
|
||||
|
||||
def asciicast_title(asciicast)
|
||||
if asciicast.title.present?
|
||||
asciicast.title
|
||||
elsif asciicast.command.present?
|
||||
"$ #{asciicast.command}"
|
||||
else
|
||||
"##{asciicast.id}"
|
||||
end
|
||||
end
|
||||
|
||||
def asciicast_author(asciicast)
|
||||
if asciicast.user
|
||||
link_to avatar_img(asciicast.user) + " #{asciicast.user.nickname}", '#'
|
||||
end
|
||||
end
|
||||
|
||||
def asciicast_time(asciicast)
|
||||
time_ago_in_words(asciicast.created_at) + " ago"
|
||||
end
|
||||
|
||||
def player_script(asciicast)
|
||||
return <<EOS.html_safe
|
||||
<script>
|
||||
|
@ -7,11 +7,22 @@ class Asciicast < ActiveRecord::Base
|
||||
validates :stdout, :stdout_timing, :presence => true
|
||||
validates :terminal_columns, :terminal_lines, :duration, :presence => true
|
||||
|
||||
belongs_to :user
|
||||
has_many :comments, :order => :created_at
|
||||
|
||||
before_create :assign_user, :unless => :user
|
||||
|
||||
attr_reader :description
|
||||
|
||||
def self.assign_user(user_token, user)
|
||||
where(:user_id => nil, :user_token => user_token).
|
||||
update_all(:user_id => user.id, :user_token => nil)
|
||||
end
|
||||
|
||||
def meta=(file)
|
||||
data = JSON.parse(file.tempfile.read)
|
||||
|
||||
self.user_token = data['user_token']
|
||||
self.duration = data['duration']
|
||||
self.recorded_at = data['recorded_at']
|
||||
self.title = data['title']
|
||||
@ -45,4 +56,13 @@ class Asciicast < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def assign_user
|
||||
if user_token.present?
|
||||
if ut = UserToken.find_by_token(user_token)
|
||||
self.user = ut.user
|
||||
self.user_token = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,6 +4,8 @@ class User < ActiveRecord::Base
|
||||
validate :uid, :presence => true
|
||||
validate :nickname, :presence => true
|
||||
|
||||
has_many :user_tokens
|
||||
|
||||
def self.create_with_omniauth(auth)
|
||||
create! do |user|
|
||||
user.provider = auth["provider"]
|
||||
@ -14,4 +16,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def add_user_token(token)
|
||||
user_tokens.find_or_create_by_token(token)
|
||||
end
|
||||
end
|
||||
|
5
app/models/user_token.rb
Normal file
5
app/models/user_token.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class UserToken < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
validates :user, :token, :presence => true
|
||||
end
|
6
app/views/asciicasts/_preview.html.erb
Normal file
6
app/views/asciicasts/_preview.html.erb
Normal file
@ -0,0 +1,6 @@
|
||||
<li class="asciicast-preview">
|
||||
<h3><%= link_to asciicast_title(asciicast), asciicast %></h3>
|
||||
<% if asciicast.description.present? %>
|
||||
<p class="description"><%= asciicast.description %></p>
|
||||
<% end %>
|
||||
</li>
|
@ -1,9 +1,7 @@
|
||||
<h2>Some title</h2>
|
||||
<h2>Recent asciicasts</h2>
|
||||
|
||||
<ul class="asciicasts">
|
||||
<% @asciicasts.each do |asciicast| %>
|
||||
<li class="asciicast">
|
||||
<a href="/<%= asciicast.id %>"><%= asciicast.id %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= render :partial => "asciicasts/preview", :collection => @asciicasts, :as => :asciicast %>
|
||||
</ul>
|
||||
|
||||
<%= paginate @asciicasts %>
|
||||
|
@ -1,16 +1,19 @@
|
||||
<h2>#<%= @asciicast.id %> <%= @asciicast.title %></h2>
|
||||
|
||||
<div class="asciicast">
|
||||
<div class="player">
|
||||
<%# <pre class="term"></pre> %>
|
||||
<%# <div class="hud">--------------========</div> %>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<h2><%= asciicast_title(@asciicast) %></h2>
|
||||
<p class="meta">
|
||||
<%= asciicast_author(@asciicast) %>
|
||||
<%= asciicast_time(@asciicast) %>
|
||||
</p>
|
||||
|
||||
<div class="description">
|
||||
<p>I’ve been doing some reflecting this week on how I can work smarter (instead of harder), and one of the things I came up with was adding a few more tools to my Vim repertoire. I spend more than half of my engineering time in Vim (the other half usually being in a web browser), so I figured that a few minutes here and there would eventually add up in a big way.</p>
|
||||
<p>But like anything else with Vim, there are always multiple ways of accomplishing the very same thing, so I make no guarantees that there aren’t simpler ways of getting this done — but I can say that this way gets the job done, and is pretty easy to get working on your own system.</p>
|
||||
<div class="wrapper">
|
||||
<div class="player"></div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div class="description">
|
||||
<p>I’ve been doing some reflecting this week on how I can work smarter (instead of harder), and one of the things I came up with was adding a few more tools to my Vim repertoire. I spend more than half of my engineering time in Vim (the other half usually being in a web browser), so I figured that a few minutes here and there would eventually add up in a big way.</p>
|
||||
<p>But like anything else with Vim, there are always multiple ways of accomplishing the very same thing, so I make no guarantees that there aren’t simpler ways of getting this done — but I can say that this way gets the job done, and is pretty easy to get working on your own system.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= player_script(@asciicast) %>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<% if current_user %>
|
||||
<li>
|
||||
<%= avatar_img current_user %>
|
||||
<%= link_to "Log out", logout_path %>
|
||||
<%= link_to "Log out", logout_path, :class => "logout" %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li><%= link_to "Log in", login_path %></li>
|
||||
|
@ -10,27 +10,26 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="all">
|
||||
<div id="top">
|
||||
<div id="logo">
|
||||
<h1>ascii.io</h1>
|
||||
</div>
|
||||
<div id="topnav">
|
||||
<%= render :partial => 'layouts/session_info' %>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<% if notice %>
|
||||
<p id="notice" ><%= notice %></p>
|
||||
<% elsif alert %>
|
||||
<p id="alert" ><%= alert %></p>
|
||||
<% end %>
|
||||
<header>
|
||||
<nav>
|
||||
<h1>
|
||||
<%= link_to "ascii.io", "/", :class => "home" %>
|
||||
</h1>
|
||||
<%= render :partial => 'layouts/session_info' %>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<%= yield %>
|
||||
<div id="content">
|
||||
<% if notice %>
|
||||
<p id="notice" class="flash"><%= notice %></p>
|
||||
<% elsif alert %>
|
||||
<p id="alert" class="flash"><%= alert %></p>
|
||||
<% end %>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<%= yield %>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
3
app/views/user_tokens/error.html.erb
Normal file
3
app/views/user_tokens/error.html.erb
Normal file
@ -0,0 +1,3 @@
|
||||
<h2>Oops.</h2>
|
||||
|
||||
<p>Seems like the token is incorrect. Please make sure you've pasted it correctly.</p>
|
@ -17,5 +17,7 @@ AsciiIo::Application.routes.draw do
|
||||
match "/login" => "sessions#new"
|
||||
match "/logout" => "sessions#destroy"
|
||||
|
||||
match "/connect/:user_token" => "user_tokens#create"
|
||||
|
||||
root :to => 'asciicasts#index'
|
||||
end
|
||||
|
7
db/migrate/20120304161025_add_user_token_to_asciicast.rb
Normal file
7
db/migrate/20120304161025_add_user_token_to_asciicast.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class AddUserTokenToAsciicast < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :asciicasts, :user_token, :string
|
||||
|
||||
add_index :asciicasts, :user_token
|
||||
end
|
||||
end
|
13
db/migrate/20120304162005_create_user_tokens.rb
Normal file
13
db/migrate/20120304162005_create_user_tokens.rb
Normal file
@ -0,0 +1,13 @@
|
||||
class CreateUserTokens < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :user_tokens do |t|
|
||||
t.integer :user_id, :null => false
|
||||
t.string :token, :null => false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :user_tokens, :user_id
|
||||
add_index :user_tokens, :token
|
||||
end
|
||||
end
|
18
db/schema.rb
18
db/schema.rb
@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120227230718) do
|
||||
ActiveRecord::Schema.define(:version => 20120304162005) do
|
||||
|
||||
create_table "asciicasts", :force => true do |t|
|
||||
t.integer "user_id"
|
||||
@ -24,17 +24,29 @@ ActiveRecord::Schema.define(:version => 20120227230718) do
|
||||
t.string "command"
|
||||
t.string "shell"
|
||||
t.string "uname"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "stdin"
|
||||
t.string "stdin_timing"
|
||||
t.string "stdout"
|
||||
t.string "stdout_timing"
|
||||
t.string "user_token"
|
||||
end
|
||||
|
||||
add_index "asciicasts", ["created_at"], :name => "index_asciicasts_on_created_at"
|
||||
add_index "asciicasts", ["recorded_at"], :name => "index_asciicasts_on_recorded_at"
|
||||
add_index "asciicasts", ["user_id"], :name => "index_asciicasts_on_user_id"
|
||||
add_index "asciicasts", ["user_token"], :name => "index_asciicasts_on_user_token"
|
||||
|
||||
create_table "user_tokens", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
t.string "token", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "user_tokens", ["token"], :name => "index_user_tokens_on_token"
|
||||
add_index "user_tokens", ["user_id"], :name => "index_user_tokens_on_user_id"
|
||||
|
||||
create_table "comments", :force => true do |t|
|
||||
t.text "body"
|
||||
|
49
spec/controllers/user_tokens_controller_spec.rb
Normal file
49
spec/controllers/user_tokens_controller_spec.rb
Normal file
@ -0,0 +1,49 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe UserTokensController do
|
||||
describe '#create' do
|
||||
let(:user) { Factory(:user) }
|
||||
let(:user_token) { Factory.build(:user_token, :user => nil) }
|
||||
|
||||
before do
|
||||
@controller.stub!(:current_user => user)
|
||||
user.stub!(:add_user_token => user_token)
|
||||
end
|
||||
|
||||
context 'when given token is valid' do
|
||||
before do
|
||||
user_token.stub!(:valid? => true)
|
||||
end
|
||||
|
||||
it 'calls Asciicast.assign_user' do
|
||||
Asciicast.should_receive(:assign_user).with(user_token.token, user).and_return(1)
|
||||
|
||||
post :create, :user_token => user_token.token
|
||||
end
|
||||
|
||||
it 'redirects to root_path' do
|
||||
post :create, :user_token => user_token.token
|
||||
|
||||
response.should redirect_to(root_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given token is invalid' do
|
||||
before do
|
||||
user_token.stub!(:valid? => false)
|
||||
end
|
||||
|
||||
it 'calls Asciicast.assign_user' do
|
||||
Asciicast.should_not_receive(:assign_user)
|
||||
|
||||
post :create, :user_token => user_token.token
|
||||
end
|
||||
|
||||
it 'renders :error' do
|
||||
post :create, :user_token => user_token.token
|
||||
|
||||
response.should render_template(:error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -3,17 +3,16 @@ include ActionDispatch::TestProcess
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :asciicast do
|
||||
user_id 1
|
||||
association :user
|
||||
title "bashing"
|
||||
duration 100
|
||||
recorded_at "2011-11-23 22:06:07"
|
||||
terminal_type "xterm"
|
||||
terminal_columns 80
|
||||
terminal_lines 25
|
||||
shell "/bin/bash"
|
||||
uname "uname"
|
||||
stdout { fixture_file_upload("spec/fixtures/stdout", "application/octet-stream") }
|
||||
stdout_timing { fixture_file_upload("spec/fixtures/stdout", "application/octet-stream") }
|
||||
title "MyString"
|
||||
duration 1
|
||||
recorded_at "2011-11-23 22:06:07"
|
||||
terminal_type "MyString"
|
||||
terminal_columns 1
|
||||
terminal_lines 1
|
||||
command "MyString"
|
||||
shell "MyString"
|
||||
uname "MyString"
|
||||
end
|
||||
end
|
||||
|
8
spec/factories/user_tokens.rb
Normal file
8
spec/factories/user_tokens.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# Read about factories at http://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :user_token do
|
||||
association :user
|
||||
sequence(:token) { |n| "2b4b4e02-6613-11e1-9be5-#{Kernel.format('%012i', n)}" }
|
||||
end
|
||||
end
|
14
spec/fixtures/asciicasts/1/meta.json
vendored
Normal file
14
spec/fixtures/asciicasts/1/meta.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"command": null,
|
||||
"duration": 5.914434194564819,
|
||||
"recorded_at": "Sun, 04 Mar 2012 16:43:52 +0000",
|
||||
"shell": "/bin/zsh",
|
||||
"term": {
|
||||
"columns": 89,
|
||||
"lines": 27,
|
||||
"type": "rxvt-unicode-256color"
|
||||
},
|
||||
"title": null,
|
||||
"uname": "Linux 3.2.6-3.fc16.x86_64 #1 SMP Mon Feb 13 20:35:42 UTC 2012 x86_64",
|
||||
"user_token": "2b4b4e02-6613-11e1-9be5-00215c6bbb11"
|
||||
}
|
BIN
spec/fixtures/asciicasts/1/stdout
vendored
Normal file
BIN
spec/fixtures/asciicasts/1/stdout
vendored
Normal file
Binary file not shown.
BIN
spec/fixtures/asciicasts/1/stdout.time
vendored
Normal file
BIN
spec/fixtures/asciicasts/1/stdout.time
vendored
Normal file
Binary file not shown.
@ -1,5 +1,70 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Asciicast do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
it "has valid factory" do
|
||||
Factory.build(:asciicast).should be_valid
|
||||
end
|
||||
|
||||
describe '.assign_user' do
|
||||
let(:user) { Factory(:user) }
|
||||
let(:token) { 'token' }
|
||||
let!(:asciicast) { Factory(:asciicast, :user => nil, :user_token => token) }
|
||||
|
||||
subject { Asciicast.assign_user(token, user) }
|
||||
|
||||
it 'returns number of updated records' do
|
||||
subject.should == 1
|
||||
end
|
||||
|
||||
it 'assigns user to matching asciicasts' do
|
||||
subject
|
||||
asciicast.reload.user.should == user
|
||||
end
|
||||
end
|
||||
|
||||
describe '#save' do
|
||||
let(:asciicast) { Factory.build(:asciicast, :user => user) }
|
||||
|
||||
context 'when no user given' do
|
||||
let(:user) { nil }
|
||||
|
||||
it 'calls #assign_user' do
|
||||
asciicast.should_receive(:assign_user)
|
||||
asciicast.save
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user given' do
|
||||
let(:user) { Factory.build(:user) }
|
||||
|
||||
it "doesn't call #assign_user" do
|
||||
asciicast.should_not_receive(:assign_user)
|
||||
asciicast.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assign_user' do
|
||||
let(:user) { Factory(:user) }
|
||||
let(:asciicast) { Factory(:asciicast, :user => nil, :user_token => user_token) }
|
||||
|
||||
context 'when user exists with given token' do
|
||||
let(:user_token) { Factory(:user_token, :user => user).token }
|
||||
|
||||
it 'assigns user and resets user_token' do
|
||||
asciicast.assign_user
|
||||
asciicast.user.should == user
|
||||
asciicast.user_token.should be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is no user with given token' do
|
||||
let(:user_token) { 'some-foo-bar' }
|
||||
|
||||
it 'assigns user' do
|
||||
asciicast.assign_user
|
||||
asciicast.user.should be(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -47,4 +47,28 @@ describe User do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add_user_token' do
|
||||
before { user.save }
|
||||
|
||||
context "when user doesn't have given token" do
|
||||
let(:token) { Factory.attributes_for(:user_token)[:token] }
|
||||
|
||||
it 'returns created UserToken' do
|
||||
ut = user.add_user_token(token)
|
||||
ut.should be_kind_of(UserToken)
|
||||
ut.id.should_not be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context "when user doesn't have given token" do
|
||||
let(:existing_token) { Factory(:user_token, :user => user) }
|
||||
let(:token) { existing_token.token }
|
||||
|
||||
it 'returns existing UserToken' do
|
||||
ut = user.add_user_token(token)
|
||||
ut.should == existing_token
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
7
spec/models/user_token_spec.rb
Normal file
7
spec/models/user_token_spec.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe UserToken do
|
||||
it "has valid factory" do
|
||||
Factory.build(:user_token).should be_valid
|
||||
end
|
||||
end
|
11
spec/routing/connect_spec.rb
Normal file
11
spec/routing/connect_spec.rb
Normal file
@ -0,0 +1,11 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'connect routing' do
|
||||
it 'routes /connect/:user_token to user_tokens#create for user_token' do
|
||||
{ :get => '/connect/jolka-misio' }.should route_to(
|
||||
:controller => 'user_tokens',
|
||||
:action => 'create',
|
||||
:user_token => 'jolka-misio'
|
||||
)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user