More test work
This commit is contained in:
parent
6ce635d5d3
commit
7fef0353f2
6 changed files with 210 additions and 57 deletions
|
@ -37,7 +37,7 @@ Metrics/BlockNesting:
|
||||||
# Offense count: 60
|
# Offense count: 60
|
||||||
# Configuration parameters: CountComments.
|
# Configuration parameters: CountComments.
|
||||||
Metrics/ClassLength:
|
Metrics/ClassLength:
|
||||||
Max: 1552
|
Max: 1628
|
||||||
|
|
||||||
# Offense count: 68
|
# Offense count: 68
|
||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
|
|
|
@ -254,7 +254,7 @@ class ChangesetController < ApplicationController
|
||||||
# list edits (open changesets) in reverse chronological order
|
# list edits (open changesets) in reverse chronological order
|
||||||
def list
|
def list
|
||||||
if request.format == :atom && params[:max_id]
|
if request.format == :atom && params[:max_id]
|
||||||
redirect_to params.merge(:max_id => nil), :status => :moved_permanently
|
redirect_to url_for(params.merge(:max_id => nil)), :status => :moved_permanently
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ class ChangesetController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (params[:friends] || params[:nearby]) && !@user && request.format == :html
|
if (params[:friends] || params[:nearby]) && !@user
|
||||||
require_user
|
require_user
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,11 +38,6 @@ class OauthController < ApplicationController
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def oauth1_authorize
|
def oauth1_authorize
|
||||||
unless @token
|
|
||||||
render :action => "authorize_failure"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if @token.invalidated?
|
if @token.invalidated?
|
||||||
@message = t "oauth.oauthorize_failure.invalid"
|
@message = t "oauth.oauthorize_failure.invalid"
|
||||||
render :action => "authorize_failure"
|
render :action => "authorize_failure"
|
||||||
|
|
|
@ -120,8 +120,8 @@ OpenStreetMap::Application.routes.draw do
|
||||||
match "/user/:display_name/history" => "changeset#list", :via => :get
|
match "/user/:display_name/history" => "changeset#list", :via => :get
|
||||||
match "/user/:display_name/history/feed" => "changeset#feed", :via => :get, :defaults => { :format => :atom }
|
match "/user/:display_name/history/feed" => "changeset#feed", :via => :get, :defaults => { :format => :atom }
|
||||||
match "/user/:display_name/notes" => "notes#mine", :via => :get
|
match "/user/:display_name/notes" => "notes#mine", :via => :get
|
||||||
match "/history/friends" => "changeset#list", :via => :get, :friends => true, :as => "friend_changesets"
|
match "/history/friends" => "changeset#list", :via => :get, :friends => true, :as => "friend_changesets", :defaults => { :format => :html }
|
||||||
match "/history/nearby" => "changeset#list", :via => :get, :nearby => true, :as => "nearby_changesets"
|
match "/history/nearby" => "changeset#list", :via => :get, :nearby => true, :as => "nearby_changesets", :defaults => { :format => :html }
|
||||||
|
|
||||||
get "/browse/way/:id", :to => redirect(:path => "/way/%{id}")
|
get "/browse/way/:id", :to => redirect(:path => "/way/%{id}")
|
||||||
get "/browse/way/:id/history", :to => redirect(:path => "/way/%{id}/history")
|
get "/browse/way/:id/history", :to => redirect(:path => "/way/%{id}/history")
|
||||||
|
|
|
@ -3,7 +3,7 @@ require "changeset_controller"
|
||||||
|
|
||||||
class ChangesetControllerTest < ActionController::TestCase
|
class ChangesetControllerTest < ActionController::TestCase
|
||||||
api_fixtures
|
api_fixtures
|
||||||
fixtures :changeset_comments, :changesets_subscribers
|
fixtures :friends, :changeset_comments, :changesets_subscribers
|
||||||
|
|
||||||
##
|
##
|
||||||
# test all routes which lead to this controller
|
# test all routes which lead to this controller
|
||||||
|
@ -74,11 +74,11 @@ class ChangesetControllerTest < ActionController::TestCase
|
||||||
)
|
)
|
||||||
assert_routing(
|
assert_routing(
|
||||||
{ :path => "/history/friends", :method => :get },
|
{ :path => "/history/friends", :method => :get },
|
||||||
{ :controller => "changeset", :action => "list", :friends => true }
|
{ :controller => "changeset", :action => "list", :friends => true, :format => :html }
|
||||||
)
|
)
|
||||||
assert_routing(
|
assert_routing(
|
||||||
{ :path => "/history/nearby", :method => :get },
|
{ :path => "/history/nearby", :method => :get },
|
||||||
{ :controller => "changeset", :action => "list", :nearby => true }
|
{ :controller => "changeset", :action => "list", :nearby => true, :format => :html }
|
||||||
)
|
)
|
||||||
assert_routing(
|
assert_routing(
|
||||||
{ :path => "/history", :method => :get },
|
{ :path => "/history", :method => :get },
|
||||||
|
@ -1760,7 +1760,7 @@ EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# This should display the last 20 changesets closed.
|
# This should display the last 20 changesets closed
|
||||||
def test_list
|
def test_list
|
||||||
get :list, :format => "html"
|
get :list, :format => "html"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
@ -1768,25 +1768,15 @@ EOF
|
||||||
assert_template :layout => "map"
|
assert_template :layout => "map"
|
||||||
assert_select "h2", :text => "Changesets", :count => 1
|
assert_select "h2", :text => "Changesets", :count => 1
|
||||||
|
|
||||||
get :list, :format => "html", :list => "1", :bbox => "-180,-90,90,180"
|
xhr :get, :list, :format => "html", :list => "1"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "list"
|
assert_template "list"
|
||||||
|
|
||||||
changesets = Changeset
|
check_list_result(Changeset.all)
|
||||||
.where("num_changes > 0 and min_lon is not null")
|
|
||||||
.order(:created_at => :desc)
|
|
||||||
.limit(20)
|
|
||||||
assert changesets.size <= 20
|
|
||||||
|
|
||||||
# Now check that all 20 (or however many were returned) changesets are in the html
|
|
||||||
assert_select "li", :count => changesets.size
|
|
||||||
changesets.each do |_changeset|
|
|
||||||
# FIXME: this test needs rewriting - test for table contents
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# This should display the last 20 changesets closed.
|
# This should display the last 20 changesets closed
|
||||||
def test_list_xhr
|
def test_list_xhr
|
||||||
xhr :get, :list, :format => "html"
|
xhr :get, :list, :format => "html"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
@ -1794,31 +1784,59 @@ EOF
|
||||||
assert_template :layout => "xhr"
|
assert_template :layout => "xhr"
|
||||||
assert_select "h2", :text => "Changesets", :count => 1
|
assert_select "h2", :text => "Changesets", :count => 1
|
||||||
|
|
||||||
get :list, :format => "html", :list => "1", :bbox => "-180,-90,90,180"
|
xhr :get, :list, :format => "html", :list => "1"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "list"
|
assert_template "list"
|
||||||
|
|
||||||
changesets = Changeset
|
check_list_result(Changeset.all)
|
||||||
.where("num_changes > 0 and min_lon is not null")
|
end
|
||||||
.order(:created_at => :desc)
|
|
||||||
.limit(20)
|
|
||||||
assert changesets.size <= 20
|
|
||||||
|
|
||||||
# Now check that all 20 (or however many were returned) changesets are in the html
|
##
|
||||||
assert_select "li", :count => changesets.size
|
# This should display the last 20 changesets closed in a specific area
|
||||||
changesets.each do |_changeset|
|
def test_list_bbox
|
||||||
# FIXME: this test needs rewriting - test for table contents
|
get :list, :format => "html", :bbox => "4.5,4.5,5.5,5.5"
|
||||||
end
|
assert_response :success
|
||||||
|
assert_template "history"
|
||||||
|
assert_template :layout => "map"
|
||||||
|
assert_select "h2", :text => "Changesets", :count => 1
|
||||||
|
|
||||||
|
xhr :get, :list, :format => "html", :bbox => "4.5,4.5,5.5,5.5", :list => "1"
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
|
||||||
|
check_list_result(Changeset.where("min_lon < 55000000 and max_lon > 45000000 and min_lat < 55000000 and max_lat > 45000000"))
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Checks the display of the user changesets listing
|
# Checks the display of the user changesets listing
|
||||||
def test_list_user
|
def test_list_user
|
||||||
user = users(:public_user)
|
user = users(:public_user)
|
||||||
|
|
||||||
get :list, :format => "html", :display_name => user.display_name
|
get :list, :format => "html", :display_name => user.display_name
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "history"
|
assert_template "history"
|
||||||
# FIXME: need to add more checks to see which if edits are actually shown if your data is public
|
|
||||||
|
get :list, :format => "html", :display_name => user.display_name, :list => "1"
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
|
||||||
|
check_list_result(user.changesets)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks the display of the user changesets listing for a private user
|
||||||
|
def test_list_private_user
|
||||||
|
user = users(:normal_user)
|
||||||
|
|
||||||
|
get :list, :format => "html", :display_name => user.display_name
|
||||||
|
assert_response :success
|
||||||
|
assert_template "history"
|
||||||
|
|
||||||
|
get :list, :format => "html", :display_name => user.display_name, :list => "1"
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
|
||||||
|
check_list_result(Changeset.none)
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -1827,33 +1845,89 @@ EOF
|
||||||
get :list, :format => "html", :display_name => "Some random user"
|
get :list, :format => "html", :display_name => "Some random user"
|
||||||
assert_response :not_found
|
assert_response :not_found
|
||||||
assert_template "user/no_such_user"
|
assert_template "user/no_such_user"
|
||||||
|
|
||||||
|
get :list, :format => "html", :display_name => "Some random user", :list => "1"
|
||||||
|
assert_response :not_found
|
||||||
|
assert_template "user/no_such_user"
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# This should display the last 20 changesets closed.
|
# Checks the display of the friends changesets listing
|
||||||
def test_feed
|
def test_list_friends
|
||||||
changesets = Changeset.where("num_changes > 0").order(:created_at => :desc).limit(20)
|
user = users(:normal_user)
|
||||||
assert changesets.size <= 20
|
|
||||||
get :feed, :format => "atom"
|
get :list, :friends => true
|
||||||
|
assert_response :redirect
|
||||||
|
assert_redirected_to :controller => :user, :action => :login, :referer => friend_changesets_path
|
||||||
|
|
||||||
|
session[:user] = user.id
|
||||||
|
|
||||||
|
get :list, :friends => true
|
||||||
|
assert_response :success
|
||||||
|
assert_template "history"
|
||||||
|
|
||||||
|
get :list, :friends => true, :list => "1"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "list"
|
assert_template "list"
|
||||||
# Now check that all 20 (or however many were returned) changesets are in the html
|
|
||||||
assert_select "feed", :count => 1
|
check_list_result(Changeset.where(:user => user.friend_users.identifiable))
|
||||||
assert_select "entry", :count => changesets.size
|
end
|
||||||
changesets.each do |_changeset|
|
|
||||||
# FIXME: this test needs rewriting - test for feed contents
|
##
|
||||||
end
|
# Checks the display of the nearby user changesets listing
|
||||||
|
def test_list_nearby
|
||||||
|
user = users(:normal_user)
|
||||||
|
|
||||||
|
get :list, :nearby => true
|
||||||
|
assert_response :redirect
|
||||||
|
assert_redirected_to :controller => :user, :action => :login, :referer => nearby_changesets_path
|
||||||
|
|
||||||
|
session[:user] = user.id
|
||||||
|
|
||||||
|
get :list, :nearby => true
|
||||||
|
assert_response :success
|
||||||
|
assert_template "history"
|
||||||
|
|
||||||
|
get :list, :nearby => true, :list => "1"
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
|
||||||
|
check_list_result(Changeset.where(:user => user.nearby))
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# This should display the last 20 changesets closed
|
||||||
|
def test_feed
|
||||||
|
get :feed, :format => :atom
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
assert_equal "application/atom+xml", response.content_type
|
||||||
|
|
||||||
|
check_feed_result(Changeset.all)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# This should display the last 20 changesets closed in a specific area
|
||||||
|
def test_feed_bbox
|
||||||
|
get :feed, :format => :atom, :bbox => "4.5,4.5,5.5,5.5"
|
||||||
|
assert_response :success
|
||||||
|
assert_template "list"
|
||||||
|
assert_equal "application/atom+xml", response.content_type
|
||||||
|
|
||||||
|
check_feed_result(Changeset.where("min_lon < 55000000 and max_lon > 45000000 and min_lat < 55000000 and max_lat > 45000000"))
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Checks the display of the user changesets feed
|
# Checks the display of the user changesets feed
|
||||||
def test_feed_user
|
def test_feed_user
|
||||||
user = users(:public_user)
|
user = users(:public_user)
|
||||||
get :feed, :format => "atom", :display_name => user.display_name
|
|
||||||
|
get :feed, :format => :atom, :display_name => user.display_name
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "list"
|
assert_template "list"
|
||||||
assert_equal "application/atom+xml", response.content_type
|
assert_equal "application/atom+xml", response.content_type
|
||||||
# FIXME: need to add more checks to see which if edits are actually shown if your data is public
|
|
||||||
|
check_feed_result(user.changesets)
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -1863,6 +1937,14 @@ EOF
|
||||||
assert_response :not_found
|
assert_response :not_found
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Check that we can't request later pages of the changesets feed
|
||||||
|
def test_feed_max_id
|
||||||
|
get :feed, :format => "atom", :max_id => 100
|
||||||
|
assert_response :redirect
|
||||||
|
assert_redirected_to :action => :feed
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# check that the changeset download for a changeset with a redacted
|
# check that the changeset download for a changeset with a redacted
|
||||||
# element in it doesn't contain that element.
|
# element in it doesn't contain that element.
|
||||||
|
@ -2149,9 +2231,7 @@ EOF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#------------------------------------------------------------
|
private
|
||||||
# utility functions
|
|
||||||
#------------------------------------------------------------
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# boilerplate for checking that certain changesets exist in the
|
# boilerplate for checking that certain changesets exist in the
|
||||||
|
@ -2195,4 +2275,38 @@ EOF
|
||||||
xml.find("//osm/way").first[name] = value.to_s
|
xml.find("//osm/way").first[name] = value.to_s
|
||||||
xml
|
xml
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# check the result of a list
|
||||||
|
def check_list_result(changesets)
|
||||||
|
changesets = changesets.where("num_changes > 0")
|
||||||
|
.order(:created_at => :desc)
|
||||||
|
.limit(20)
|
||||||
|
assert changesets.size <= 20
|
||||||
|
|
||||||
|
assert_select "ol.changesets", :count => [changesets.size, 1].min do
|
||||||
|
assert_select "li", :count => changesets.size
|
||||||
|
|
||||||
|
changesets.each do |changeset|
|
||||||
|
assert_select "li#changeset_#{changeset.id}", :count => 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# check the result of a feed
|
||||||
|
def check_feed_result(changesets)
|
||||||
|
changesets = changesets.where("num_changes > 0")
|
||||||
|
.order(:created_at => :desc)
|
||||||
|
.limit(20)
|
||||||
|
assert changesets.size <= 20
|
||||||
|
|
||||||
|
assert_select "feed", :count => [changesets.size, 1].min do
|
||||||
|
assert_select "entry", :count => changesets.size
|
||||||
|
|
||||||
|
changesets.each do |changeset|
|
||||||
|
assert_select "entry > id", changeset_url(:id => changeset.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
|
|
||||||
oauth10_without_callback(client)
|
oauth10_without_callback(client)
|
||||||
oauth10_with_callback(client, "http://another.web.app.org/callback")
|
oauth10_with_callback(client, "http://another.web.app.org/callback")
|
||||||
|
oauth10_refused(client)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_oauth10_desktop_app
|
def test_oauth10_desktop_app
|
||||||
|
@ -23,6 +24,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|
||||||
oauth10_without_callback(client)
|
oauth10_without_callback(client)
|
||||||
|
oauth10_refused(client)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_oauth10a_web_app
|
def test_oauth10a_web_app
|
||||||
|
@ -33,6 +35,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
|
|
||||||
oauth10a_without_callback(client)
|
oauth10a_without_callback(client)
|
||||||
oauth10a_with_callback(client, "http://another.web.app.org/callback")
|
oauth10a_with_callback(client, "http://another.web.app.org/callback")
|
||||||
|
oauth10a_refused(client)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_oauth10a_desktop_app
|
def test_oauth10a_desktop_app
|
||||||
|
@ -42,6 +45,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|
||||||
oauth10a_without_callback(client)
|
oauth10a_without_callback(client)
|
||||||
|
oauth10a_refused(client)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -57,7 +61,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_redirected_to "#{client.callback_url}?oauth_token=#{token.token}"
|
assert_redirected_to "#{client.callback_url}?oauth_token=#{token.token}"
|
||||||
else
|
else
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "authorize_success"
|
assert_template :authorize_success
|
||||||
end
|
end
|
||||||
token.reload
|
token.reload
|
||||||
assert_not_nil token.created_at
|
assert_not_nil token.created_at
|
||||||
|
@ -93,6 +97,26 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :unauthorized
|
assert_response :unauthorized
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def oauth10_refused(client)
|
||||||
|
token = get_request_token(client)
|
||||||
|
|
||||||
|
post "/oauth/authorize", :oauth_token => token.token
|
||||||
|
assert_response :success
|
||||||
|
assert_template :authorize_failure
|
||||||
|
assert_select "p", "You have denied application #{client.name} access to your account."
|
||||||
|
token.reload
|
||||||
|
assert_nil token.authorized_at
|
||||||
|
assert_not_nil token.invalidated_at
|
||||||
|
|
||||||
|
post "/oauth/authorize", :oauth_token => token.token
|
||||||
|
assert_response :success
|
||||||
|
assert_template :authorize_failure
|
||||||
|
assert_select "p", "The authorization token is not valid."
|
||||||
|
token.reload
|
||||||
|
assert_nil token.authorized_at
|
||||||
|
assert_not_nil token.invalidated_at
|
||||||
|
end
|
||||||
|
|
||||||
def oauth10_with_callback(client, callback_url)
|
def oauth10_with_callback(client, callback_url)
|
||||||
token = get_request_token(client)
|
token = get_request_token(client)
|
||||||
|
|
||||||
|
@ -147,7 +171,7 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_redirected_to "http://some.web.app.org/callback?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
|
assert_redirected_to "http://some.web.app.org/callback?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
|
||||||
else
|
else
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "authorize_success"
|
assert_template :authorize_success
|
||||||
m = response.body.match("<p>The verification code is ([A-Za-z0-9]+).</p>")
|
m = response.body.match("<p>The verification code is ([A-Za-z0-9]+).</p>")
|
||||||
assert_not_nil m
|
assert_not_nil m
|
||||||
verifier = m[1]
|
verifier = m[1]
|
||||||
|
@ -237,6 +261,26 @@ class OAuthTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :unauthorized
|
assert_response :unauthorized
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def oauth10a_refused(client)
|
||||||
|
token = get_request_token(client, :oauth_callback => "oob")
|
||||||
|
|
||||||
|
post "/oauth/authorize", :oauth_token => token.token
|
||||||
|
assert_response :success
|
||||||
|
assert_template :authorize_failure
|
||||||
|
assert_select "p", "You have denied application #{client.name} access to your account."
|
||||||
|
token.reload
|
||||||
|
assert_nil token.authorized_at
|
||||||
|
assert_not_nil token.invalidated_at
|
||||||
|
|
||||||
|
post "/oauth/authorize", :oauth_token => token.token
|
||||||
|
assert_response :success
|
||||||
|
assert_template :authorize_failure
|
||||||
|
assert_select "p", "The authorization token is not valid."
|
||||||
|
token.reload
|
||||||
|
assert_nil token.authorized_at
|
||||||
|
assert_not_nil token.invalidated_at
|
||||||
|
end
|
||||||
|
|
||||||
def get_request_token(client, options = {})
|
def get_request_token(client, options = {})
|
||||||
signed_get "/oauth/request_token", options.merge(:consumer => client)
|
signed_get "/oauth/request_token", options.merge(:consumer => client)
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue