Reorganize graphql specs

Back in commit c984e666f, we reorganized the code related to the GraphQL
API, but we didn't reorganize the tests.

So we're doing it now, since we're going to fix a potential issue and
add some tests for it.
This commit is contained in:
Javi Martín
2024-07-23 02:09:11 +02:00
parent b1b963f90a
commit ba558b1490
11 changed files with 334 additions and 310 deletions

View File

@@ -0,0 +1,34 @@
require "rails_helper"
describe Types::BudgetType do
describe "#investment" do
it "does not include hidden comments" do
budget = create(:budget)
investment = create(:budget_investment, budget: budget)
create(:comment, commentable: investment, body: "Visible")
create(:comment, :hidden, commentable: investment, body: "Hidden")
query = <<~GRAPHQL
{
budget(id: #{budget.id}) {
investment(id: #{investment.id}) {
comments {
edges {
node {
body
}
}
}
}
}
}
GRAPHQL
response = execute(query)
received_bodies = extract_fields(response, "budget.investment.comments", "body")
expect(received_bodies).to eq ["Visible"]
end
end
end

View File

@@ -0,0 +1,23 @@
require "rails_helper"
describe Types::CommentType do
it "does not link author if public activity is set to false" do
create(:user, :with_comment, username: "public", public_activity: true)
create(:user, :with_comment, username: "private", public_activity: false)
response = execute("{ comments { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "comments", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:comment, created_at: created_at)
response = execute("{ comments { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "comments", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
end

View File

@@ -0,0 +1,36 @@
require "rails_helper"
describe Types::DebateType do
it "does not link author if public activity is set to false" do
create(:user, :with_debate, username: "public", public_activity: true)
create(:user, :with_debate, username: "private", public_activity: false)
response = execute("{ debates { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "debates", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:debate, created_at: created_at)
response = execute("{ debates { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "debates", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only returns tags with kind nil or category" do
create(:tag, name: "Parks")
create(:tag, :category, name: "Health")
create(:tag, name: "Admin tag", kind: "admin")
debate = create(:debate, tag_list: "Parks, Health, Admin tag")
response = execute("{ debate(id: #{debate.id}) { tags { edges { node { name } } } } }")
received_tags = dig(response, "data.debate.tags.edges").map { |node| node["node"]["name"] }
expect(received_tags).to match_array ["Parks", "Health"]
end
end

View File

@@ -0,0 +1,11 @@
require "rails_helper"
describe Types::MilestoneType do
it "formats publication date like in view" do
milestone = create(:milestone, publication_date: Time.zone.parse("2024-07-02 11:45:17"))
response = execute("{ milestone(id: #{milestone.id}) { id publication_date } }")
received_publication_date = dig(response, "data.milestone.publication_date")
expect(received_publication_date).to eq "2024-07-02"
end
end

View File

@@ -0,0 +1,26 @@
require "rails_helper"
describe Types::ProposalNotificationType do
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:proposal_notification, created_at: created_at)
response = execute("{ proposal_notifications { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "proposal_notifications", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only links proposal if public" do
visible_proposal = create(:proposal, title: "Visible")
hidden_proposal = create(:proposal, :hidden, title: "Hidden")
create(:proposal_notification, proposal: visible_proposal)
create(:proposal_notification, proposal: hidden_proposal)
response = execute("{ proposal_notifications { edges { node { proposal { title } } } } }")
received_proposals = extract_fields(response, "proposal_notifications", "proposal.title")
expect(received_proposals).to match_array ["Visible"]
end
end

View File

@@ -0,0 +1,46 @@
require "rails_helper"
describe Types::ProposalType do
it "does not link author if public activity is set to false" do
create(:user, :with_proposal, username: "public", public_activity: true)
create(:user, :with_proposal, username: "private", public_activity: false)
response = execute("{ proposals { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "proposals", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:proposal, created_at: created_at)
response = execute("{ proposals { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "proposals", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only returns tags with kind nil or category" do
create(:tag, name: "Parks")
create(:tag, :category, name: "Health")
create(:tag, name: "Admin tag", kind: "admin")
proposal = create(:proposal, tag_list: "Parks, Health, Admin tag")
response = execute("{ proposal(id: #{proposal.id}) { tags { edges { node { name } } } } }")
received_tags = dig(response, "data.proposal.tags.edges").map { |node| node["node"]["name"] }
expect(received_tags).to match_array ["Parks", "Health"]
end
it "returns nested votes for a proposal" do
proposal = create(:proposal, voters: [create(:user), create(:user)])
response = execute("{ proposal(id: #{proposal.id}) " \
"{ votes_for { edges { node { public_created_at } } } } }")
votes = response["data"]["proposal"]["votes_for"]["edges"]
expect(votes.count).to eq(2)
end
end

View File

@@ -1,36 +1,6 @@
require "rails_helper" require "rails_helper"
def execute(query_string, context = {}, variables = {}) describe Types::QueryType do
ConsulSchema.execute(query_string, context: context, variables: variables)
end
def dig(response, path)
response.dig(*path.split("."))
end
def hidden_field?(response, field_name)
data_is_empty = response["data"].nil?
error_message = /Field '#{field_name}' doesn't exist on type '[[:alnum:]]*'/
error_is_present = ((response["errors"].first["message"] =~ error_message) == 0)
data_is_empty && error_is_present
end
def extract_fields(response, collection_name, field_chain)
fields = field_chain.split(".")
dig(response, "data.#{collection_name}.edges").map do |node|
begin
if fields.size > 1
node["node"][fields.first][fields.second]
else
node["node"][fields.first]
end
rescue NoMethodError
end
end.compact
end
describe "Consul Schema" do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:proposal) { create(:proposal, author: user) } let(:proposal) { create(:proposal, author: user) }
@@ -94,175 +64,7 @@ describe "Consul Schema" do
expect(hidden_field?(response, "encrypted_password")).to be_truthy expect(hidden_field?(response, "encrypted_password")).to be_truthy
end end
describe "Users" do describe "#comments" do
let(:user) { create(:user, public_activity: false) }
it "does not link debates if activity is not public" do
create(:debate, author: user)
response = execute("{ user(id: #{user.id}) { public_debates { edges { node { title } } } } }")
received_debates = dig(response, "data.user.public_debates.edges")
expect(received_debates).to eq []
end
it "does not link proposals if activity is not public" do
create(:proposal, author: user)
response = execute("{ user(id: #{user.id}) { public_proposals { edges { node { title } } } } }")
received_proposals = dig(response, "data.user.public_proposals.edges")
expect(received_proposals).to eq []
end
it "does not link comments if activity is not public" do
create(:comment, author: user)
response = execute("{ user(id: #{user.id}) { public_comments { edges { node { body } } } } }")
received_comments = dig(response, "data.user.public_comments.edges")
expect(received_comments).to eq []
end
end
describe "Proposals" do
it "does not include hidden proposals" do
create(:proposal, title: "Visible")
create(:proposal, :hidden, title: "Hidden")
response = execute("{ proposals { edges { node { title } } } }")
received_titles = extract_fields(response, "proposals", "title")
expect(received_titles).to match_array ["Visible"]
end
it "includes proposals of authors even if public activity is set to false" do
visible_author = create(:user, public_activity: true)
hidden_author = create(:user, public_activity: false)
visible_proposal = create(:proposal, author: visible_author)
hidden_proposal = create(:proposal, author: hidden_author)
response = execute("{ proposals { edges { node { title } } } }")
received_titles = extract_fields(response, "proposals", "title")
expect(received_titles).to match_array [visible_proposal.title, hidden_proposal.title]
end
it "does not link author if public activity is set to false" do
create(:user, :with_proposal, username: "public", public_activity: true)
create(:user, :with_proposal, username: "private", public_activity: false)
response = execute("{ proposals { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "proposals", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:proposal, created_at: created_at)
response = execute("{ proposals { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "proposals", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only retruns tags with kind nil or category" do
create(:tag, name: "Parks")
create(:tag, :category, name: "Health")
create(:tag, name: "Admin tag", kind: "admin")
proposal = create(:proposal, tag_list: "Parks, Health, Admin tag")
response = execute("{ proposal(id: #{proposal.id}) { tags { edges { node { name } } } } }")
received_tags = dig(response, "data.proposal.tags.edges").map { |node| node["node"]["name"] }
expect(received_tags).to match_array ["Parks", "Health"]
end
it "returns nested votes for a proposal" do
proposal = create(:proposal, voters: [create(:user), create(:user)])
response = execute("{ proposal(id: #{proposal.id}) " \
"{ votes_for { edges { node { public_created_at } } } } }")
votes = response["data"]["proposal"]["votes_for"]["edges"]
expect(votes.count).to eq(2)
end
end
describe "Budgets" do
it "does not include unpublished budgets" do
create(:budget, :drafting, name: "Draft")
response = execute("{ budgets { edges { node { name } } } }")
received_names = extract_fields(response, "budgets", "name")
expect(received_names).to eq []
end
end
describe "Debates" do
it "does not include hidden debates" do
create(:debate, title: "Visible")
create(:debate, :hidden, title: "Hidden")
response = execute("{ debates { edges { node { title } } } }")
received_titles = extract_fields(response, "debates", "title")
expect(received_titles).to match_array ["Visible"]
end
it "includes debates of authors even if public activity is set to false" do
visible_author = create(:user, public_activity: true)
hidden_author = create(:user, public_activity: false)
visible_debate = create(:debate, author: visible_author)
hidden_debate = create(:debate, author: hidden_author)
response = execute("{ debates { edges { node { title } } } }")
received_titles = extract_fields(response, "debates", "title")
expect(received_titles).to match_array [visible_debate.title, hidden_debate.title]
end
it "does not link author if public activity is set to false" do
create(:user, :with_debate, username: "public", public_activity: true)
create(:user, :with_debate, username: "private", public_activity: false)
response = execute("{ debates { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "debates", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:debate, created_at: created_at)
response = execute("{ debates { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "debates", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only retruns tags with kind nil or category" do
create(:tag, name: "Parks")
create(:tag, :category, name: "Health")
create(:tag, name: "Admin tag", kind: "admin")
debate = create(:debate, tag_list: "Parks, Health, Admin tag")
response = execute("{ debate(id: #{debate.id}) { tags { edges { node { name } } } } }")
received_tags = dig(response, "data.debate.tags.edges").map { |node| node["node"]["name"] }
expect(received_tags).to match_array ["Parks", "Health"]
end
end
describe "Comments" do
it "only returns comments from proposals, debates, polls and Budget::Investment" do it "only returns comments from proposals, debates, polls and Budget::Investment" do
create(:comment, commentable: create(:proposal)) create(:comment, commentable: create(:proposal))
create(:comment, commentable: create(:debate)) create(:comment, commentable: create(:debate))
@@ -289,16 +91,6 @@ describe "Consul Schema" do
expect(received_comments).to match_array [visible_comment.body, hidden_comment.body] expect(received_comments).to match_array [visible_comment.body, hidden_comment.body]
end end
it "does not link author if public activity is set to false" do
create(:user, :with_comment, username: "public", public_activity: true)
create(:user, :with_comment, username: "private", public_activity: false)
response = execute("{ comments { edges { node { public_author { username } } } } }")
received_authors = extract_fields(response, "comments", "public_author.username")
expect(received_authors).to match_array ["public"]
end
it "does not include hidden comments" do it "does not include hidden comments" do
create(:comment, body: "Visible") create(:comment, body: "Visible")
create(:comment, :hidden, body: "Hidden") create(:comment, :hidden, body: "Hidden")
@@ -401,27 +193,6 @@ describe "Consul Schema" do
expect(received_comments).not_to include(not_public_investment_comment.body) expect(received_comments).not_to include(not_public_investment_comment.body)
end end
it "only links public comments" do
user = create(:administrator).user
create(:comment, author: user, body: "Public")
create(:budget_investment_comment, author: user, valuation: true, body: "Valuation")
response = execute("{ user(id: #{user.id}) { public_comments { edges { node { body } } } } }")
received_comments = dig(response, "data.user.public_comments.edges")
expect(received_comments).to eq [{ "node" => { "body" => "Public" }}]
end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:comment, created_at: created_at)
response = execute("{ comments { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "comments", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "does not include valuation comments" do it "does not include valuation comments" do
create(:comment, body: "Regular comment") create(:comment, body: "Regular comment")
create(:comment, :valuation, body: "Valuation comment") create(:comment, :valuation, body: "Valuation comment")
@@ -433,7 +204,68 @@ describe "Consul Schema" do
end end
end end
describe "Geozones" do describe "#budgets" do
it "does not include unpublished budgets" do
create(:budget, :drafting, name: "Draft")
response = execute("{ budgets { edges { node { name } } } }")
received_names = extract_fields(response, "budgets", "name")
expect(received_names).to eq []
end
end
describe "#debates" do
it "does not include hidden debates" do
create(:debate, title: "Visible")
create(:debate, :hidden, title: "Hidden")
response = execute("{ debates { edges { node { title } } } }")
received_titles = extract_fields(response, "debates", "title")
expect(received_titles).to match_array ["Visible"]
end
it "includes debates of authors even if public activity is set to false" do
visible_author = create(:user, public_activity: true)
hidden_author = create(:user, public_activity: false)
visible_debate = create(:debate, author: visible_author)
hidden_debate = create(:debate, author: hidden_author)
response = execute("{ debates { edges { node { title } } } }")
received_titles = extract_fields(response, "debates", "title")
expect(received_titles).to match_array [visible_debate.title, hidden_debate.title]
end
end
describe "#proposals" do
it "does not include hidden proposals" do
create(:proposal, title: "Visible")
create(:proposal, :hidden, title: "Hidden")
response = execute("{ proposals { edges { node { title } } } }")
received_titles = extract_fields(response, "proposals", "title")
expect(received_titles).to match_array ["Visible"]
end
it "includes proposals of authors even if public activity is set to false" do
visible_author = create(:user, public_activity: true)
hidden_author = create(:user, public_activity: false)
visible_proposal = create(:proposal, author: visible_author)
hidden_proposal = create(:proposal, author: hidden_author)
response = execute("{ proposals { edges { node { title } } } }")
received_titles = extract_fields(response, "proposals", "title")
expect(received_titles).to match_array [visible_proposal.title, hidden_proposal.title]
end
end
describe "#geozones" do
it "returns geozones" do it "returns geozones" do
geozone_names = [create(:geozone), create(:geozone)].map(&:name) geozone_names = [create(:geozone), create(:geozone)].map(&:name)
@@ -444,7 +276,7 @@ describe "Consul Schema" do
end end
end end
describe "Proposal notifications" do describe "#proposal_notifications" do
it "does not include proposal notifications for hidden proposals" do it "does not include proposal notifications for hidden proposals" do
visible_proposal = create(:proposal) visible_proposal = create(:proposal)
hidden_proposal = create(:proposal, :hidden) hidden_proposal = create(:proposal, :hidden)
@@ -467,32 +299,9 @@ describe "Consul Schema" do
expect(received_notifications).not_to include(not_public_proposal_notification.title) expect(received_notifications).not_to include(not_public_proposal_notification.title)
end end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:proposal_notification, created_at: created_at)
response = execute("{ proposal_notifications { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "proposal_notifications", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
it "only links proposal if public" do
visible_proposal = create(:proposal, title: "Visible")
hidden_proposal = create(:proposal, :hidden, title: "Hidden")
create(:proposal_notification, proposal: visible_proposal)
create(:proposal_notification, proposal: hidden_proposal)
response = execute("{ proposal_notifications { edges { node { proposal { title } } } } }")
received_proposals = extract_fields(response, "proposal_notifications", "proposal.title")
expect(received_proposals).to match_array ["Visible"]
end
end end
describe "Tags" do describe "#tags" do
it "only display tags with kind nil or category" do it "only display tags with kind nil or category" do
create(:tag, name: "Parks") create(:tag, name: "Parks")
create(:tag, :category, name: "Health") create(:tag, :category, name: "Health")
@@ -522,7 +331,7 @@ describe "Consul Schema" do
expect(received_tags).to match_array ["Health", "health"] expect(received_tags).to match_array ["Health", "health"]
end end
it "works OK when both tags are present for proposals" do it "works OK when both tags are present for debates" do
create(:debate).tags = [uppercase_tag] create(:debate).tags = [uppercase_tag]
create(:debate).tags = [lowercase_tag] create(:debate).tags = [lowercase_tag]
@@ -564,7 +373,7 @@ describe "Consul Schema" do
end end
end end
describe "Votes" do describe "#votes" do
it "only returns votes from proposals, debates and comments" do it "only returns votes from proposals, debates and comments" do
create(:proposal, voters: [create(:user)]) create(:proposal, voters: [create(:user)])
create(:debate, voters: [create(:user)]) create(:debate, voters: [create(:user)])
@@ -662,56 +471,5 @@ describe "Consul Schema" do
expect(received_votables).not_to include(not_public_comment.id) expect(received_votables).not_to include(not_public_comment.id)
end end
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:vote, created_at: created_at)
response = execute("{ votes { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "votes", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
end
describe "Milestone" do
it "formats publication date like in view" do
milestone = create(:milestone, publication_date: Time.zone.parse("2024-07-02 11:45:17"))
response = execute("{ milestone(id: #{milestone.id}) { id publication_date } }")
received_publication_date = dig(response, "data.milestone.publication_date")
expect(received_publication_date).to eq "2024-07-02"
end
end
describe "Budget investment" do
it "does not include hidden comments" do
budget = create(:budget)
investment = create(:budget_investment, budget: budget)
create(:comment, commentable: investment, body: "Visible")
create(:comment, :hidden, commentable: investment, body: "Hidden")
query = <<~GRAPHQL
{
budget(id: #{budget.id}) {
investment(id: #{investment.id}) {
comments {
edges {
node {
body
}
}
}
}
}
}
GRAPHQL
response = execute(query)
received_bodies = extract_fields(response, "budget.investment.comments", "body")
expect(received_bodies).to eq ["Visible"]
end
end end
end end

View File

@@ -0,0 +1,45 @@
require "rails_helper"
describe Types::UserType do
context "activity is not public" do
let(:user) { create(:user, public_activity: false) }
it "does not link debates" do
create(:debate, author: user)
response = execute("{ user(id: #{user.id}) { public_debates { edges { node { title } } } } }")
received_debates = dig(response, "data.user.public_debates.edges")
expect(received_debates).to eq []
end
it "does not link proposals" do
create(:proposal, author: user)
response = execute("{ user(id: #{user.id}) { public_proposals { edges { node { title } } } } }")
received_proposals = dig(response, "data.user.public_proposals.edges")
expect(received_proposals).to eq []
end
it "does not link comments" do
create(:comment, author: user)
response = execute("{ user(id: #{user.id}) { public_comments { edges { node { body } } } } }")
received_comments = dig(response, "data.user.public_comments.edges")
expect(received_comments).to eq []
end
end
it "only links public comments" do
user = create(:administrator).user
create(:comment, author: user, body: "Public")
create(:budget_investment_comment, author: user, valuation: true, body: "Valuation")
response = execute("{ user(id: #{user.id}) { public_comments { edges { node { body } } } } }")
received_comments = dig(response, "data.user.public_comments.edges")
expect(received_comments).to eq [{ "node" => { "body" => "Public" }}]
end
end

View File

@@ -0,0 +1,13 @@
require "rails_helper"
describe Types::VoteType do
it "only returns date and hour for created_at" do
created_at = Time.zone.parse("2017-12-31 9:30:15")
create(:vote, created_at: created_at)
response = execute("{ votes { edges { node { public_created_at } } } }")
received_timestamps = extract_fields(response, "votes", "public_created_at")
expect(Time.zone.parse(received_timestamps.first)).to eq Time.zone.parse("2017-12-31 9:00:00")
end
end

View File

@@ -7,6 +7,7 @@ module CommonActions
include Debates include Debates
include Documents include Documents
include Emails include Emails
include GraphQLAPI
include Images include Images
include Maps include Maps
include Notifications include Notifications

View File

@@ -0,0 +1,31 @@
module GraphQLAPI
def execute(query_string, context = {}, variables = {})
ConsulSchema.execute(query_string, context: context, variables: variables)
end
def dig(response, path)
response.dig(*path.split("."))
end
def hidden_field?(response, field_name)
data_is_empty = response["data"].nil?
error_message = /Field '#{field_name}' doesn't exist on type '[[:alnum:]]*'/
error_is_present = ((response["errors"].first["message"] =~ error_message) == 0)
data_is_empty && error_is_present
end
def extract_fields(response, collection_name, field_chain)
fields = field_chain.split(".")
dig(response, "data.#{collection_name}.edges").map do |node|
begin
if fields.size > 1
node["node"][fields.first][fields.second]
else
node["node"][fields.first]
end
rescue NoMethodError
end
end.compact
end
end