Compare commits
6 commits
6d343989de
...
470c805880
Author | SHA1 | Date | |
---|---|---|---|
470c805880 | |||
b84942d77c | |||
e8db9cf729 | |||
0be9dee6fc | |||
27f21ab775 | |||
cc2d2906e4 |
18 changed files with 557 additions and 248 deletions
|
@ -27,6 +27,8 @@
|
||||||
// we partially override `config/database.yml` to connect to `db`!
|
// we partially override `config/database.yml` to connect to `db`!
|
||||||
"DATABASE_URL_PRIMARY_DEV": "mysql2://db",
|
"DATABASE_URL_PRIMARY_DEV": "mysql2://db",
|
||||||
"DATABASE_URL_OPENNEO_ID_DEV": "mysql2://db",
|
"DATABASE_URL_OPENNEO_ID_DEV": "mysql2://db",
|
||||||
|
"DATABASE_URL_PRIMARY_TEST": "mysql2://db",
|
||||||
|
"DATABASE_URL_OPENNEO_ID_TEST": "mysql2://db",
|
||||||
|
|
||||||
// HACK: Out of the box, this dev container doesn't allow installation to
|
// HACK: Out of the box, this dev container doesn't allow installation to
|
||||||
// the default GEM_HOME, because of a weird thing going on with RVM.
|
// the default GEM_HOME, because of a weird thing going on with RVM.
|
||||||
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"editor.rulers": [80]
|
|
||||||
}
|
|
5
Gemfile
5
Gemfile
|
@ -79,3 +79,8 @@ gem "stackprof", "~> 0.2.25"
|
||||||
# For monitoring errors in production.
|
# For monitoring errors in production.
|
||||||
gem "sentry-ruby", "~> 5.12"
|
gem "sentry-ruby", "~> 5.12"
|
||||||
gem "sentry-rails", "~> 5.12"
|
gem "sentry-rails", "~> 5.12"
|
||||||
|
|
||||||
|
# For automated testing.
|
||||||
|
group :test do
|
||||||
|
gem 'sqlite3', '~> 1.7'
|
||||||
|
end
|
||||||
|
|
|
@ -297,6 +297,8 @@ GEM
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
|
sqlite3 (1.7.0)
|
||||||
|
mini_portile2 (~> 2.8.0)
|
||||||
stackprof (0.2.25)
|
stackprof (0.2.25)
|
||||||
stringio (3.0.8)
|
stringio (3.0.8)
|
||||||
temple (0.8.2)
|
temple (0.8.2)
|
||||||
|
@ -359,6 +361,7 @@ DEPENDENCIES
|
||||||
sentry-rails (~> 5.12)
|
sentry-rails (~> 5.12)
|
||||||
sentry-ruby (~> 5.12)
|
sentry-ruby (~> 5.12)
|
||||||
sprockets (~> 4.2)
|
sprockets (~> 4.2)
|
||||||
|
sqlite3 (~> 1.7)
|
||||||
stackprof (~> 0.2.25)
|
stackprof (~> 0.2.25)
|
||||||
terser (~> 1.1, >= 1.1.17)
|
terser (~> 1.1, >= 1.1.17)
|
||||||
thread-local (~> 1.1)
|
thread-local (~> 1.1)
|
||||||
|
|
|
@ -1,80 +1,51 @@
|
||||||
@import "../partials/clean/constants"
|
@import "../partials/clean/constants"
|
||||||
@import "../partials/clean/mixins"
|
@import "../partials/clean/mixins"
|
||||||
|
|
||||||
=grayscale
|
|
||||||
// http://www.karlhorky.com/2012/06/cross-browser-image-grayscale-with-css.html
|
|
||||||
filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale")
|
|
||||||
filter: gray
|
|
||||||
|
|
||||||
// Cheap hack: https://github.com/chriseppstein/compass/issues/811
|
|
||||||
$percent: 100%
|
|
||||||
-webkit-filter: unquote('grayscale(#{$percent})')
|
|
||||||
|
|
||||||
body.items-show
|
body.items-show
|
||||||
#item-header
|
#item-header
|
||||||
border-bottom: 1px solid $module-border-color
|
border-bottom: 1px solid $module-border-color
|
||||||
display: block
|
|
||||||
margin-bottom: 1em
|
margin-bottom: 1em
|
||||||
padding: 1em 0
|
padding: 1em 0
|
||||||
|
|
||||||
div, img
|
display: grid
|
||||||
+inline-block
|
grid-template-areas: "img gap1" "img name" "img links" "img gap2"
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
column-gap: 1em
|
||||||
|
row-gap: .5em
|
||||||
|
|
||||||
|
#item-thumbnail
|
||||||
|
grid-area: img
|
||||||
|
|
||||||
|
border: 1px solid $module-border-color
|
||||||
|
height: 80px
|
||||||
|
width: 80px
|
||||||
|
|
||||||
|
#item-name
|
||||||
|
grid-area: name
|
||||||
|
|
||||||
div
|
|
||||||
text-align: left
|
text-align: left
|
||||||
|
line-height: 100%
|
||||||
|
|
||||||
|
#item-links
|
||||||
|
grid-area: links
|
||||||
|
|
||||||
|
text-align: left
|
||||||
a
|
a
|
||||||
font-size: 75%
|
font-size: 75%
|
||||||
margin-left: 1em
|
margin-left: 1em
|
||||||
|
|
||||||
#item-thumbnail
|
|
||||||
border: 1px solid $module-border-color
|
|
||||||
height: 80px
|
|
||||||
margin-right: .5em
|
|
||||||
width: 80px
|
|
||||||
|
|
||||||
#item-name
|
#item-name
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
|
||||||
#item-preview
|
#item-info-section
|
||||||
+clearfix
|
display: grid
|
||||||
|
|
||||||
> div, > ul
|
grid-template-areas: "info form"
|
||||||
float: left
|
grid-template-columns: 1fr auto
|
||||||
|
|
||||||
#item-preview-species
|
#item-info
|
||||||
display: block
|
grid-area: info
|
||||||
width: 400px
|
|
||||||
|
|
||||||
.pet-type, img
|
|
||||||
height: 50px
|
|
||||||
width: 50px
|
|
||||||
|
|
||||||
.pet-type
|
|
||||||
+inline-block
|
|
||||||
&.current
|
|
||||||
background: $module-bg-color
|
|
||||||
outline: 1px solid $module-border-color
|
|
||||||
&.deactivated
|
|
||||||
img
|
|
||||||
+grayscale
|
|
||||||
+opacity(0.5)
|
|
||||||
&.current
|
|
||||||
background: transparent
|
|
||||||
outline-color: $error_border_color
|
|
||||||
|
|
||||||
ul, li
|
|
||||||
display: inline
|
|
||||||
|
|
||||||
#item-preview-error
|
|
||||||
display: none
|
|
||||||
padding: 20px 10px 0
|
|
||||||
width: 380px
|
|
||||||
|
|
||||||
#item-preview-swf
|
|
||||||
height: 300px
|
|
||||||
overflow: hidden
|
|
||||||
width: 300px
|
|
||||||
|
|
||||||
#item-zones
|
#item-zones
|
||||||
font:
|
font:
|
||||||
|
@ -88,6 +59,52 @@ body.items-show
|
||||||
&:first-child
|
&:first-child
|
||||||
margin-right: 1em
|
margin-right: 1em
|
||||||
|
|
||||||
|
#your-items-form
|
||||||
|
grid-area: form
|
||||||
|
|
||||||
|
border: 1px solid $module-border-color
|
||||||
|
font-size: 85%
|
||||||
|
margin-bottom: 3em
|
||||||
|
margin-left: 1em
|
||||||
|
padding: 1em
|
||||||
|
width: 30em
|
||||||
|
|
||||||
|
// compete with #trade-hangers
|
||||||
|
position: relative
|
||||||
|
z-index: 2
|
||||||
|
|
||||||
|
h3
|
||||||
|
font-size: 150%
|
||||||
|
font-weight: bold
|
||||||
|
margin-bottom: .25em
|
||||||
|
|
||||||
|
#closet-hangers-ownership-groups
|
||||||
|
+clearfix
|
||||||
|
margin-bottom: .5em
|
||||||
|
|
||||||
|
div
|
||||||
|
float: left
|
||||||
|
margin: 0 5%
|
||||||
|
text-align: left
|
||||||
|
width: 40%
|
||||||
|
|
||||||
|
li
|
||||||
|
list-style: none
|
||||||
|
word-wrap: break-word
|
||||||
|
|
||||||
|
label.unlisted
|
||||||
|
font-style: italic
|
||||||
|
|
||||||
|
form
|
||||||
|
padding: .5em 0
|
||||||
|
|
||||||
|
select
|
||||||
|
width: 9em
|
||||||
|
|
||||||
|
input[type=number]
|
||||||
|
margin-right: .5em
|
||||||
|
width: 3em
|
||||||
|
|
||||||
#trade-hangers
|
#trade-hangers
|
||||||
font-size: 85%
|
font-size: 85%
|
||||||
margin-bottom: 3em
|
margin-bottom: 3em
|
||||||
|
@ -149,64 +166,10 @@ body.items-show
|
||||||
li:last-child::after
|
li:last-child::after
|
||||||
content: "."
|
content: "."
|
||||||
|
|
||||||
#item-preview-header
|
|
||||||
clear: both
|
|
||||||
|
|
||||||
h3, a
|
|
||||||
+inline-block
|
|
||||||
a
|
|
||||||
font-size: 85%
|
|
||||||
margin: -1.5em 0 0 1em
|
|
||||||
|
|
||||||
.nc-icon
|
.nc-icon
|
||||||
height: 16px
|
height: 16px
|
||||||
width: 16px
|
width: 16px
|
||||||
|
|
||||||
#closet-hangers
|
|
||||||
border: 1px solid $module-border-color
|
|
||||||
float: right
|
|
||||||
font-size: 85%
|
|
||||||
margin-bottom: 3em
|
|
||||||
margin-left: 1em
|
|
||||||
padding: 1em
|
|
||||||
width: 30em
|
|
||||||
|
|
||||||
// compete with #trade-hangers
|
|
||||||
position: relative
|
|
||||||
z-index: 2
|
|
||||||
|
|
||||||
h3
|
|
||||||
font-size: 150%
|
|
||||||
font-weight: bold
|
|
||||||
margin-bottom: .25em
|
|
||||||
|
|
||||||
#closet-hangers-ownership-groups
|
|
||||||
+clearfix
|
|
||||||
margin-bottom: .5em
|
|
||||||
|
|
||||||
div
|
|
||||||
float: left
|
|
||||||
margin: 0 5%
|
|
||||||
text-align: left
|
|
||||||
width: 40%
|
|
||||||
|
|
||||||
li
|
|
||||||
list-style: none
|
|
||||||
word-wrap: break-word
|
|
||||||
|
|
||||||
label.unlisted
|
|
||||||
font-style: italic
|
|
||||||
|
|
||||||
form
|
|
||||||
padding: .5em 0
|
|
||||||
|
|
||||||
select
|
|
||||||
width: 9em
|
|
||||||
|
|
||||||
input[type=number]
|
|
||||||
margin-right: .5em
|
|
||||||
width: 3em
|
|
||||||
|
|
||||||
&.js
|
&.js
|
||||||
#trade-hangers
|
#trade-hangers
|
||||||
p
|
p
|
||||||
|
|
|
@ -4,6 +4,7 @@ class ClosetHanger < ApplicationRecord
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
delegate :name, to: :item, prefix: true
|
delegate :name, to: :item, prefix: true
|
||||||
|
delegate :log_trade_activity, to: :user
|
||||||
|
|
||||||
validates :item_id, :uniqueness => {:scope => [:user_id, :owned, :list_id]}
|
validates :item_id, :uniqueness => {:scope => [:user_id, :owned, :list_id]}
|
||||||
validates :quantity, :numericality => {:greater_than => 0}
|
validates :quantity, :numericality => {:greater_than => 0}
|
||||||
|
@ -16,6 +17,32 @@ class ClosetHanger < ApplicationRecord
|
||||||
joins(:item => :translations).where(it[:locale].eq(I18n.locale)).
|
joins(:item => :translations).where(it[:locale].eq(I18n.locale)).
|
||||||
order(it[:name].asc)
|
order(it[:name].asc)
|
||||||
}
|
}
|
||||||
|
scope :trading, -> {
|
||||||
|
ch = arel_table
|
||||||
|
cl = ClosetList.arel_table
|
||||||
|
u = User.arel_table
|
||||||
|
joins(:user, :list).where(
|
||||||
|
# sigh… our default-lists continue to be a pain
|
||||||
|
(
|
||||||
|
ch[:list_id].not_eq(nil).and(cl[:visibility].gteq(
|
||||||
|
ClosetVisibility[:trading].id))
|
||||||
|
).or(
|
||||||
|
(
|
||||||
|
ch[:list_id].eq(nil).and(ch[:owned].eq(true))
|
||||||
|
).and(
|
||||||
|
u[:owned_closet_hangers_visibility].gteq(
|
||||||
|
ClosetVisibility[:trading].id)
|
||||||
|
)
|
||||||
|
).or(
|
||||||
|
(
|
||||||
|
ch[:list_id].eq(nil).and(ch[:owned].eq(false))
|
||||||
|
).and(
|
||||||
|
u[:wanted_closet_hangers_visibility].gteq(
|
||||||
|
ClosetVisibility[:trading].id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
scope :newest, -> { order(arel_table[:created_at].desc) }
|
scope :newest, -> { order(arel_table[:created_at].desc) }
|
||||||
scope :owned_before_wanted, -> { order(arel_table[:owned].desc) }
|
scope :owned_before_wanted, -> { order(arel_table[:owned].desc) }
|
||||||
scope :unlisted, -> { where(:list_id => nil) }
|
scope :unlisted, -> { where(:list_id => nil) }
|
||||||
|
@ -36,6 +63,9 @@ class ClosetHanger < ApplicationRecord
|
||||||
|
|
||||||
before_validation :merge_quantities, :set_owned_by_list
|
before_validation :merge_quantities, :set_owned_by_list
|
||||||
|
|
||||||
|
after_save :log_trade_activity, if: :trading?
|
||||||
|
after_destroy :log_trade_activity, if: :trading?
|
||||||
|
|
||||||
def possibly_null_closet_list
|
def possibly_null_closet_list
|
||||||
list || user.null_closet_list(owned)
|
list || user.null_closet_list(owned)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,10 +6,15 @@ class ClosetList < ApplicationRecord
|
||||||
validates :user, :presence => true
|
validates :user, :presence => true
|
||||||
validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"}
|
validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"}
|
||||||
|
|
||||||
|
delegate :log_trade_activity, to: :user
|
||||||
|
|
||||||
scope :alphabetical, -> { order(:name) }
|
scope :alphabetical, -> { order(:name) }
|
||||||
scope :publicly_visible, -> {
|
scope :publicly_visible, -> {
|
||||||
where(arel_table[:visibility].gteq(ClosetVisibility[:public].id))
|
where(arel_table[:visibility].gteq(ClosetVisibility[:public].id))
|
||||||
}
|
}
|
||||||
|
scope :trading, -> {
|
||||||
|
where(arel_table[:visibility].gteq(ClosetVisibility[:trading].id))
|
||||||
|
}
|
||||||
scope :visible_to, ->(user) {
|
scope :visible_to, ->(user) {
|
||||||
condition = arel_table[:visibility].gteq(ClosetVisibility[:public].id)
|
condition = arel_table[:visibility].gteq(ClosetVisibility[:public].id)
|
||||||
condition = condition.or(arel_table[:user_id].eq(user.id)) if user
|
condition = condition.or(arel_table[:user_id].eq(user.id)) if user
|
||||||
|
@ -17,6 +22,12 @@ class ClosetList < ApplicationRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
after_save :sync_hangers_owned!
|
after_save :sync_hangers_owned!
|
||||||
|
after_save :log_trade_activity, if: :trading?
|
||||||
|
after_destroy :log_trade_activity, if: :trading?
|
||||||
|
|
||||||
|
def trading?
|
||||||
|
visibility >= ClosetVisibility[:trading].id
|
||||||
|
end
|
||||||
|
|
||||||
def sync_hangers_owned!
|
def sync_hangers_owned!
|
||||||
if hangers_owned_changed?
|
if hangers_owned_changed?
|
||||||
|
|
|
@ -25,6 +25,12 @@ class User < ApplicationRecord
|
||||||
scope :top_contributors, -> { order('points DESC').where('points > 0') }
|
scope :top_contributors, -> { order('points DESC').where('points > 0') }
|
||||||
|
|
||||||
after_update :sync_name_with_auth_user!, if: :saved_change_to_name?
|
after_update :sync_name_with_auth_user!, if: :saved_change_to_name?
|
||||||
|
after_update :log_trade_activity, if: -> user {
|
||||||
|
(user.saved_change_to_owned_closet_hangers_visibility? &&
|
||||||
|
user.owned_closet_hangers_visibility >= ClosetVisibility[:trading].id) ||
|
||||||
|
(user.saved_change_to_wanted_closet_hangers_visibility? &&
|
||||||
|
user.wanted_closet_hangers_visibility >= ClosetVisibility[:trading].id)
|
||||||
|
}
|
||||||
|
|
||||||
def sync_name_with_auth_user!
|
def sync_name_with_auth_user!
|
||||||
auth_user.name = name
|
auth_user.name = name
|
||||||
|
@ -169,6 +175,10 @@ class User < ApplicationRecord
|
||||||
contact_neopets_connection.try(:neopets_username)
|
contact_neopets_connection.try(:neopets_username)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_trade_activity
|
||||||
|
touch(:last_trade_activity_at)
|
||||||
|
end
|
||||||
|
|
||||||
def self.points_required_to_pass_top_contributor(offset)
|
def self.points_required_to_pass_top_contributor(offset)
|
||||||
user = User.top_contributors.select(:points).limit(1).offset(offset).first
|
user = User.top_contributors.select(:points).limit(1).offset(offset).first
|
||||||
user ? user.points : 0
|
user ? user.points : 0
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
%header#item-header
|
%header#item-header
|
||||||
= image_tag @item.thumbnail_url, :id => 'item-thumbnail'
|
= image_tag @item.thumbnail_url, :id => 'item-thumbnail'
|
||||||
%div
|
|
||||||
%h2#item-name= @item.name
|
%h2#item-name= @item.name
|
||||||
|
%nav#item-links
|
||||||
= nc_icon_for(@item)
|
= nc_icon_for(@item)
|
||||||
- unless @item.rarity.blank?
|
- unless @item.rarity.blank?
|
||||||
== #{t '.rarity'}: #{@item.rarity_index} (#{@item.rarity})
|
== #{t '.rarity'}: #{@item.rarity_index} (#{@item.rarity})
|
||||||
|
@ -19,8 +19,33 @@
|
||||||
= link_to t('.resources.trading_post'), trading_post_url_for(@item)
|
= link_to t('.resources.trading_post'), trading_post_url_for(@item)
|
||||||
= link_to t('.resources.auction_genie'), auction_genie_url_for(@item)
|
= link_to t('.resources.auction_genie'), auction_genie_url_for(@item)
|
||||||
|
|
||||||
|
%section#item-info-section
|
||||||
|
#item-info
|
||||||
|
%p= @item.description
|
||||||
|
|
||||||
|
#item-zones
|
||||||
|
%p
|
||||||
|
%strong #{t '.zones.occupied_header'}:
|
||||||
|
= list_zones @occupied_zones, :uncertain_label
|
||||||
|
%p
|
||||||
|
%strong #{t '.zones.restricted_header'}:
|
||||||
|
- if @restricted_zones.empty?
|
||||||
|
= t '.zones.none'
|
||||||
|
- else
|
||||||
|
= list_zones @restricted_zones
|
||||||
|
|
||||||
|
#trade-hangers
|
||||||
|
- [true, false].each do |owned|
|
||||||
|
%p
|
||||||
|
%strong
|
||||||
|
= trading_closet_hangers_header(owned, @trading_closet_hangers_by_owned[owned].size)
|
||||||
|
= render_trading_closet_hangers(owned)
|
||||||
|
%span.toggle
|
||||||
|
%span.more= t '.trading_closet_hangers.show_more'
|
||||||
|
%span.less= t '.trading_closet_hangers.show_less'
|
||||||
|
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
#closet-hangers
|
#your-items-form
|
||||||
%h3
|
%h3
|
||||||
= t '.closet_hangers.header_html',
|
= t '.closet_hangers.header_html',
|
||||||
:user_items_link => link_to(t('your_items'),
|
:user_items_link => link_to(t('your_items'),
|
||||||
|
@ -50,29 +75,6 @@
|
||||||
t('.closet_hangers.quantity_label')
|
t('.closet_hangers.quantity_label')
|
||||||
= submit_tag t('.closet_hangers.submit')
|
= submit_tag t('.closet_hangers.submit')
|
||||||
|
|
||||||
%p= @item.description
|
|
||||||
|
|
||||||
#item-zones
|
|
||||||
%p
|
|
||||||
%strong #{t '.zones.occupied_header'}:
|
|
||||||
= list_zones @occupied_zones, :uncertain_label
|
|
||||||
%p
|
|
||||||
%strong #{t '.zones.restricted_header'}:
|
|
||||||
- if @restricted_zones.empty?
|
|
||||||
= t '.zones.none'
|
|
||||||
- else
|
|
||||||
= list_zones @restricted_zones
|
|
||||||
|
|
||||||
#trade-hangers
|
|
||||||
- [true, false].each do |owned|
|
|
||||||
%p
|
|
||||||
%strong
|
|
||||||
= trading_closet_hangers_header(owned, @trading_closet_hangers_by_owned[owned].size)
|
|
||||||
= render_trading_closet_hangers(owned)
|
|
||||||
%span.toggle
|
|
||||||
%span.more= t '.trading_closet_hangers.show_more'
|
|
||||||
%span.less= t '.trading_closet_hangers.show_less'
|
|
||||||
|
|
||||||
#outfit-preview-root{'data-item-id': @item.id}
|
#outfit-preview-root{'data-item-id': @item.id}
|
||||||
|
|
||||||
- unless @contributors_with_counts.empty?
|
- unless @contributors_with_counts.empty?
|
||||||
|
|
|
@ -24,6 +24,32 @@ development:
|
||||||
sql_mode: TRADITIONAL
|
sql_mode: TRADITIONAL
|
||||||
migrations_paths: db/openneo_id_migrate
|
migrations_paths: db/openneo_id_migrate
|
||||||
|
|
||||||
|
test:
|
||||||
|
primary:
|
||||||
|
# You can override these default settings with this environment variable,
|
||||||
|
# fully or partially. We do this in the .devcontainer setup!
|
||||||
|
url: <%= ENV['DATABASE_URL_PRIMARY_TEST'] %>
|
||||||
|
adapter: mysql2
|
||||||
|
database: openneo_impress_test
|
||||||
|
username: impress_dev
|
||||||
|
password: impress_dev
|
||||||
|
pool: 5
|
||||||
|
variables:
|
||||||
|
sql_mode: TRADITIONAL
|
||||||
|
|
||||||
|
openneo_id:
|
||||||
|
# You can override these default settings with this environment variable,
|
||||||
|
# fully or partially. We do this in the .devcontainer setup!
|
||||||
|
url: <%= ENV['DATABASE_URL_OPENNEO_ID_TEST'] %>
|
||||||
|
adapter: mysql2
|
||||||
|
database: openneo_id_test
|
||||||
|
username: impress_dev
|
||||||
|
password: impress_dev
|
||||||
|
pool: 2
|
||||||
|
variables:
|
||||||
|
sql_mode: TRADITIONAL
|
||||||
|
migrations_paths: db/openneo_id_migrate
|
||||||
|
|
||||||
production:
|
production:
|
||||||
primary:
|
primary:
|
||||||
url: <%= ENV['DATABASE_URL_PRIMARY'] %>
|
url: <%= ENV['DATABASE_URL_PRIMARY'] %>
|
||||||
|
|
|
@ -35,7 +35,7 @@ Rails.application.configure do
|
||||||
config.action_controller.allow_forgery_protection = false
|
config.action_controller.allow_forgery_protection = false
|
||||||
|
|
||||||
# Store uploaded files on the local file system in a temporary directory.
|
# Store uploaded files on the local file system in a temporary directory.
|
||||||
config.active_storage.service = :test
|
# config.active_storage.service = :test
|
||||||
|
|
||||||
config.action_mailer.perform_caching = false
|
config.action_mailer.perform_caching = false
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
# Make sure your secret_key_base is kept private
|
# Make sure your secret_key_base is kept private
|
||||||
# if you're sharing your code publicly.
|
# if you're sharing your code publicly.
|
||||||
if Rails.env.development?
|
if Rails.env.development? || Rails.env.test?
|
||||||
# In development, we use a hardcoded secret key, because it doesn't actually
|
# In development, we use a hardcoded secret key, because it doesn't actually
|
||||||
# need to be secret!
|
# need to be secret!
|
||||||
OpenneoImpressItems::Application.config.secret_key_base = "7584841652f89044a8b5a428efa6dfac2461449eb24741a33668cd642130d79f93b0347766ebf4a4d7d5033a263c36431594ad56b5735a7325c8cdda991219c2"
|
OpenneoImpressItems::Application.config.secret_key_base = "7584841652f89044a8b5a428efa6dfac2461449eb24741a33668cd642130d79f93b0347766ebf4a4d7d5033a263c36431594ad56b5735a7325c8cdda991219c2"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
class AddLastTradeActivityAtToUsers < ActiveRecord::Migration[7.1]
|
||||||
|
def change
|
||||||
|
add_column :users, :last_trade_activity_at, :timestamp
|
||||||
|
|
||||||
|
reversible do |direction|
|
||||||
|
direction.up do
|
||||||
|
User.find_in_batches do |users|
|
||||||
|
# Find the last ClosetList/ClosetHanger updated_at timestamp for each
|
||||||
|
# user, for trading lists/hangers only.
|
||||||
|
max_closet_list_updated_at_by_user_id = ClosetList.
|
||||||
|
trading.
|
||||||
|
group(:user_id).
|
||||||
|
where(user_id: users.map(&:id)).
|
||||||
|
maximum(:updated_at)
|
||||||
|
max_closet_hanger_updated_at_by_user_id = ClosetHanger.
|
||||||
|
trading.
|
||||||
|
group(:user_id).
|
||||||
|
where(user_id: users.map(&:id)).
|
||||||
|
maximum(:updated_at)
|
||||||
|
|
||||||
|
# Set `last_trade_activity_at` to the largest such `updated_at` for
|
||||||
|
# that user, or nil if there's none.
|
||||||
|
User.transaction do
|
||||||
|
users.each do |user|
|
||||||
|
user.last_trade_activity_at = [
|
||||||
|
max_closet_list_updated_at_by_user_id[user.id],
|
||||||
|
max_closet_hanger_updated_at_by_user_id[user.id],
|
||||||
|
].filter(&:present?).max
|
||||||
|
user.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,7 +11,7 @@
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.1].define(version: 2023_08_07_005748) do
|
ActiveRecord::Schema[7.1].define(version: 2023_08_07_005748) do
|
||||||
create_table "users", id: { type: :integer, unsigned: true }, charset: "utf8mb3", force: :cascade do |t|
|
create_table "users", id: { type: :integer, unsigned: true }, charset: "utf8mb3", collation: "utf8mb3_general_ci", force: :cascade do |t|
|
||||||
t.string "name", limit: 20, null: false
|
t.string "name", limit: 20, null: false
|
||||||
t.string "encrypted_password", limit: 64, null: false
|
t.string "encrypted_password", limit: 64, null: false
|
||||||
t.string "email", limit: 50, null: false
|
t.string "email", limit: 50, null: false
|
||||||
|
|
45
db/schema.rb
45
db/schema.rb
|
@ -10,8 +10,8 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
ActiveRecord::Schema[7.1].define(version: 2024_01_19_061745) do
|
||||||
create_table "auth_servers", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "auth_servers", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "short_name", limit: 10, null: false
|
t.string "short_name", limit: 10, null: false
|
||||||
t.string "name", limit: 40, null: false
|
t.string "name", limit: 40, null: false
|
||||||
t.text "icon", size: :medium, null: false
|
t.text "icon", size: :medium, null: false
|
||||||
|
@ -19,7 +19,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.string "secret", limit: 64, null: false
|
t.string "secret", limit: 64, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "campaigns", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "campaigns", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "progress", default: 0, null: false
|
t.integer "progress", default: 0, null: false
|
||||||
t.integer "goal", null: false
|
t.integer "goal", null: false
|
||||||
t.boolean "active", null: false
|
t.boolean "active", null: false
|
||||||
|
@ -33,7 +33,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.string "name"
|
t.string "name"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "closet_hangers", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "closet_hangers", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "item_id"
|
t.integer "item_id"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.integer "quantity"
|
t.integer "quantity"
|
||||||
|
@ -49,7 +49,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["user_id"], name: "index_closet_hangers_on_user_id"
|
t.index ["user_id"], name: "index_closet_hangers_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "closet_lists", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "closet_lists", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
|
@ -60,7 +60,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["user_id"], name: "index_closet_lists_on_user_id"
|
t.index ["user_id"], name: "index_closet_lists_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "color_translations", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "color_translations", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "color_id"
|
t.integer "color_id"
|
||||||
t.string "locale"
|
t.string "locale"
|
||||||
t.string "name"
|
t.string "name"
|
||||||
|
@ -70,13 +70,13 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["locale"], name: "index_color_translations_on_locale"
|
t.index ["locale"], name: "index_color_translations_on_locale"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "colors", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "colors", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.boolean "basic"
|
t.boolean "basic"
|
||||||
t.boolean "standard"
|
t.boolean "standard"
|
||||||
t.boolean "prank", default: false, null: false
|
t.boolean "prank", default: false, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "contributions", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "contributions", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "contributed_type", limit: 8, null: false
|
t.string "contributed_type", limit: 8, null: false
|
||||||
t.integer "contributed_id", null: false
|
t.integer "contributed_id", null: false
|
||||||
t.integer "user_id", null: false
|
t.integer "user_id", null: false
|
||||||
|
@ -85,14 +85,14 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["user_id"], name: "index_contributions_on_user_id"
|
t.index ["user_id"], name: "index_contributions_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "donation_features", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "donation_features", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "donation_id", null: false
|
t.integer "donation_id", null: false
|
||||||
t.integer "outfit_id"
|
t.integer "outfit_id"
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "donations", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "donations", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "amount", null: false
|
t.integer "amount", null: false
|
||||||
t.string "charge_id", null: false
|
t.string "charge_id", null: false
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
|
@ -104,7 +104,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.integer "campaign_id", null: false
|
t.integer "campaign_id", null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "item_outfit_relationships", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "item_outfit_relationships", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "item_id"
|
t.integer "item_id"
|
||||||
t.integer "outfit_id"
|
t.integer "outfit_id"
|
||||||
t.boolean "is_worn"
|
t.boolean "is_worn"
|
||||||
|
@ -149,7 +149,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["modeling_status_hint"], name: "items_modeling_status_hint"
|
t.index ["modeling_status_hint"], name: "items_modeling_status_hint"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "login_cookies", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "login_cookies", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "user_id", null: false
|
t.integer "user_id", null: false
|
||||||
t.integer "series", null: false
|
t.integer "series", null: false
|
||||||
t.integer "token", null: false
|
t.integer "token", null: false
|
||||||
|
@ -157,20 +157,20 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["user_id"], name: "login_cookies_user_id"
|
t.index ["user_id"], name: "login_cookies_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "modeling_logs", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "modeling_logs", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.text "log_json", null: false
|
t.text "log_json", null: false
|
||||||
t.string "pet_name", limit: 128, null: false
|
t.string "pet_name", limit: 128, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "neopets_connections", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "neopets_connections", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.string "neopets_username"
|
t.string "neopets_username"
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "outfits", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "outfits", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "pet_state_id"
|
t.integer "pet_state_id"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.datetime "created_at", precision: nil
|
t.datetime "created_at", precision: nil
|
||||||
|
@ -193,7 +193,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["swf_asset_id"], name: "parents_swf_assets_swf_asset_id"
|
t.index ["swf_asset_id"], name: "parents_swf_assets_swf_asset_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "pet_loads", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "pet_loads", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "pet_name", limit: 20, null: false
|
t.string "pet_name", limit: 20, null: false
|
||||||
t.text "amf", size: :medium, null: false
|
t.text "amf", size: :medium, null: false
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
|
@ -225,17 +225,17 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["species_id", "color_id"], name: "pet_types_species_color", unique: true
|
t.index ["species_id", "color_id"], name: "pet_types_species_color", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "pets", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "pets", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "name", limit: 20, null: false
|
t.string "name", limit: 20, null: false
|
||||||
t.integer "pet_type_id", limit: 3, null: false
|
t.integer "pet_type_id", limit: 3, null: false
|
||||||
t.index ["name"], name: "pets_name", unique: true
|
t.index ["name"], name: "pets_name", unique: true
|
||||||
t.index ["pet_type_id"], name: "pets_pet_type_id"
|
t.index ["pet_type_id"], name: "pets_pet_type_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "species", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "species", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "species_translations", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "species_translations", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "species_id"
|
t.integer "species_id"
|
||||||
t.string "locale"
|
t.string "locale"
|
||||||
t.string "name"
|
t.string "name"
|
||||||
|
@ -267,7 +267,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["zone_id"], name: "idx_swf_assets_zone_id"
|
t.index ["zone_id"], name: "idx_swf_assets_zone_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "users", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "users", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.string "name", limit: 20, null: false
|
t.string "name", limit: 20, null: false
|
||||||
t.integer "auth_server_id", limit: 1, null: false
|
t.integer "auth_server_id", limit: 1, null: false
|
||||||
t.integer "remote_id", null: false
|
t.integer "remote_id", null: false
|
||||||
|
@ -278,9 +278,10 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.integer "owned_closet_hangers_visibility", default: 1, null: false
|
t.integer "owned_closet_hangers_visibility", default: 1, null: false
|
||||||
t.integer "wanted_closet_hangers_visibility", default: 1, null: false
|
t.integer "wanted_closet_hangers_visibility", default: 1, null: false
|
||||||
t.integer "contact_neopets_connection_id"
|
t.integer "contact_neopets_connection_id"
|
||||||
|
t.timestamp "last_trade_activity_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "zone_translations", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "zone_translations", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "zone_id"
|
t.integer "zone_id"
|
||||||
t.string "locale"
|
t.string "locale"
|
||||||
t.string "label"
|
t.string "label"
|
||||||
|
@ -291,7 +292,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_11_234255) do
|
||||||
t.index ["zone_id"], name: "index_zone_translations_on_zone_id"
|
t.index ["zone_id"], name: "index_zone_translations_on_zone_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "zones", id: :integer, charset: "latin1", force: :cascade do |t|
|
create_table "zones", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
||||||
t.integer "depth"
|
t.integer "depth"
|
||||||
t.integer "type_id"
|
t.integer "type_id"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
require 'test_helper'
|
|
||||||
require 'rails/performance_test_help'
|
|
||||||
|
|
||||||
# Profiling results for each test method are written to tmp/performance.
|
|
||||||
class BrowsingTest < ActionDispatch::PerformanceTest
|
|
||||||
def test_homepage
|
|
||||||
get '/'
|
|
||||||
end
|
|
||||||
end
|
|
232
test/trade_activity_test.rb
Normal file
232
test/trade_activity_test.rb
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class TradeActivityTest < ActiveSupport::TestCase
|
||||||
|
test "New user's last trade activity is nil" do
|
||||||
|
user = create_user
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Trading list updates last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:trading].id)
|
||||||
|
hanger = create_closet_hanger(user: user, list: list)
|
||||||
|
created_at = Time.now
|
||||||
|
|
||||||
|
assert_equal created_at, user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_equal created_at + 1.day, user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Public list does not update last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:public].id)
|
||||||
|
hanger = create_closet_hanger(user: user, list: list)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Private list does not update last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:private].id)
|
||||||
|
hanger = create_closet_hanger(user: user, list: list)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Trading default-list updates last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:trading].id,
|
||||||
|
wanted_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
hanger = create_closet_hanger(user: user, owned: true)
|
||||||
|
created_at = Time.now
|
||||||
|
|
||||||
|
assert_equal created_at, user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_equal created_at + 1.day, user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Public default-list does not update last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:public].id,
|
||||||
|
wanted_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
hanger = create_closet_hanger(user: user, owned: true)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Adding or removing items in a Private default-list does not update last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
wanted_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
hanger = create_closet_hanger(user: user, owned: true)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
hanger.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Creating, editing, or deleting a Trading list updates last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:trading].id
|
||||||
|
)
|
||||||
|
created_at = Time.now
|
||||||
|
|
||||||
|
assert_equal created_at, user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.update!(description: "Hello, world!")
|
||||||
|
|
||||||
|
assert_equal created_at + 1.day, user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.destroy!
|
||||||
|
|
||||||
|
assert_equal created_at + 2.day, user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Creating, editing, or deleting a Public list does not update last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:public].id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.update!(description: "Hello, world!")
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Creating, editing, or deleting a Private list does not update last trade activity" do
|
||||||
|
user = create_user
|
||||||
|
list = create_closet_list(
|
||||||
|
user: user, visibility: ClosetVisibility[:private].id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.update!(description: "Hello, world!")
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
travel 1.day
|
||||||
|
list.destroy!
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Updating default-list visibility to Trading updates last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
user.update!(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:trading].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_equal Time.now, user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Updating default-list visibility to Public does not update last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
user.update!(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:public].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Updating default-list visibility to Private does not update last trade activity" do
|
||||||
|
user = create_user(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:public].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
|
||||||
|
user.update!(
|
||||||
|
owned_closet_hangers_visibility: ClosetVisibility[:private].id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nil user.last_trade_activity_at
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do
|
||||||
|
freeze_time # to compare timestamps accurately
|
||||||
|
|
||||||
|
Item.create!(
|
||||||
|
thumbnail_url: "https://images.neopets.com/foo.png",
|
||||||
|
zones_restrict: "",
|
||||||
|
price: 123,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_user(**args)
|
||||||
|
auth_user = AuthUser.create!(
|
||||||
|
name: 'test', email: 'test@example.com', password: 'test123!'
|
||||||
|
)
|
||||||
|
auth_user.user.update!(**args) unless args.empty?
|
||||||
|
auth_user.user
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_closet_list(**args)
|
||||||
|
num = ClosetList.count + 1
|
||||||
|
ClosetList.create!(name: "Test List #{num}", hangers_owned: true, **args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_closet_hanger(**args)
|
||||||
|
ClosetHanger.create!(item: Item.first, quantity: 1, **args)
|
||||||
|
end
|
||||||
|
end
|
BIN
vendor/cache/sqlite3-1.7.0-x86_64-linux.gem
vendored
Normal file
BIN
vendor/cache/sqlite3-1.7.0-x86_64-linux.gem
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue