Remove pro role + expose analytics to all users via dashboard (#13156)

* Remove pro role on user, expose pro dashboard to all users as analytics

* Remove pro from Elasticsearch mappings

* Update user role docs to use :trusted over :pro

* Remove pro from Role model spec

* Remove more references to pro, as noted by @rhymes
This commit is contained in:
Vaidehi Joshi 2021-03-30 15:02:18 -07:00 committed by GitHub
parent 2534a8aa5f
commit 95055b2a89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 83 additions and 211 deletions

View file

@ -21,11 +21,9 @@ function addRelevantButtonsToArticle(user) {
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1" href="${articleContainer.dataset.path}/manage" rel="nofollow">Manage</a>`,
);
}
if (user.pro) {
actions.push(
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1" href="${articleContainer.dataset.path}/stats" rel="nofollow">Stats</a>`,
);
}
actions.push(
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1" href="${articleContainer.dataset.path}/stats" rel="nofollow">Stats</a>`,
);
document.getElementById('action-space').innerHTML = actions.join('');
}
}

View file

@ -263,7 +263,7 @@
margin: 0 auto;
}
.pro-container {
.analytics-container {
width: 1400px;
margin: 0 auto;
}

View file

@ -74,13 +74,6 @@
width: 1.5em;
vertical-align: -0.22em;
margin-right: 0.15em;
&.pro-checkmark {
height: 0.5em;
width: 0.5em;
vertical-align: 0.08em;
margin-left: 0;
}
}
}
a {

View file

@ -195,7 +195,7 @@ module Admin
def user_params
allowed_params = %i[
new_note note_for_current_role user_status
pro merge_user_id add_credits remove_credits
merge_user_id add_credits remove_credits
add_org_credits remove_org_credits
organization_id identity_id
]

View file

@ -7,7 +7,6 @@ module Api
rescue_from UnauthorizedError, with: :error_unauthorized
before_action :authenticate_with_api_key_or_current_user!
before_action :authorize_pro_user
before_action :authorize_user_organization
before_action :load_owner
before_action :validate_date_params, only: [:historical]
@ -46,10 +45,6 @@ module Api
private
def authorize_pro_user
raise UnauthorizedError unless @user&.pro?
end
def authorize_user_organization
return unless analytics_params[:organization_id]

View file

@ -172,7 +172,6 @@ class ArticlesController < ApplicationController
end
def stats
authorize current_user, :pro_user?
authorize @article
@organization_id = @article.organization_id
end

View file

@ -66,7 +66,6 @@ class AsyncInfoController < ApplicationController
trusted: @user.trusted,
moderator_for_tags: @user.moderator_for_tags,
config_body_class: @user.config_body_class,
pro: @user.pro?,
feed_style: feed_style_preference,
created_at: @user.created_at,
admin: @user.any_admin?
@ -83,7 +82,6 @@ class AsyncInfoController < ApplicationController
#{current_user&.updated_at}__
#{current_user&.reactions_count}__
#{current_user&.articles_count}__
#{current_user&.pro?}__
#{current_user&.blocking_others_count}__"
end
end

View file

@ -1,14 +1,11 @@
class DashboardsController < ApplicationController
before_action :set_no_cache_header
before_action :authenticate_user!
before_action :fetch_and_authorize_user, except: :pro
before_action :fetch_and_authorize_user, except: :analytics
before_action :set_source, only: %i[subscriptions]
before_action -> { limit_per_page(default: 80, max: 1000) }, except: %i[show pro]
after_action :verify_authorized
before_action -> { limit_per_page(default: 80, max: 1000) }, except: %i[show analytics]
def show
@current_user_pro = current_user.pro?
target = @user
not_authorized if params[:org_id] && !@user.org_admin?(params[:org_id] || @user.any_admin?)
@ -55,13 +52,10 @@ class DashboardsController < ApplicationController
.includes(:follower).order(created_at: :desc).limit(@follows_limit)
end
def pro
def analytics
@user_or_org = if params[:org_id]
org = Organization.find_by(id: params[:org_id])
authorize org, :pro_org_user?
org
Organization.find_by(id: params[:org_id])
else
authorize current_user, :pro_user?
current_user
end
@organizations = current_user.member_organizations

View file

@ -34,7 +34,6 @@ describe('<ReadingList />', () => {
user: {
id: 318840,
name: 'Bobby Tables',
pro: null,
profile_image_90: 'https://picsum.photos/90/90',
username: 'bobbytables',
},

View file

@ -6,7 +6,6 @@ module Constants
"Suspend",
"Regular Member",
"Trusted",
"Pro",
].freeze
SPECIAL_ROLES = [

View file

@ -6,7 +6,6 @@ class Role < ApplicationRecord
codeland_admin
comment_banned
podcast_admin
pro
restricted_liquid_tag
single_resource_admin
super_admin

View file

@ -94,7 +94,7 @@ class User < ApplicationRecord
\z
}x.freeze
attr_accessor :scholar_email, :new_note, :note_for_current_role, :user_status, :pro, :merge_user_id,
attr_accessor :scholar_email, :new_note, :note_for_current_role, :user_status, :merge_user_id,
:add_credits, :remove_credits, :add_org_credits, :remove_org_credits, :ip_address,
:current_password
@ -387,12 +387,6 @@ class User < ApplicationRecord
has_role?(:tech_admin) || has_role?(:super_admin)
end
def pro?
Rails.cache.fetch("user-#{id}/has_pro_role", expires_in: 200.hours) do
has_role?(:pro)
end
end
def vomitted_on?
Reaction.exists?(reactable_id: id, reactable_type: "User", category: "vomit", status: "confirmed")
end

View file

@ -30,8 +30,4 @@ class OrganizationPolicy < ApplicationPolicy
def generate_new_secret?
update?
end
def pro_org_user?
user.pro? && OrganizationMembership.exists?(user_id: user.id, organization_id: record.id)
end
end

View file

@ -108,10 +108,6 @@ class UserPolicy < ApplicationPolicy
current_user? || user_admin? || minimal_admin?
end
def pro_user?
current_user? && user.pro?
end
def moderation_routes?
(user.has_role?(:trusted) || minimal_admin?) && !user.banned
end

View file

@ -1,5 +1,5 @@
module Search
class NestedUserSerializer < ApplicationSerializer
attributes :id, :name, :pro, :profile_image_90, :username
attributes :id, :name, :profile_image_90, :username
end
end

View file

@ -11,7 +11,6 @@ module DataSync
SHARED_FIELDS = %i[
username
name
pro
profile_image_url
].freeze

View file

@ -26,7 +26,6 @@ module Moderator
def remove_privileges
@user.remove_role(:workshop_pass)
@user.remove_role(:pro)
remove_mod_roles
remove_tag_moderator_role
end
@ -68,7 +67,6 @@ module Moderator
regular_member
when "Trusted"
remove_negative_roles
user.remove_role(:pro)
TagModerators::AddTrustedRole.call(user)
when "Admin"
check_super_admin
@ -90,10 +88,6 @@ module Moderator
check_super_admin
remove_negative_roles
user.add_role(:single_resource_admin, role.split("Resource Admin: ").last.safe_constantize)
when "Pro"
remove_negative_roles
TagModerators::AddTrustedRole.call(user)
user.add_role(:pro)
end
create_note(role, note)
end
@ -110,7 +104,6 @@ module Moderator
def regular_member
remove_negative_roles
user.remove_role(:pro)
remove_mod_roles
end

View file

@ -1,6 +1,6 @@
<% title "Stats for Your Article" %>
<div class="dashboard-container pro-container" id="user-dashboard">
<div class="dashboard-container analytics-container" id="user-dashboard">
<a
href="<%= @article.current_state_path %>"
class="rounded-btn rounded-btn--transparent"
@ -11,7 +11,7 @@
</a>
<section class="header-card card">
<h1 class="pro-header">Stats for "<%= @article.title %>"</h1>
<h1 class="analytics-header">Stats for "<%= @article.title %>"</h1>
</section>
<%= render "shared/stats" %>

View file

@ -39,15 +39,13 @@
<%= inline_svg_tag("external-link.svg", aria: true, class: "crayons-icon", title: "Moderation") %>
</a>
<% if @current_user_pro %>
<a class="crayons-link crayons-link--block" href="<%= dashboard_pro_path %>">
Pro Analytics
</a>
<a class="crayons-link crayons-link--block" href="<%= dashboard_analytics_path %>">
Analytics
</a>
<% if @organizations && (params[:which].blank? || params[:which] == "organization") %>
<% @organizations.each do |org| %>
<a class="crayons-link crayons-link--block" href="<%= dashboard_pro_org_path(org.id) %>">Pro Analytics for <%= org.name %></a>
<% end %>
<% if @organizations && (params[:which].blank? || params[:which] == "organization") %>
<% @organizations.each do |org| %>
<a class="crayons-link crayons-link--block" href="<%= dashboard_analytics_org_path(org.id) %>">Analytics for <%= org.name %></a>
<% end %>
<% end %>

View file

@ -9,13 +9,11 @@
<option value="/listings/dashboard">Listings</option>
<% if @current_user_pro %>
<option value="<%= dashboard_pro_path %>">Pro Analytics</option>
<option value="<%= dashboard_analytics_path %>">Analytics</option>
<% if @organizations && (params[:which].blank? || params[:which] == "organization") %>
<% @organizations.each do |org| %>
<option value="<%= dashboard_pro_org_path(org.id) %>">Pro Analytics for <%= org.name %></option>
<% end %>
<% if @organizations && (params[:which].blank? || params[:which] == "organization") %>
<% @organizations.each do |org| %>
<option value="<%= dashboard_analytics_org_path(org.id) %>">Analytics for <%= org.name %></option>
<% end %>
<% end %>

View file

@ -64,9 +64,8 @@
<% elsif @user == article.user %>
<a href="<%= article.path %>/delete_confirm" data-no-instant class="crayons-btn crayons-btn--danger">Delete</a>
<% end %>
<% if @current_user_pro %>
<a href="<%= article.path %>/stats" data-no-instant class="crayons-btn">Stats</a>
<% end %>
<a href="<%= article.path %>/stats" data-no-instant class="crayons-btn">Stats</a>
<% if article.published %>
<span id="pageviews-<%= article.id %>" class="crayons-btn dashboard-pageviews-indicator" data-analytics-pageviews data-article-id="<%= article.id %>">

View file

@ -100,9 +100,7 @@
<% if article.user_subscriptions_count > 0 %>
<a href="<%= dashboard_subscriptions_path(source_type: "Article", source_id: article.id) %>" class="crayons-link crayons-link--block w-100"><%= "Subscriptions (#{article.user_subscriptions_count})" %></a>
<% end %>
<% if @current_user_pro %>
<a href="<%= article.path %>/stats" class="crayons-link crayons-link--block w-100">Stats</a>
<% end %>
<a href="<%= article.path %>/stats" class="crayons-link crayons-link--block w-100">Stats</a>
<%= form_for(article, method: :patch, remote: true, authenticity_token: true, html: { "data-type": "json", class: "js-archive-toggle" }) do |f| %>
<%= f.hidden_field :archived, value: !article.archived, id: "article_archived_#{article.id}" %>

View file

@ -1,24 +1,25 @@
<% title "Pro Analytics" %>
<% title "Analytics" %>
<div class="dashboard-container pro-container crayons-layout" id="user-dashboard">
<div class="dashboard-container analytics-container crayons-layout" id="user-dashboard">
<a href="/dashboard" class="rounded-btn rounded-btn--transparent">👈 Back to Main Dashboard</a>
<a class="rounded-btn <%= "active" unless params[:org_id] %>" href="/dashboard/pro">
Your Pro Dashboard
<a class="rounded-btn <%= "active" unless params[:org_id] %>" href="<%= dashboard_analytics_path %>">
Your Dashboard
</a>
<% @organizations.each do |org| %>
<a
class="rounded-btn organization <%= "active" if params[:org_id].to_i == org.id %>"
href="/dashboard/pro/org/<%= org.id %>"
href="<%= dashboard_analytics_org_path(org.id) %>"
href="<%= dashboard_analytics_path %>"
data-organization-id="<%= org.id %>">
<%= org.name %> Pro Dashboard
<%= org.name %> Analytics Dashboard
</a>
<% end %>
<section class="header-card card">
<h1 class="pro-header">Pro Dashboard for <%= @user_or_org.name %></h1>
<p>Welcome to the Pro Dashboard, the home of in-depth user metrics so that authors can make data-driven decisions about the <%= SiteConfig.community_member_label %> ecosystem.</p>
<h1 class="analytics-header">Analytics Dashboard for <%= @user_or_org.name %></h1>
<p>Welcome to the Analytics Dashboard, the home of in-depth user metrics so that authors can make data-driven decisions about the <%= SiteConfig.community_member_label %> ecosystem.</p>
<p>This dashboard highlights deep insights especially relevant to <%= SiteConfig.community_member_label %> relations, authors, and serious bloggers.</p>
</section>

View file

@ -170,9 +170,6 @@
},
"profile_image_90": {
"type": "keyword"
},
"pro": {
"type": "boolean"
}
}
},

View file

@ -78,9 +78,6 @@
},
"profile_image_90": {
"type": "keyword"
},
"pro": {
"type": "boolean"
}
}
}

View file

@ -557,8 +557,8 @@ Rails.application.routes.draw do
get "/settings/:tab/:id", to: "users#edit", constraints: { tab: /response-templates/ }
get "/signout_confirm", to: "users#signout_confirm"
get "/dashboard", to: "dashboards#show"
get "/dashboard/pro", to: "dashboards#pro"
get "dashboard/pro/org/:org_id", to: "dashboards#pro", as: :dashboard_pro_org
get "/dashboard/analytics", to: "dashboards#analytics"
get "dashboard/analytics/org/:org_id", to: "dashboards#analytics", as: :dashboard_analytics_org
get "dashboard/following", to: "dashboards#following_tags"
get "dashboard/following_tags", to: "dashboards#following_tags"
get "dashboard/following_users", to: "dashboards#following_users"

View file

@ -33,21 +33,21 @@ at the console.
rails console
```
- after verifying the user `test_user_name` is missing the `pro` role we proceed
to add it and then verify the role has been added:
- after verifying the user `test_user_name` is missing the `trusted` role we
proceed to add it and then verify the role has been added:
```ruby
> user = User.find_by(username: "test_user_name")
> user.has_role? :pro
> user.has_role? :trusted
=> false
> user.add_role(:pro)
> user.add_role(:trusted)
=> #<Role:
...
name: "pro"
name: "trusted"
.. >
> user.has_role? :pro
> user.has_role? :trusted
=> true
```

View file

@ -99,10 +99,6 @@ FactoryBot.define do
end
end
trait :pro do
after(:build) { |user| user.add_role(:pro) }
end
trait :org_member do
after(:create) do |user|
org = create(:organization)

View file

@ -8,7 +8,7 @@ RSpec.describe Role, type: :model do
describe "::ROLES" do
it "contains the correct values" do
expected_roles = %w[
admin banned chatroom_beta_tester codeland_admin comment_banned podcast_admin pro restricted_liquid_tag
admin banned chatroom_beta_tester codeland_admin comment_banned podcast_admin restricted_liquid_tag
single_resource_admin super_admin tag_moderator mod_relations_admin support_admin tech_admin trusted
warned workshop_pass
]

View file

@ -759,17 +759,6 @@ RSpec.describe User, type: :model do
end
end
describe "#pro?" do
it "returns false if the user is not a pro" do
expect(user.pro?).to be(false)
end
it "returns true if the user has the pro role" do
user.add_role(:pro)
expect(user.pro?).to be(true)
end
end
describe "#enough_credits?" do
it "returns false if the user has less unspent credits than neeed" do
expect(user.enough_credits?(1)).to be(false)

View file

@ -9,7 +9,7 @@ RSpec.describe "Api::V0::Analytics", type: :request do
include_examples "GET /api/analytics/:endpoint authorization examples", "historical", "&start=2019-03-29"
context "when the start parameter is not included" do
before { get "/api/analytics/historical", headers: { "api-key" => pro_api_token.secret } }
before { get "/api/analytics/historical", headers: { "api-key" => api_token.secret } }
it "fails with an unprocessable entity HTTP error" do
expect(response).to have_http_status(:unprocessable_entity)
@ -22,7 +22,7 @@ RSpec.describe "Api::V0::Analytics", type: :request do
end
context "when the start parameter has the incorrect format" do
before { get "/api/analytics/historical?start=2019/2/2", headers: { "api-key" => pro_api_token.secret } }
before { get "/api/analytics/historical?start=2019/2/2", headers: { "api-key" => api_token.secret } }
it "fails with an unprocessable entity HTTP error" do
expect(response).to have_http_status(:unprocessable_entity)

View file

@ -301,13 +301,7 @@ RSpec.describe "Articles", type: :request do
expect { get "#{article.path}/stats" }.to raise_error(Pundit::NotAuthorizedError)
end
it "returns unauthorized if the user is not pro" do
article = create(:article, user: user)
expect { get "#{article.path}/stats" }.to raise_error(Pundit::NotAuthorizedError)
end
it "works successfully" do
user.add_role(:pro)
article = create(:article, user: user)
get "#{article.path}/stats"
expect(response).to have_http_status(:ok)

View file

@ -4,7 +4,6 @@ RSpec.describe "Dashboards", type: :request do
let(:user) { create(:user) }
let(:second_user) { create(:user) }
let(:super_admin) { create(:user, :super_admin) }
let(:pro_user) { create(:user, :pro) }
let(:article) { create(:article, user: user) }
let(:unpublished_article) { create(:article, user: user, published: false) }
let(:organization) { create(:organization) }
@ -28,9 +27,12 @@ RSpec.describe "Dashboards", type: :request do
expect(response.body).to include(CGI.escapeHTML(article.title))
end
it 'does not show "STATS" for articles' do
it 'shows "STATS" for articles' do
article = create(:article, user: user)
get "/dashboard"
expect(response.body).not_to include("Stats")
expect(response.body).to include("Stats")
expect(response.body).to include("#{article.path}/stats")
end
it "renders the delete button for drafts" do
@ -66,18 +68,18 @@ RSpec.describe "Dashboards", type: :request do
expect(response.body).not_to include "pagination"
end
it "does not render a link to pro analytics" do
it "renders a link to analytics dashboard" do
get dashboard_path
expect(response.body).not_to include("Pro Analytics")
expect(response.body).to include("Analytics")
end
it "does not render a link to pro analytics for the org" do
it "renders a link to analytics for the org" do
create(:organization_membership, type_of_user: :admin, organization: organization, user: user)
get dashboard_path
expect(response.body).not_to include("Pro Analytics for #{organization.name}")
expect(response.body).to include("Analytics for #{organization.name}")
end
it "does not render a link to upload a video when enable_video_upload is false" do
@ -105,32 +107,6 @@ RSpec.describe "Dashboards", type: :request do
end
end
context "when logged in as a pro user" do
it 'shows "STATS" for articles' do
article = create(:article, user: pro_user)
sign_in pro_user
get "/dashboard"
expect(response.body).to include("Stats")
expect(response.body).to include("#{article.path}/stats")
end
it "renders a link to pro analytics" do
sign_in pro_user
get dashboard_path
expect(response.body).to include("Pro Analytics")
end
it "renders a link to pro analytics for the org" do
create(:organization_membership, type_of_user: :admin, organization: organization, user: pro_user)
sign_in pro_user
get dashboard_path
expect(response.body).to include("Pro Analytics for #{CGI.escapeHTML(organization.name)}")
end
end
context "when logged in as a non recent user with enable_video_upload set to true on the Forem" do
it "renders a link to upload a video" do
Timecop.freeze(Time.current) do
@ -278,49 +254,41 @@ RSpec.describe "Dashboards", type: :request do
end
end
describe "GET /dashboard/pro" do
describe "GET /dashboard/analytics" do
context "when not logged in" do
it "raises unauthorized" do
get "/dashboard/pro"
get "/dashboard/analytics"
expect(response).to redirect_to("/enter")
end
end
context "when user does not have permission" do
it "raises unauthorized" do
sign_in user
expect { get "/dashboard/pro" }.to raise_error(Pundit::NotAuthorizedError)
end
end
context "when user has pro permission" do
context "when user is signed in" do
it "shows page properly" do
user.add_role(:pro)
sign_in user
get "/dashboard/pro"
expect(response.body).to include("pro")
get "/dashboard/analytics"
expect(response.body).to include("Analytics")
end
end
context "when user has pro permission and is an org admin" do
context "when user is an org admin" do
it "shows page properly" do
org = create :organization
create(:organization_membership, user: user, organization: org, type_of_user: "admin")
user.add_role(:pro)
sign_in user
get "/dashboard/pro/org/#{org.id}"
expect(response.body).to include("pro")
get "/dashboard/analytics/org/#{org.id}"
expect(response.body).to include("Analytics")
end
end
context "when user has pro permission and is an org member" do
context "when user has is an org member" do
it "shows page properly" do
org = create :organization
create(:organization_membership, user: user, organization: org)
user.add_role(:pro)
sign_in user
get "/dashboard/pro/org/#{org.id}"
expect(response.body).to include("pro")
get "/dashboard/analytics/org/#{org.id}"
expect(response.body).to include("Analytics")
end
end
end

View file

@ -1,14 +1,12 @@
RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |endpoint, params|
let(:user) { create(:user) }
let(:api_token) { create(:api_secret, user: user) }
let(:pro_user) { create(:user, :pro) }
let(:pro_api_token) { create(:api_secret, user: pro_user) }
let(:pro_org_member) { create(:user, :pro, :org_member) }
let(:org_member_token) { create(:api_secret, user: pro_org_member) }
let(:org) { pro_org_member.organizations.first }
let(:org_member) { create(:user, :org_member) }
let(:org_member_token) { create(:api_secret, user: org_member) }
let(:org) { org_member.organizations.first }
let(:article) { create(:article, user: user) }
let(:pro_user_article) { create(:article, user: pro_user) }
let(:pro_org_article) { create(:article, user: pro_user, organization: org) }
let(:user_article) { create(:article, user: user) }
let(:org_article) { create(:article, user: user, organization: org) }
context "when an invalid token is given" do
before { get "/api/analytics/#{endpoint}?#{params}", headers: { "api-key" => "abadskajdlsak" } }
@ -22,21 +20,9 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
end
end
context "when a valid token is given but the user is not a pro" do
context "when a valid token is given" do
before { get "/api/analytics/#{endpoint}?#{params}", headers: { "api-key" => api_token.secret } }
it "renders an error message: 'unauthorized' in JSON" do
expect(response.parsed_body).to include("error" => "unauthorized")
end
it "has a status 401" do
expect(response).to have_http_status(:unauthorized)
end
end
context "when a valid token is given and the user is a pro" do
before { get "/api/analytics/#{endpoint}?#{params}", headers: { "api-key" => pro_api_token.secret } }
it "renders JSON as the content type" do
expect(response.media_type).to eq "application/json"
end
@ -44,7 +30,7 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
context "when attempting to view organization analytics without belonging to the organization" do
before do
headers = { "api-key" => pro_api_token.secret }
headers = { "api-key" => api_token.secret }
get "/api/analytics/#{endpoint}?organization_id=#{org.id}#{params}", headers: headers
end
@ -59,7 +45,7 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
context "when attempting to view organization analytics and being a member of the organization" do
before do
path = "/api/analytics/#{endpoint}?organization_id=#{pro_org_member.organization_ids.first}#{params}"
path = "/api/analytics/#{endpoint}?organization_id=#{org_member.organization_ids.first}#{params}"
get path, headers: { "api-key" => org_member_token.secret }
end
@ -86,7 +72,7 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
context "when viewing as current user" do
it "responds with status 200 OK" do
sign_in pro_user
sign_in user
get "/api/analytics/#{endpoint}?#{params}"
expect(response).to have_http_status(:ok)
end
@ -94,18 +80,18 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
context "when viewing your own single article's analytics" do
it "responds with status 200 OK" do
sign_in pro_user
get "/api/analytics/#{endpoint}?article_id=#{pro_user_article.id}#{params}"
sign_in user
get "/api/analytics/#{endpoint}?article_id=#{user_article.id}#{params}"
expect(response).to have_http_status(:ok)
end
end
context "when viewing your own organizaiton's single article's analytics" do
it "responds with status 200 OK" do
org_param = "&organization_id=#{pro_org_article.organization.id}"
org_param = "&organization_id=#{org_article.organization.id}"
sign_in pro_org_member
get "/api/analytics/#{endpoint}?article_id=#{pro_org_article.id}#{params}#{org_param}"
sign_in org_member
get "/api/analytics/#{endpoint}?article_id=#{org_article.id}#{params}#{org_param}"
expect(response).to have_http_status(:ok)
end
end

View file

@ -4,9 +4,8 @@ RSpec.describe "Viewing an article stats", type: :system, js: true do
let(:user) { create(:user) }
let(:article) { create(:article, user: user) }
it "shows stats for pro users by clicking on the stats button" do
it "shows stats for a user by clicking on the stats button" do
path = "/#{user.username}/#{article.slug}/stats"
allow(user).to receive(:pro?).and_return(true)
sign_in user
visit path