QuizApiClient

Welcome!

Installation

Add this line to your application's Gemfile:

gem 'quiz_api_client'

And then execute:

$ bundle

Or install it yourself as:

$ gem install quiz_api_client

Usage

This client library is used to access quiz_api through Signed Auth, our implementation of signing a JWT with the appropriate scope and resource_id.

Currently, the "services" are organized by resource, following the REST convention of pluralization.

Instantiate the Client

To instantiate a client, you'll need the secret and the host.

client = QuizApiClient::Client.new(
  consumer_key: 'the consumer key normally stored in the quiz_api signed_auth_consumers table',
  host: 'your-quiz-api-host-here.com',
  shared_secret: 'the-api-secret normally stored on the quiz_api account',
  protocol: 'http' # Set this to what you need, ideally it's an environment variable
)

Creation of Tokens

JWTs are created without hitting quiz_api and and they are validated on quiz_api. Tokens are created for a given scope, expiration, and an optional resource_id.

Example, generate a token for building:

client.jwt_service.grant_permission(
  scope: 'quiz.build',
  exp: Time.now.utc.to_i + 60, # some reasonable time, obviously longer is more a security risk
  resource_id: 1)

Calling the API

Example, create a Quiz:

client.quizzes_service.create(
  params: {
    title: 'My quiz'
  },
  token: my_scoped_token
)

Currently Supported Functionality

Quizzes Service

# Create Quiz
client.quizzes_service.create(token:, params:)

# List Quizzes
client.quizzes_service.list(token:, params:)

Quiz Entries Service

# Get Quiz Entries
client.quiz_entries_service.list(
  token: my_scoped_token,
  params: {
    id: quiz_id
  }
)

Quiz Session Service

# Update Quiz Session
client.quiz_session_service.update(
  token: my_scoped_token,
  params: {
    id: quiz_session_id,
    # Other params here
  }
)

Quiz Sessions Service

# Create Quiz Session
client.quiz_sessions_service.create(
  token: my_scoped_token,
  params: {
    quiz_id: quiz_id_to_create_session_under
  }
)

QTI Imports Service

# Create QTI Import
client.qti_imports_service.create(
  token: my_scoped_token,
  params: {
    quiz_id: quiz_id_to_create_import_under,
    qti_import: {
      url: url where QTI Export is stored
    }
  }
)

Item Analyses Service

# List item analyses
client.item_analyses_service.list(
  token: my_scoped_token,
  params: {
    quiz_id: quiz_id_to_list_items_under
  }
)
# get specific item analysis
client.item_analyses_service.get(
  token: my_scoped_token,
  params: {
    quiz_id: quiz_id_to_list_items_under,
    id: item_id_to_get_under
  }
)

Quiz Analyses Service

# get specific item analysis
client.quiz_analyses_service.get(
  token: my_scoped_token,
  params: {
    quiz_id: quiz_id_to_get_analysis
  }
)

Quiz Session Events Service

# list quiz session events
client.quiz_session_events_service.list(
  token: my_scoped_token,
  params: {
    quiz_session_id: quiz_session_id_to_get_events_under
  }
)

Development

After checking out the repo, run bin/setup to install dependencies.

Then, run bundle exec rake spec to run the tests.

You can also run bundle exec rake console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

When you add or modify a service, be sure to add or modify contract tests!

Contract Tests

We use Pact for our contract testing. To generate a Pact file, run bin/contracts-generate. The script will generate the Pact file and place it in the pacts/ directory. It will also attempt to publish the Pact file to a local Pact Broker.

Development Workflow:

  1. In the quiz_api repo, spin up the Quiz API service with bin/dev-setup
  2. In the quiz_pact_broker repo, spin up a Pact Broker with bin/dev-setup
  3. In the quiz_api repo, write Pact provider states in the spec/service_consumers/api/quiz_api_client_ruby/ directory as needed
  4. In this repo's spec/contracts/ directory, write or modify a contract test
  5. In this repo, run bin/contracts-generate to generate a Pact file and publish it to the Pact Broker
  6. In the quiz_api repo, run bin/contracts to pull the new Pact file from the Pact Broker and run the updated contract tests against the Quiz API service

Bonus: You can view your Pact file in the Pact Broker at http://pact-broker.docker along with some cool goodies!

Debugging Failures

Pact has some basic RSpec output for failed specs. It also keeps a log in log/pact.log and offers general pointers for debugging.

Above all, learn the Pact basics.

What should contract tests cover?

The aim of contract testing here is not to test all functional requirements of the Quiz API service. Rather, the goal is to ensure changes to the Quiz API service don't break its clients. We can best accomplish this with the following contract test coverage:

  • Basic happy path requests for all endpoints (POST, GET, PUT, DELETE)
  • Basic error paths for all endpoints (verify the error messages and/or HTTP response codes are accurate)
  • Resource state management; for example, when a quiz attempt is submitted but not yet graded
  • Special edge case errors

Again, what not to test: the functional behavior of the service; for example, a series of sequential API calls to test a full user scenario.