spec: add base provider states for contract tests

refs QUIZ-4638

With a "base" provider state we can easily manage any number of
provider states from which all other provider states will
inherit.

Change-Id: Ic92dcb4b4649d334abdc64c622f252b5ec5825b6
Reviewed-on: https://gerrit.instructure.com/155564
Tested-by: Jenkins
Reviewed-by: Gentry Beckmann <gbeckmann@instructure.com>
Product-Review: Michael Hargiss <mhargiss@instructure.com>
QA-Review: Michael Hargiss <mhargiss@instructure.com>
This commit is contained in:
Michael Hargiss 2018-06-27 16:33:45 -06:00
parent f93a0149ed
commit 9e3de1c6ec
4 changed files with 254 additions and 20 deletions

View File

@ -22,26 +22,27 @@ require_relative '../pact_config'
require_relative '../../../spec_helper'
require_relative 'pact_setup'
require_relative 'proxy_app'
Dir[File.dirname(__FILE__) + "/provider_states_for_consumer/*.rb"].each {|f| require f }
require_relative 'provider_states_for_consumer'
Pact.service_provider PactConfig::Providers::CANVAS_LMS_API do
app { PactApiConsumerProxy.new }
pact_path = format(
'pacts/provider/%<provider>s/consumer/%<consumer>s',
provider: ERB::Util.url_encode(PactConfig::Providers::CANVAS_LMS_API),
consumer: ERB::Util.url_encode(PactConfig::Consumers::GENERIC_CONSUMER)
)
PactConfig::Consumers::ALL.each do |consumer|
pact_path = format(
'pacts/provider/%<provider>s/consumer/%<consumer>s',
provider: ERB::Util.url_encode(PactConfig::Providers::CANVAS_LMS_API),
consumer: ERB::Util.url_encode(consumer)
)
honours_pact_with PactConfig::Consumers::GENERIC_CONSUMER do
if PactConfig.jenkins_build? then
honours_pact_with consumer do
pact_uri PactConfig.pact_uri(pact_path: pact_path)
else
pact_uri 'pacts/generic_consumer-canvas_lms_api.json'
end
app_version PactConfig::Providers::CANVAS_API_VERSION
publish_verification_results true
if !PactConfig.jenkins_build? && consumer == 'Generic Consumer'
pact_uri 'pacts/generic_consumer-canvas_lms_api.json'
end
app_version PactConfig::Providers::CANVAS_API_VERSION
publish_verification_results true
end
end
end

View File

@ -0,0 +1,195 @@
#
# Copyright (C) 2018 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
Dir[File.dirname(__FILE__) + "/provider_states_for_consumer/*.rb"].each {|f| require f }
require 'spec/factories/course_factory'
require 'spec/factories/user_factory'
PactConfig::Consumers::ALL.each do |consumer|
Pact.provider_states_for consumer do
set_up do
Pact::Canvas.base_state = Pact::Canvas::BaseState.seed!
end
# The following states are provided by the set_up block above, thus the no_op
# because no additional setup is required.
provider_state('an account') { no_op }
provider_state('a course') { no_op }
provider_state('a student enrolled in a course') { no_op }
provider_state('a teacher enrolled in a course') { no_op }
provider_state('a teacher assistant enrolled in a course') { no_op }
provider_state('an observer enrolled in a course') { no_op }
provider_state('an account admin') { no_op }
provider_state('a site admin') { no_op }
end
end
module Pact::Canvas
def self.base_state=(base_state)
@base_state ||= base_state
end
def self.base_state
@base_state
end
class BaseState
include Factories
attr_reader(
:account,
:account_admins,
:course,
:observers,
:site_admins,
:site_admin_account,
:students,
:teachers,
:teacher_assistants
)
def self.seed!(opts: {})
self.new(opts)
end
private
def initialize(opts)
@site_admin_account = opts[:site_admin_account] || Account.site_admin
@account = opts[:account] || Account.default
@course = opts[:course] || seed_course
seed_users(opts)
end
def seed_course
course_factory(account: @account, active_course: true, course_name: 'Contract Tests Course')
end
def seed_users(opts)
@site_admins = opts[:site_admins] || seed_site_admins
@account_admins = opts[:account_admins] || seed_account_admins
@teachers = opts[:teachers] || seed_teachers
@teacher_assistants = opts[:teacher_assistants] || seed_teacher_assistants
@students = opts[:students] || seed_students
@observers = opts[:observers] || seed_observers
end
def seed_site_admins(count: 1)
site_admins = []
count.times do |i|
index = i + 1
site_admin_name = "SiteAdmin#{index}"
site_admin_email = "#{site_admin_name}@instructure.com"
site_admin = account_admin_user(account: @site_admin_account, email: site_admin_email, name: site_admin_name)
site_admin.pseudonyms.create!(unique_id: site_admin_email, password: 'password', password_confirmation: 'password')
site_admin.email = site_admin_email
site_admin.accept_terms
site_admins << site_admin
end
site_admins
end
def seed_account_admins(count: 1)
account_admins = []
count.times do |i|
index = i + 1
admin_name = "Admin#{index}"
admin_email = "#{admin_name}@instructure.com"
admin = account_admin_user(account: @account, email: admin_email, name: admin_name)
admin.pseudonyms.create!(unique_id: admin_email, password: 'password', password_confirmation: 'password')
admin.email = admin_email
admin.accept_terms
account_admins << admin
end
account_admins
end
def seed_teachers(count: 1)
teachers = []
count.times do |i|
index = i + 1
teacher_name = "Teacher#{index}"
teacher_email = "#{teacher_name}@instructure.com"
teacher = user_factory(active_all: true, course: @course, name: teacher_name)
teacher.pseudonyms.create!(unique_id: teacher_email, password: 'password', password_confirmation: 'password')
teacher.email = teacher_email
teacher.accept_terms
course.enroll_teacher(teacher).accept!
teachers << teacher
end
teachers
end
def seed_teacher_assistants(count: 1)
teacher_assistants = []
count.times do |i|
index = i + 1
ta_name = "TeacherAssistant#{index}"
ta_email = "#{ta_name}@instructure.com"
ta = user_factory(active_all: true, course: @course, name: ta_name)
ta.pseudonyms.create!(unique_id: ta_email, password: 'password', password_confirmation: 'password')
ta.email = ta_email
ta.accept_terms
course.enroll_ta(ta).accept!
teacher_assistants << ta
end
teacher_assistants
end
def seed_students(count: 1)
students = []
count.times do |i|
index = i + 1
student_name = "Student#{index}"
student_email = "#{student_name}@instructure.com"
student = user_factory(active_all: true, course: @course, name: student_name)
student.pseudonyms.create!(unique_id: student_email, password: 'password', password_confirmation: 'password')
student.email = student_email
student.accept_terms
course.enroll_student(student).accept!
students << student
end
students
end
def seed_observers(count: 1)
observers = []
count.times do |i|
index = i + 1
observer_name = "Observer#{index}"
observer_email = "#{observer_name}@instructure.com"
observer = user_factory(active_all: true, course: @course, name: observer_name)
observer.pseudonyms.create!(unique_id: observer_email, password: 'password', password_confirmation: 'password')
observer.email = observer_email
observer.accept_terms
enroll_observer(observer: observer)
observers << observer
end
observers
end
def enroll_observer(observer:, student_to_observe: nil)
student = student_to_observe || @students.first
@course.enroll_user(
observer,
'ObserverEnrollment',
enrollment_state: 'active',
associated_user_id: student.id
)
end
end
end

View File

@ -0,0 +1,36 @@
#
# Copyright (C) 2018 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
PactConfig::Consumers::ALL.each do |consumer|
Pact.provider_states_for consumer do
provider_state 'a quiz' do
set_up do
course = Pact::Canvas.base_state.course
quiz_model(course: course)
end
end
provider_state 'a migrated quiz' do
set_up do
course = Pact::Canvas.base_state.course
quiz = quiz_model(course: course)
quiz.migration_id = 'i09d7615b43e5f35589cc1e2647dd345f'
quiz.save!
end
end
end
end

View File

@ -21,18 +21,20 @@ class PactApiConsumerProxy
USER_HEADER = 'HTTP_AUTH_USER'.freeze
def call(env)
# Users calling the API will know the user ID of the
# user that they want to identify as. These are given
# in the provider state descriptions.
# Users calling the API will know the user name of the
# user that they want to identify as. For example, "Admin1".
if expects_auth_header?(env)
user = find_requesting_user(env)
# You can create an access token without having a pseudonym;
# however, when Canvas receives a request and looks up the user
# for that access token, it expects that user to have a pseudonym.
Pseudonym.create!(user: user, unique_id: "#{user.name}@instructure.com")
Pseudonym.create!(user: user, unique_id: "#{user.name}@instructure.com") if user.pseudonyms.empty?
token = user.access_tokens.create!.full_token
env[AUTH_HEADER] = "Bearer #{token}"
end
# Unset the 'AUTH_USER' header -- that's only for this proxy,
# don't pass it along to Canvas.
env.delete(USER_HEADER)
@ -47,12 +49,12 @@ class PactApiConsumerProxy
end
def find_requesting_user(env)
user = User.first
user_name = env[USER_HEADER]
if user_name
user = User.where(name: user_name).first
raise "There is no user with name #{user_name}." unless user
else
user = User.first
end
user