forked from TheOdinProject/theodinproject
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Endpoint for Viewing Lesson Completion Stats (TheOdinProject#967)
* Add Endpoint for Viewing Lesson Completion Stats To keep an eye on lesson completion stats, we need access to lesson completion data so we can make visulizations. * Fix authentication, it wasn't checking both the username and password it was instead just checking the password. Also fixes some unit test formatting * Allow endpoint to be queried with a date range * Add additional configuration keys to env * Stub out accessing mailchimp api in unit test
- Loading branch information
1 parent
c1d7084
commit 4a7827d
Showing
18 changed files
with
358 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
API_USERNAME: 'development' | ||
API_PASSWORD: 'qwerty123' | ||
GITHUB_API_TOKEN: 1234 | ||
GITHUB_APP_ID: 1234 | ||
GITHUB_SECRET: 1234 | ||
GOOGLE_CLIENT_ID: 1234 | ||
GOOGLE_CLIENT_SECRET: 1234 | ||
MAILCHIMP_API_KEY: 1234 | ||
MAILCHIMP_LIST_ID: 1234 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
module Api | ||
class LessonCompletionsController < ApplicationController | ||
before_action :authenticate | ||
|
||
def index | ||
render json: serialized_lesson_completions | ||
end | ||
|
||
private | ||
|
||
def serialized_lesson_completions | ||
Course.order(:position).map do |course| | ||
CourseSerializer.as_json(course, between_dates) | ||
end | ||
end | ||
|
||
def between_dates | ||
(DateTime.parse(start_date)..DateTime.parse(end_date)) | ||
end | ||
|
||
def start_date | ||
params.fetch(:start_date, '2013/01/01') | ||
end | ||
|
||
def end_date | ||
params.fetch(:end_date, DateTime.now.to_s) | ||
end | ||
|
||
def authenticate | ||
authenticate_or_request_with_http_basic do |username, password| | ||
username == ENV.fetch('API_USERNAME') && | ||
password == ENV.fetch('API_PASSWORD') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class CourseSerializer | ||
attr_reader :course, :between_dates | ||
private :course, :between_dates | ||
|
||
def initialize(course, between_dates = nil) | ||
@course, @between_dates = course, between_dates | ||
end | ||
|
||
def self.as_json(course, between_dates = nil) | ||
new(course, between_dates).as_json | ||
end | ||
|
||
def as_json(options = nil) | ||
{ | ||
title: course.title, | ||
sections: serialized_sections, | ||
} | ||
end | ||
|
||
private | ||
|
||
def serialized_sections | ||
course.sections.map do |section| | ||
SectionSerializer.as_json(section, between_dates) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
class LessonSerializer | ||
attr_reader :lesson, :between_dates | ||
private :lesson, :between_dates | ||
|
||
def initialize(lesson, between_dates = nil) | ||
@lesson, @between_dates = lesson, between_dates | ||
end | ||
|
||
def self.as_json(lesson, between_dates = nil) | ||
new(lesson, between_dates).as_json | ||
end | ||
|
||
def as_json(options=nil) | ||
{ | ||
title: lesson.title, | ||
completions: completions.count, | ||
} | ||
end | ||
|
||
private | ||
|
||
def completions | ||
lesson.lesson_completions.where(created_at: between_dates) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class SectionSerializer | ||
attr_reader :section, :between_dates | ||
private :section, :between_dates | ||
|
||
def initialize(section, between_dates = nil) | ||
@section, @between_dates = section, between_dates | ||
end | ||
|
||
def self.as_json(section, between_dates = nil) | ||
new(section, between_dates).as_json | ||
end | ||
|
||
def as_json(options=nil) | ||
{ | ||
title: section.title, | ||
lessons: serialized_lessons | ||
} | ||
end | ||
|
||
private | ||
|
||
def serialized_lessons | ||
section.lessons.map do |lesson| | ||
LessonSerializer.as_json(lesson, between_dates) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
spec/controllers/api/lesson_completions_controller_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
require 'rails_helper' | ||
|
||
module Api | ||
RSpec.describe LessonCompletionsController do | ||
let(:params) { { start_date: start_date, end_date: end_date } } | ||
let(:start_date) { '2019/01/01' } | ||
let(:end_date) { '2019/01/31' } | ||
let!(:course) { create(:course, title: 'Web Development 101', position: 1) } | ||
let(:serialized_course) do | ||
{ | ||
'title' => 'Web Development 101', | ||
'sections' => [ | ||
{ | ||
'title' => 'Installations', | ||
'lessons' => [ | ||
'title' => 'Overview', | ||
'completions' => 1, | ||
] | ||
} | ||
] | ||
} | ||
end | ||
let(:username) { 'development' } | ||
let(:password) { 'qwerty123' } | ||
let(:authenticate_request) do | ||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic. | ||
encode_credentials(username, password) | ||
end | ||
let(:between_dates) do | ||
(DateTime.parse(start_date)..DateTime.parse(end_date)) | ||
end | ||
|
||
before do | ||
allow(CourseSerializer).to receive(:as_json).with(course, between_dates). | ||
and_return(serialized_course) | ||
end | ||
|
||
describe '#index' do | ||
context 'when authenticated' do | ||
|
||
before do | ||
authenticate_request | ||
end | ||
|
||
it 'returns a 200 status code' do | ||
get :index, params: params | ||
expect(response.status).to eql(200) | ||
end | ||
|
||
it 'renders serialized courses in json format' do | ||
get :index, params: params | ||
expect(JSON.parse(response.body)).to eql([serialized_course]) | ||
end | ||
|
||
context 'when start and end dates are not present' do | ||
let(:params) { { } } | ||
let(:between_dates) do | ||
(DateTime.parse('2013/01/01')..DateTime.parse(DateTime.now.to_s)) | ||
end | ||
|
||
it 'uses the default dates' do | ||
get :index, params: params | ||
|
||
expect(CourseSerializer).to have_received(:as_json). | ||
with(course, between_dates) | ||
end | ||
end | ||
end | ||
|
||
context 'when not authenticated' do | ||
it 'does not allow access' do | ||
get :index, params: params | ||
expect(response.status).to eql(401) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
require 'rails_helper' | ||
|
||
RSpec.describe CourseSerializer do | ||
subject { described_class.as_json(course, between_dates) } | ||
|
||
let(:course) do | ||
double( | ||
'Section', | ||
title: 'Web Development 101', | ||
sections: sections, | ||
) | ||
end | ||
let(:between_dates) do | ||
(DateTime.parse('2019/01/01')..DateTime.parse('2019/12/31')) | ||
end | ||
let(:sections) { [section] } | ||
let(:section) { double('Section') } | ||
let(:serialized_section) do | ||
{ | ||
title: 'Installations', | ||
lessons: [{ title: 'Overview', completions: 1 }], | ||
} | ||
end | ||
|
||
describe '#as_json' do | ||
let(:serialized_course) do | ||
{ | ||
title: 'Web Development 101', | ||
sections: [serialized_section], | ||
} | ||
end | ||
|
||
before do | ||
allow(SectionSerializer).to receive(:as_json). | ||
with(section, between_dates).and_return(serialized_section) | ||
end | ||
|
||
it { is_expected.to eql(serialized_course) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
require 'rails_helper' | ||
|
||
RSpec.describe LessonSerializer do | ||
subject { described_class.as_json(lesson, between_dates) } | ||
|
||
let(:lesson) do | ||
double('Lesson', title: 'Overview', lesson_completions: lesson_completions) | ||
end | ||
let(:between_dates) do | ||
(DateTime.parse('2019/01/01')..DateTime.parse('2019/12/31')) | ||
end | ||
let(:lesson_completions) { [lesson_completion] } | ||
let(:lesson_completion) do | ||
double('LessonCompletion', created_at: '2019/01/10') | ||
end | ||
|
||
describe '#as_json' do | ||
let(:serialized_lesson) do | ||
{ | ||
title: 'Overview', | ||
completions: 1 | ||
} | ||
end | ||
|
||
before do | ||
allow(lesson_completions).to receive(:where). | ||
with(created_at: between_dates).and_return([lesson_completion]) | ||
end | ||
|
||
it { is_expected.to eql(serialized_lesson) } | ||
end | ||
end |
Oops, something went wrong.