mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
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:
parent
3dda5710de
commit
4ef5f40fa1
6 changed files with 88 additions and 98 deletions
|
@ -1358,8 +1358,9 @@
|
|||
loading_error:
|
||||
could_not_load: "Error loading from server"
|
||||
connection_failure: "Connection Failed" # {change}
|
||||
connection_failure_desc: "It doesn’t look like you’re 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, there’s nothing we can show you here! Make sure you’re 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 it’s 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"
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
else if !jqxhr.status
|
||||
h1(data-i18n="loading_error.connection_failure")
|
||||
p It doesn’t look like you’re 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")
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue