Merge pull request #70 from Retrospring/feature/announcements
Implement Announcements
This commit is contained in:
commit
516bc48aa0
2
Gemfile
2
Gemfile
|
@ -105,4 +105,6 @@ group :development, :test do
|
||||||
gem 'letter_opener' # Use this just in local test environments
|
gem 'letter_opener' # Use this just in local test environments
|
||||||
gem 'brakeman'
|
gem 'brakeman'
|
||||||
gem 'guard-brakeman'
|
gem 'guard-brakeman'
|
||||||
|
gem 'timecop'
|
||||||
|
gem 'rails-controller-testing'
|
||||||
end
|
end
|
||||||
|
|
|
@ -344,6 +344,10 @@ GEM
|
||||||
rails-assets-growl (1.3.5)
|
rails-assets-growl (1.3.5)
|
||||||
rails-assets-jquery
|
rails-assets-jquery
|
||||||
rails-assets-jquery (2.2.4)
|
rails-assets-jquery (2.2.4)
|
||||||
|
rails-controller-testing (1.0.4)
|
||||||
|
actionpack (>= 5.0.1.x)
|
||||||
|
actionview (>= 5.0.1.x)
|
||||||
|
activesupport (>= 5.0.1.x)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
|
@ -459,6 +463,7 @@ GEM
|
||||||
thor (1.0.1)
|
thor (1.0.1)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.10)
|
tilt (2.0.10)
|
||||||
|
timecop (0.9.1)
|
||||||
tiny-color-rails (0.0.2)
|
tiny-color-rails (0.0.2)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
turbolinks (2.5.4)
|
turbolinks (2.5.4)
|
||||||
|
@ -553,6 +558,7 @@ DEPENDENCIES
|
||||||
rails (~> 5.2)
|
rails (~> 5.2)
|
||||||
rails-assets-growl!
|
rails-assets-growl!
|
||||||
rails-assets-jquery (~> 2.2.0)!
|
rails-assets-jquery (~> 2.2.0)!
|
||||||
|
rails-controller-testing
|
||||||
rails-i18n (~> 5.0)
|
rails-i18n (~> 5.0)
|
||||||
rails_admin
|
rails_admin
|
||||||
rake
|
rake
|
||||||
|
@ -570,6 +576,7 @@ DEPENDENCIES
|
||||||
simplecov-rcov
|
simplecov-rcov
|
||||||
spring (~> 2.0)
|
spring (~> 2.0)
|
||||||
sweetalert-rails
|
sweetalert-rails
|
||||||
|
timecop
|
||||||
tiny-color-rails
|
tiny-color-rails
|
||||||
tumblr_client!
|
tumblr_client!
|
||||||
turbolinks (~> 2.5.3)
|
turbolinks (~> 2.5.3)
|
||||||
|
|
|
@ -74,6 +74,16 @@ _ready = ->
|
||||||
lineColor: bodyColor
|
lineColor: bodyColor
|
||||||
density: 23000
|
density: 23000
|
||||||
|
|
||||||
|
$(".alert-announcement").each ->
|
||||||
|
aId = $(this)[0].dataset.announcementId
|
||||||
|
unless (window.localStorage.getItem("announcement#{aId}"))
|
||||||
|
$(this).toggleClass("hidden")
|
||||||
|
|
||||||
|
$(document).on "click", ".alert-announcement button.close", (evt) ->
|
||||||
|
announcement = event.target.closest(".alert-announcement")
|
||||||
|
aId = announcement.dataset.announcementId
|
||||||
|
window.localStorage.setItem("announcement#{aId}", true)
|
||||||
|
|
||||||
$('.arctic_scroll').arctic_scroll speed: 500
|
$('.arctic_scroll').arctic_scroll speed: 500
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
class AnnouncementController < ApplicationController
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
def index
|
||||||
|
@announcements = Announcement.all
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@announcement = Announcement.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@announcement = Announcement.new(announcement_params)
|
||||||
|
@announcement.user = current_user
|
||||||
|
if @announcement.save
|
||||||
|
flash[:success] = "Announcement created successfully."
|
||||||
|
redirect_to action: :index
|
||||||
|
else
|
||||||
|
render 'announcement/new'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@announcement = Announcement.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@announcement = Announcement.find(params[:id])
|
||||||
|
@announcement.update(announcement_params)
|
||||||
|
if @announcement.save
|
||||||
|
flash[:success] = "Announcement updated successfully."
|
||||||
|
redirect_to announcement_index_path
|
||||||
|
else
|
||||||
|
render 'announcement/edit'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if Announcement.destroy(params[:id])
|
||||||
|
flash[:success] = "Announcement deleted successfully."
|
||||||
|
else
|
||||||
|
flash[:error] = "Failed to delete announcement."
|
||||||
|
end
|
||||||
|
redirect_to announcement_index_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def announcement_params
|
||||||
|
params.require(:announcement).permit(:content, :link_text, :link_href, :starts_at, :ends_at)
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
|
||||||
before_action :configure_permitted_parameters, if: :devise_controller?
|
before_action :configure_permitted_parameters, if: :devise_controller?
|
||||||
before_action :check_locale
|
before_action :check_locale
|
||||||
before_action :banned?
|
before_action :banned?
|
||||||
|
before_action :find_active_announcements
|
||||||
|
|
||||||
# check if user wants to read
|
# check if user wants to read
|
||||||
def check_locale
|
def check_locale
|
||||||
|
@ -50,6 +51,10 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_active_announcements
|
||||||
|
@active_announcements ||= Announcement.find_active
|
||||||
|
end
|
||||||
|
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
module AnnouncementHelper
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
class Announcement < ApplicationRecord
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
validates :content, presence: true
|
||||||
|
validates :starts_at, presence: true
|
||||||
|
validates :link_href, presence: true, if: -> { link_text.present? }
|
||||||
|
validate :starts_at, :validate_date_range
|
||||||
|
|
||||||
|
def self.find_active
|
||||||
|
Rails.cache.fetch "announcement_active", expires_in: 1.minute do
|
||||||
|
where "starts_at <= :now AND ends_at > :now", now: Time.current
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def active?
|
||||||
|
Time.now.utc >= starts_at && Time.now.utc < ends_at
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_present?
|
||||||
|
link_text.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_date_range
|
||||||
|
if starts_at > ends_at
|
||||||
|
errors.add(:starts_at, "Start date must be before end date")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
- provide(:title, generate_title("Edit announcement"))
|
||||||
|
.container.j2-page
|
||||||
|
= bootstrap_form_for(@announcement, url: {action: "update"}, method: "PATCH") do |f|
|
||||||
|
- if @announcement.errors.any?
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
.alert.alert-danger
|
||||||
|
%strong
|
||||||
|
= pluralize(@announcement.errors.count, "error")
|
||||||
|
prohibited this announcement from being saved:
|
||||||
|
%ul
|
||||||
|
- @announcement.errors.full_messages.each do |err|
|
||||||
|
%li= err
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
= f.text_area :content, label: "Content"
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.url_field :link_href, label: "Link URL"
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :link_text, label: "Link text"
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :starts_at, label: "Start time"
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :ends_at, label: "End time"
|
||||||
|
.row
|
||||||
|
.col-md-12.text-right
|
||||||
|
= f.submit class: "btn btn-primary"
|
|
@ -0,0 +1,14 @@
|
||||||
|
- provide(:title, generate_title("Announcements"))
|
||||||
|
.container.j2-page
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
= link_to "Add new", :announcement_new, class: "btn btn-default"
|
||||||
|
- @announcements.each do |announcement|
|
||||||
|
.panel.panel-default
|
||||||
|
.panel-heading
|
||||||
|
= announcement.starts_at
|
||||||
|
.panel-body
|
||||||
|
= announcement.content
|
||||||
|
.panel-footer
|
||||||
|
= button_to "Edit", announcement_edit_path(id: announcement.id), method: :get, class: 'btn btn-link'
|
||||||
|
= button_to "Delete", announcement_destroy_path(id: announcement.id), method: :delete, class: 'btn btn-link', confirm: 'Are you sure you want to delete this announcement?'
|
|
@ -0,0 +1,29 @@
|
||||||
|
- provide(:title, generate_title("Add new announcement"))
|
||||||
|
.container.j2-page
|
||||||
|
= bootstrap_form_for(@announcement, url: {action: "create"}) do |f|
|
||||||
|
- if @announcement.errors.any?
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
.alert.alert-danger
|
||||||
|
%strong
|
||||||
|
= pluralize(@announcement.errors.count, "error")
|
||||||
|
prohibited this announcement from being saved:
|
||||||
|
%ul
|
||||||
|
- @announcement.errors.full_messages.each do |err|
|
||||||
|
%li= err
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
= f.text_area :content, label: "Content"
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.url_field :link_href, label: "Link URL"
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :link_text, label: "Link text"
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :starts_at, label: "Start time"
|
||||||
|
.col-md-6
|
||||||
|
= f.datetime_field :ends_at, label: "End time"
|
||||||
|
.row
|
||||||
|
.col-md-12.text-right
|
||||||
|
= f.submit class: "btn btn-primary"
|
|
@ -28,6 +28,10 @@
|
||||||
%a{href: pghero_path}
|
%a{href: pghero_path}
|
||||||
%i.fa.fa-fw.fa-database
|
%i.fa.fa-fw.fa-database
|
||||||
Database Monitor
|
Database Monitor
|
||||||
|
%li
|
||||||
|
%a{href: announcement_index_path}
|
||||||
|
%i.fa.fa-fw.fa-info
|
||||||
|
Announcements
|
||||||
%li.divider
|
%li.divider
|
||||||
- if current_user.mod?
|
- if current_user.mod?
|
||||||
%li
|
%li
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
= csrf_meta_tags
|
= csrf_meta_tags
|
||||||
%body#version1
|
%body#version1
|
||||||
= render 'layouts/header'
|
= render 'layouts/header'
|
||||||
|
= render 'shared/announcements'
|
||||||
= yield
|
= yield
|
||||||
= render 'shared/locales'
|
= render 'shared/locales'
|
||||||
- if Rails.env.development?
|
- if Rails.env.development?
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
.container.announcements
|
||||||
|
- @active_announcements.each do |announcement|
|
||||||
|
.alert.alert-announcement.alert-info.alert-dismissable.hidden{ data: { 'announcement-id': announcement.id } }
|
||||||
|
%button.close{ type: "button", "data-dismiss" => "alert" }
|
||||||
|
%span{ "aria-hidden" => "true" } ×
|
||||||
|
%p= announcement.content
|
||||||
|
- if announcement.link_present?
|
||||||
|
%a.alert-link{ href: announcement.link_href }= announcement.link_text
|
|
@ -10,6 +10,13 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
mount Sidekiq::Web, at: "/sidekiq"
|
mount Sidekiq::Web, at: "/sidekiq"
|
||||||
mount PgHero::Engine, at: "/pghero", as: "pghero"
|
mount PgHero::Engine, at: "/pghero", as: "pghero"
|
||||||
|
|
||||||
|
match "/admin/announcements", to: "announcement#index", via: :get, as: :announcement_index
|
||||||
|
match "/admin/announcements", to: "announcement#create", via: :post, as: :announcement_create
|
||||||
|
match "/admin/announcements/new", to: "announcement#new", via: :get, as: :announcement_new
|
||||||
|
match "/admin/announcements/:id/edit", to: "announcement#edit", via: :get, as: :announcement_edit
|
||||||
|
match "/admin/announcements/:id", to: "announcement#update", via: :patch, as: :announcement_update
|
||||||
|
match "/admin/announcements/:id", to: "announcement#destroy", via: :delete, as: :announcement_destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
# Moderation panel
|
# Moderation panel
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
class CreateAnnouncements < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :announcements do |t|
|
||||||
|
t.text :content, null: false
|
||||||
|
t.string :link_text
|
||||||
|
t.string :link_href
|
||||||
|
t.datetime :starts_at, null: false
|
||||||
|
t.datetime :ends_at, null: false
|
||||||
|
t.belongs_to :user, null: false
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
12
db/schema.rb
12
db/schema.rb
|
@ -15,6 +15,18 @@ ActiveRecord::Schema.define(version: 2020_04_19_185535) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
create_table "announcements", force: :cascade do |t|
|
||||||
|
t.text "content", null: false
|
||||||
|
t.string "link_text"
|
||||||
|
t.string "link_href"
|
||||||
|
t.datetime "starts_at", null: false
|
||||||
|
t.datetime "ends_at", null: false
|
||||||
|
t.bigint "user_id", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["user_id"], name: "index_announcements_on_user_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "answers", id: :serial, force: :cascade do |t|
|
create_table "answers", id: :serial, force: :cascade do |t|
|
||||||
t.text "content"
|
t.text "content"
|
||||||
t.integer "question_id"
|
t.integer "question_id"
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe AnnouncementController, type: :controller do
|
||||||
|
let(:user) { FactoryBot.create(:user, roles: [:administrator]) }
|
||||||
|
|
||||||
|
describe "#index" do
|
||||||
|
subject { get :index }
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "renders the index template" do
|
||||||
|
subject
|
||||||
|
expect(response).to render_template(:index)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "no announcements" do
|
||||||
|
it "@announcements is empty" do
|
||||||
|
subject
|
||||||
|
expect(assigns(:announcements)).to be_blank
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "one announcement" do
|
||||||
|
let!(:announcement) { Announcement.create(content: "I am announcement", user: user, starts_at: Time.current, ends_at: Time.current + 2.days) }
|
||||||
|
|
||||||
|
it "includes the announcement in the @announcements assign" do
|
||||||
|
subject
|
||||||
|
expect(assigns(:announcements)).to include(announcement)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#new" do
|
||||||
|
subject { get :new }
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "renders the new template" do
|
||||||
|
subject
|
||||||
|
expect(response).to render_template(:new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#create" do
|
||||||
|
let :announcement_params do
|
||||||
|
{
|
||||||
|
announcement: {
|
||||||
|
content: "I like dogs!",
|
||||||
|
starts_at: Time.current,
|
||||||
|
ends_at: Time.current + 2.days
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { post :create, params: announcement_params }
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "creates an announcement" do
|
||||||
|
expect { subject }.to change { Announcement.count }.by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects to announcement#index" do
|
||||||
|
subject
|
||||||
|
expect(response).to redirect_to(:announcement_index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#edit" do
|
||||||
|
let! :announcement do
|
||||||
|
Announcement.create(content: "Dogs are pretty cool, I guess",
|
||||||
|
starts_at: Time.current + 3.days,
|
||||||
|
ends_at: Time.current + 10.days,
|
||||||
|
user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { get :edit, params: { id: announcement.id } }
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "renders the edit template" do
|
||||||
|
subject
|
||||||
|
expect(response).to render_template(:edit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#update" do
|
||||||
|
let :announcement_params do
|
||||||
|
{
|
||||||
|
content: "The trebuchet is the superior siege weapon"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let! :announcement do
|
||||||
|
Announcement.create(content: "Dogs are pretty cool, I guess",
|
||||||
|
starts_at: Time.current + 3.days,
|
||||||
|
ends_at: Time.current + 10.days,
|
||||||
|
user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject do
|
||||||
|
patch :update, params: {
|
||||||
|
id: announcement.id,
|
||||||
|
announcement: announcement_params
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "updates the announcement" do
|
||||||
|
subject
|
||||||
|
updated = Announcement.find announcement.id
|
||||||
|
expect(updated.content).to eq(announcement_params[:content])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects to announcement#index" do
|
||||||
|
subject
|
||||||
|
expect(response).to redirect_to(:announcement_index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#destroy" do
|
||||||
|
let! :announcement do
|
||||||
|
Announcement.create(content: "Dogs are pretty cool, I guess",
|
||||||
|
starts_at: Time.current + 3.days,
|
||||||
|
ends_at: Time.current + 10.days,
|
||||||
|
user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { delete :destroy, params: { id: announcement.id } }
|
||||||
|
|
||||||
|
context "user signed in" do
|
||||||
|
before(:each) { sign_in(user) }
|
||||||
|
|
||||||
|
it "deletes the announcement" do
|
||||||
|
expect { subject }.to change { Announcement.count }.by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects to announcement#index" do
|
||||||
|
subject
|
||||||
|
expect(response).to redirect_to(:announcement_index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
RSpec.describe(Announcement, type: :model) do
|
||||||
|
let!(:user) { FactoryBot.create :user }
|
||||||
|
let!(:me) do
|
||||||
|
Announcement.new(
|
||||||
|
content: "Raccoon",
|
||||||
|
starts_at: Time.current,
|
||||||
|
ends_at: Time.current + 1.day,
|
||||||
|
user: user
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#active?" do
|
||||||
|
it "returns true when the current time is between starts_at and ends_at" do
|
||||||
|
expect(me.active?).to be(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false when the current time is before starts_at" do
|
||||||
|
Timecop.freeze(me.starts_at - 1.second)
|
||||||
|
expect(me.active?).to be(false)
|
||||||
|
Timecop.return
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false when the current time is after ends_at" do
|
||||||
|
Timecop.freeze(me.ends_at)
|
||||||
|
expect(me.active?).to be(false)
|
||||||
|
Timecop.return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#link_present?" do
|
||||||
|
it "returns true if a link is present" do
|
||||||
|
me.link_text = "Very good dogs"
|
||||||
|
me.link_href = "https://www.reddit.com/r/rarepuppers/"
|
||||||
|
expect(me.link_present?).to be(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if a link is not present" do
|
||||||
|
me.link_text = nil
|
||||||
|
me.link_href = nil
|
||||||
|
expect(me.link_present?).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue