Network error handling fixes

* Make work there are multiple network requests and only one fails
* Test for i18n attributes instead of English translations so Travis works
* Various PR changes
This commit is contained in:
Scott Erickson 2016-01-26 13:27:05 -08:00
parent 3dda5710de
commit 4ef5f40fa1
6 changed files with 88 additions and 98 deletions

View file

@ -1358,8 +1358,9 @@
loading_error:
could_not_load: "Error loading from server"
connection_failure: "Connection Failed" # {change}
connection_failure_desc: "It doesnt look like youre connected to the internet! Check your network connection and then reload this page."
login_required: "Login Required"
login_required_desc: " You need to be logged in to access this page."
login_required_desc: "You need to be logged in to access this page."
unauthorized: "You need to be signed in. Do you have cookies disabled?"
forbidden: "Forbidden" # {change}
forbidden_desc: "Oh no, theres nothing we can show you here! Make sure youre logged into the correct account, or visit one of the links below to get back to programming!"
@ -1375,65 +1376,15 @@
general_desc: "Something went wrong, and its probably our fault. Try waiting a bit and then refreshing the page, or visit one of the following links to get back to programming!"
resources:
sessions: "Sessions"
your_sessions: "Your Sessions"
level: "Level"
social_network_apis: "Social Network APIs"
facebook_status: "Facebook Status"
facebook_friends: "Facebook Friends"
facebook_friend_sessions: "Facebook Friend Sessions"
gplus_friends: "G+ Friends"
gplus_friend_sessions: "G+ Friend Sessions"
leaderboard: "Leaderboard"
user_schema: "User Schema"
user_profile: "User Profile"
patch: "Patch"
patches: "Patches"
patched_model: "Source Document"
model: "Model"
system: "System"
systems: "Systems"
component: "Component"
components: "Components"
thang: "Thang"
thangs: "Thangs"
level_session: "Your Session"
opponent_session: "Opponent Session"
article: "Article"
user_names: "User Names"
thang_names: "Thang Names"
files: "Files"
top_simulators: "Top Simulators"
source_document: "Source Document"
document: "Document"
sprite_sheet: "Sprite Sheet"
employers: "Employers"
candidates: "Candidates"
candidate_sessions: "Candidate Sessions"
user_remark: "User Remark"
user_remarks: "User Remarks"
versions: "Versions"
items: "Items"
hero: "Hero"
heroes: "Heroes"
achievement: "Achievement"
clas: "CLAs"
play_counts: "Play Counts"
feedback: "Feedback"
payment_info: "Payment Info"
campaigns: "Campaigns"
poll: "Poll"
user_polls_record: "Poll Voting History"
course: "Course"
courses: "Courses"
course_instance: "Course Instance"
course_instances: "Course Instances"
classroom: "Classroom"
classrooms: "Classrooms"
clan: "Clan"
clans: "Clans"
members: "Members"
users: "Users"
concepts:
advanced_strings: "Advanced Strings"

View file

@ -140,7 +140,7 @@ module.exports = class SuperModel extends Backbone.Model
# Tracking resources being loaded for this supermodel
finished: ->
return @progress is 1.0 or not @denom
return (@progress is 1.0) or (not @denom) or @failed
addModelResource: (modelOrCollection, name, fetchOptions, value=1) ->
# Deprecating name. Handle if name is not included
@ -203,6 +203,7 @@ module.exports = class SuperModel extends Backbone.Model
onResourceFailed: (r) ->
return unless @resources[r.rid]
@failed = true
@trigger('failed', resource: r)
r.clean()

View file

@ -39,7 +39,7 @@ block header
li
a(href="/account/prepaid", data-i18n="account.prepaid_codes") Prepaid Codes
li
a#logout-button(data-i18n="login.log_out")
a#logout-button(data-i18n="login.log_out")
else
button.btn.btn-sm.btn-primary.header-font.signup-button(data-i18n="login.sign_up")

View file

@ -31,7 +31,7 @@
else if !jqxhr.status
h1(data-i18n="loading_error.connection_failure")
p It doesnt look like youre connected to the internet! Check your network connection and then reload this page.
p(data-i18n="loading_error.connection_failure_desc")
else
if jqxhr.status === 408
@ -49,41 +49,49 @@
#links-row.row
.col-sm-3
strong(data-i18n="cmomon.help") Help
br
a(href="/", data-i18n="nav.home")
br
a(href=view.forumLink(), data-i18n="nav.forum")
br
a(tabindex=-1, data-toggle="coco-modal", data-target="core/ContactModal", data-i18n="nav.contact")
br
a(href='/community', data-i18n="nav.community")
ul.list-unstyled
li
strong(data-i18n="common.help")
li
a(href="/", data-i18n="nav.home")
li
a(href=view.forumLink(), data-i18n="nav.forum")
li
a(tabindex=-1, data-toggle="coco-modal", data-target="core/ContactModal", data-i18n="nav.contact")
li
a(href='/community', data-i18n="nav.community")
.col-sm-3
strong(data-i18n="courses.students")
br
a(href="/courses/students", data-i18n="nav.learn_to_code")
if me.isAnonymous()
br
a.login-btn(data-i18n="login.log_in")
br
a(href="/courses", data-i18n="courses.join_class")
ul.list-unstyled
li
strong(data-i18n="courses.students")
li
a(href="/courses/students", data-i18n="nav.learn_to_code")
if me.isAnonymous()
li
a.login-btn(data-i18n="login.log_in")
li
a(href="/courses", data-i18n="courses.join_class")
.col-sm-3
strong(data-i18n="nav.teachers")
br
a(href="/schools", data-i18n="about.why_codecombat")
if me.isAnonymous()
br
a.login-btn(data-i18n="login.log_in")
br
a(href="/courses/teachers", data-i18n="nav.create_a_class")
ul.list-unstyled
li
strong(data-i18n="nav.teachers")
li
a(href="/schools", data-i18n="about.why_codecombat")
if me.isAnonymous()
li
a.login-btn(data-i18n="login.log_in")
li
a(href="/courses/teachers", data-i18n="nav.create_a_class")
.col-sm-3
strong(data-i18n="nav.other")
br
a(href="http://blog.codecombat.com/", data-i18n="nav.blog")
br
a(href="https://www.facebook.com/codecombat", data-i18n="nav.facebook")
br
a(href="https://twitter.com/codecombat", data-i18n="nav.twitter")
ul.list-unstyled
li
strong(data-i18n="nav.other")
li
a(href="http://blog.codecombat.com/", data-i18n="nav.blog")
li
a(href="https://www.facebook.com/codecombat", data-i18n="nav.facebook")
li
a(href="https://twitter.com/codecombat", data-i18n="nav.twitter")

View file

@ -158,6 +158,7 @@ module.exports = class CocoView extends Backbone.View
# Error handling for loading
onResourceLoadFailed: (e) ->
r = e.resource
@stopListening @supermodel
return if r.jqxhr?.status is 402 # payment-required failures are handled separately
@showError(r.jqxhr)

View file

@ -2,22 +2,51 @@ CocoView = require 'views/core/CocoView'
User = require 'models/User'
BlandView = class BlandView extends CocoView
template: -> ''
template: ->
return if @specialMessage then '<div id="content">custom message</div>' else '<div id="content">normal message</div>'
initialize: ->
@user = new User()
@supermodel.loadModel(@user)
@user1 = new User({_id: _.uniqueId()})
@supermodel.loadModel(@user1)
@user2 = new User({_id: _.uniqueId()})
@supermodel.loadModel(@user2)
onResourceLoadFailed: (e) ->
resource = e.resource
if resource.jqxhr.status is 400 and resource.model is @user1
@specialMessage = true
@render()
else
super(arguments...)
describe 'CocoView', ->
describe 'network error handling', ->
view = null
respond = (code, json) ->
request = jasmine.Ajax.requests.mostRecent()
respond = (code, index=0) ->
view.render()
request.respondWith({status: code, responseText: JSON.stringify(json or {})})
requests = jasmine.Ajax.requests.all()
requests[index].respondWith({status: code, responseText: JSON.stringify({})})
beforeEach ->
view = new BlandView()
describe 'when the view overrides onResourceLoadFailed', ->
beforeEach ->
view.render()
expect(view.$('#content').hasClass('hidden')).toBe(true)
respond(400)
it 'can show a custom message for a given error and model', ->
expect(view.$('#content').hasClass('hidden')).toBe(false)
expect(view.$('#content').text()).toBe('custom message')
respond(200, 1)
expect(view.$('#content').hasClass('hidden')).toBe(false)
expect(view.$('#content').text()).toBe('custom message')
it '(demo)', -> jasmine.demoEl(view.$el)
describe 'when the server returns 401', ->
beforeEach ->
@ -39,7 +68,7 @@ describe 'CocoView', ->
expect(view.openModalView).toHaveBeenCalled()
it 'says "Login Required"', ->
expect(view.$el.text().indexOf('Login Required')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.login_required"]').length).toBeTruthy()
it '(demo)', -> jasmine.demoEl(view.$el)
@ -84,10 +113,10 @@ describe 'CocoView', ->
beforeEach -> respond(408)
it 'includes "Server Timeout" in the header', ->
expect(view.$el.text().indexOf('Server Timeout')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.timeout"]').length).toBeTruthy()
it 'shows a message encouraging refreshing the page or following links', ->
expect(view.$el.text().indexOf('refresh')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.general_desc"]').length).toBeTruthy()
it '(demo)', -> jasmine.demoEl(view.$el)
@ -98,7 +127,7 @@ describe 'CocoView', ->
respond()
it 'shows "Connection Failed"', ->
expect(view.$el.text().indexOf('Connection Failed')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.connection_failure"]').length).toBeTruthy()
it '(demo)', -> jasmine.demoEl(view.$el)
@ -108,10 +137,10 @@ describe 'CocoView', ->
beforeEach -> respond(9001)
it 'includes "Unknown Error" in the header', ->
expect(view.$el.text().indexOf('Unknown Error')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.unknown"]').length).toBeTruthy()
it 'shows a message encouraging refreshing the page or following links', ->
expect(view.$el.text().indexOf('refresh')).toBeGreaterThan(-1)
expect(view.$('[data-i18n="loading_error.general_desc"]').length).toBeTruthy()
it '(demo)', -> jasmine.demoEl(view.$el)