mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-14 16:53:27 +00:00
commit
eae8b5a592
16 changed files with 6282 additions and 248 deletions
6
services/web/Dockerfile.frontend
Normal file
6
services/web/Dockerfile.frontend
Normal file
|
@ -0,0 +1,6 @@
|
|||
FROM node:8.9.4
|
||||
|
||||
# Install Google Chrome
|
||||
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
|
||||
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
||||
RUN apt-get update && apt-get install -y google-chrome-stable
|
9
services/web/Jenkinsfile
vendored
9
services/web/Jenkinsfile
vendored
|
@ -63,7 +63,14 @@ pipeline {
|
|||
}
|
||||
}
|
||||
steps {
|
||||
sh 'make --no-print-directory test_unit test_frontend MOCHA_ARGS="--reporter tap"'
|
||||
sh 'make --no-print-directory test_unit MOCHA_ARGS="--reporter tap"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Frontend Unit Test') {
|
||||
steps {
|
||||
// Spawns its own docker containers
|
||||
sh 'make --no-print-directory test_frontend'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ clean_frontend:
|
|||
|
||||
clean_tests:
|
||||
rm -rf test/unit/js
|
||||
rm -rf test/unit_frontend/js
|
||||
rm -rf test/acceptance/js
|
||||
|
||||
clean_modules:
|
||||
|
@ -181,8 +182,9 @@ test: test_unit test_frontend test_acceptance
|
|||
test_unit:
|
||||
npm -q run test:unit -- ${MOCHA_ARGS}
|
||||
|
||||
test_frontend:
|
||||
npm -q run test:frontend -- ${MOCHA_ARGS}
|
||||
test_frontend: test_clean # stop service
|
||||
$(MAKE) compile
|
||||
docker-compose ${DOCKER_COMPOSE_FLAGS} up test_frontend
|
||||
|
||||
test_acceptance: test_acceptance_app test_acceptance_modules
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e;
|
||||
MOCHA="node_modules/.bin/mocha --recursive --reporter spec"
|
||||
$MOCHA "$@" test/unit_frontend/js
|
||||
|
|
@ -20,6 +20,15 @@ services:
|
|||
- mongo
|
||||
command: node app.js
|
||||
|
||||
test_frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend
|
||||
volumes:
|
||||
- .:/app
|
||||
working_dir: /app
|
||||
command: npm run test:frontend
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
|
||||
|
|
36
services/web/karma.conf.js
Normal file
36
services/web/karma.conf.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
module.exports = function (config) {
|
||||
config.set({
|
||||
customLaunchers: {
|
||||
ChromeCustom: {
|
||||
base: 'ChromeHeadless',
|
||||
// We must disable the Chrome sandbox when running Chrome inside Docker
|
||||
// (Chrome's sandbox needs more permissions than Docker allows by
|
||||
// default)
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
browsers: ['ChromeCustom'],
|
||||
files: [
|
||||
'test/unit_frontend/js/bootstrap.js',
|
||||
// Angular must be loaded before requirejs to set up angular global
|
||||
'public/js/libs/angular-1.6.4.min.js',
|
||||
'public/js/libs/angular-mocks.js',
|
||||
'public/js/libs/jquery-1.11.1.min.js',
|
||||
// Set up requirejs
|
||||
'test/unit_frontend/js/test-main.js',
|
||||
// Include source & test files, but don't "include" them as requirejs
|
||||
// handles this for us
|
||||
{ pattern: 'public/js/**/*.js', included: false },
|
||||
{ pattern: 'test/unit_frontend/js/**/*.js', included: false }
|
||||
],
|
||||
frameworks: ['requirejs', 'mocha', 'chai-sinon'],
|
||||
plugins: [
|
||||
require('karma-requirejs'),
|
||||
require('karma-mocha'),
|
||||
require('karma-chai-sinon'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-tap-reporter')
|
||||
],
|
||||
reporters: ['tap']
|
||||
});
|
||||
}
|
2738
services/web/npm-shrinkwrap.json
generated
2738
services/web/npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,7 @@
|
|||
"test:acceptance:dir": "npm -q run test:acceptance:wait_for_app && npm -q run test:acceptance:run -- $@",
|
||||
"test:acceptance": "npm -q run test:acceptance:dir -- $@ test/acceptance/js",
|
||||
"test:unit": "npm -q run compile && bin/unit_test $@",
|
||||
"test:frontend": "npm -q run compile && bin/frontend_test $@",
|
||||
"test:frontend": "karma start --single-run",
|
||||
"compile": "make compile",
|
||||
"start": "npm -q run compile && node app.js",
|
||||
"nodemon": "nodemon --config nodemon.json",
|
||||
|
@ -119,10 +119,18 @@
|
|||
"grunt-postcss": "^0.8.0",
|
||||
"grunt-sed": "^0.1.1",
|
||||
"grunt-shell": "^2.1.0",
|
||||
"karma": "^2.0.0",
|
||||
"karma-chai-sinon": "^0.1.5",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-requirejs": "^1.1.0",
|
||||
"karma-tap-reporter": "0.0.6",
|
||||
"mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"nodemon": "^1.14.3",
|
||||
"requirejs": "^2.1.22",
|
||||
"sandboxed-module": "0.2.0",
|
||||
"sinon": "^1.17.0",
|
||||
"sinon-chai": "^2.14.0",
|
||||
"timekeeper": "",
|
||||
"translations-sharelatex": "git+https://github.com/sharelatex/translations-sharelatex.git#master",
|
||||
"webpack": "^3.10.0",
|
||||
|
|
3197
services/web/public/js/libs/angular-mocks.js
vendored
Normal file
3197
services/web/public/js/libs/angular-mocks.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
4
services/web/test/unit_frontend/coffee/bootstrap.coffee
Normal file
4
services/web/test/unit_frontend/coffee/bootstrap.coffee
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Stub out some globals
|
||||
window.sharelatex = {
|
||||
sixpackDomain: ''
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
define ['ide/editor/directives/cmEditor'], () ->
|
||||
describe 'cmEditor', () ->
|
||||
beforeEach(module('SharelatexApp'))
|
||||
|
||||
beforeEach () ->
|
||||
@richTextInit = sinon.stub()
|
||||
window.Frontend = {
|
||||
richText: {
|
||||
init: @richTextInit
|
||||
}
|
||||
}
|
||||
|
||||
it 'inits Rich Text', () ->
|
||||
inject ($compile, $rootScope) ->
|
||||
$compile('<div cm-editor></div>')($rootScope)
|
||||
expect(@richTextInit).to.have.been.called
|
||||
|
||||
it 'attaches to CM', () ->
|
||||
inject ($compile, $rootScope) ->
|
||||
setValue = sinon.stub()
|
||||
@richTextInit.returns({ setValue: setValue })
|
||||
getSnapshot = sinon.stub()
|
||||
detachFromCM = sinon.stub()
|
||||
attachToCM = sinon.stub()
|
||||
$rootScope.sharejsDoc = {
|
||||
getSnapshot: getSnapshot
|
||||
detachFromCM: detachFromCM
|
||||
attachToCM: attachToCM
|
||||
}
|
||||
|
||||
$compile('<div cm-editor sharejs-doc="sharejsDoc"></div>')($rootScope)
|
||||
$rootScope.$digest()
|
||||
|
||||
expect(getSnapshot).to.have.been.called
|
||||
expect(setValue).to.have.been.called
|
||||
expect(detachFromCM).to.have.been.called
|
||||
expect(attachToCM).to.have.been.called
|
||||
|
||||
it 'detaches from CM when destroyed', () ->
|
||||
inject ($compile, $rootScope) ->
|
||||
@richTextInit.returns({ setValue: sinon.stub() })
|
||||
detachFromCM = sinon.stub()
|
||||
$rootScope.sharejsDoc = {
|
||||
getSnapshot: sinon.stub()
|
||||
detachFromCM: detachFromCM
|
||||
attachToCM: sinon.stub()
|
||||
}
|
||||
|
||||
$compile('<div cm-editor sharejs-doc="sharejsDoc"></div>')($rootScope)
|
||||
$rootScope.$digest()
|
||||
$rootScope.$broadcast('destroy')
|
||||
|
||||
expect(detachFromCM).to.have.been.called
|
|
@ -1,164 +0,0 @@
|
|||
Path = require 'path'
|
||||
SandboxedModule = require "sandboxed-module"
|
||||
modulePath = Path.join __dirname, '../../../../../public/js/ide/history/HistoryV2Manager'
|
||||
sinon = require("sinon")
|
||||
expect = require("chai").expect
|
||||
|
||||
describe "HistoryV2Manager", ->
|
||||
beforeEach ->
|
||||
@moment = {}
|
||||
@ColorManager = {}
|
||||
SandboxedModule.require modulePath, globals:
|
||||
"define": (dependencies, builder) =>
|
||||
@HistoryV2Manager = builder(@moment, @ColorManager)
|
||||
|
||||
@scope =
|
||||
$watch: sinon.stub()
|
||||
$on: sinon.stub()
|
||||
@ide = {}
|
||||
|
||||
@historyManager = new @HistoryV2Manager(@ide, @scope)
|
||||
|
||||
it "should setup the history scope on intialization", ->
|
||||
expect(@scope.history).to.deep.equal({
|
||||
isV2: true
|
||||
updates: []
|
||||
nextBeforeTimestamp: null
|
||||
atEnd: false
|
||||
selection: {
|
||||
updates: []
|
||||
pathname: null
|
||||
docs: {}
|
||||
range: {
|
||||
fromV: null
|
||||
toV: null
|
||||
}
|
||||
}
|
||||
diff: null
|
||||
})
|
||||
|
||||
describe "_perDocSummaryOfUpdates", ->
|
||||
it "should return the range of updates for the docs", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 7, toV: 9
|
||||
},{
|
||||
pathnames: ["main.tex", "foo.tex"]
|
||||
fromV: 4, toV: 6
|
||||
},{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 3, toV: 3
|
||||
},{
|
||||
pathnames: ["foo.tex"]
|
||||
fromV: 0, toV: 2
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 3, toV: 9 },
|
||||
"foo.tex": { fromV: 0, toV: 6 }
|
||||
})
|
||||
|
||||
it "should track renames", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main2.tex"]
|
||||
fromV: 5, toV: 9
|
||||
},{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main1.tex",
|
||||
newPathname: "main2.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 4, toV: 4
|
||||
},{
|
||||
pathnames: ["main1.tex"]
|
||||
fromV: 3, toV: 3
|
||||
},{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main0.tex",
|
||||
newPathname: "main1.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 2, toV: 2
|
||||
},{
|
||||
pathnames: ["main0.tex"]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main0.tex": { fromV: 0, toV: 9 }
|
||||
})
|
||||
|
||||
it "should track single renames", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main1.tex",
|
||||
newPathname: "main2.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 4, toV: 5
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main1.tex": { fromV: 4, toV: 5 }
|
||||
})
|
||||
|
||||
it "should track additions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
add:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}, {
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 1, toV: 4
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 4 }
|
||||
})
|
||||
|
||||
it "should track single additions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
add:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 1 }
|
||||
})
|
||||
|
||||
it "should track deletions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 0, toV: 1
|
||||
}, {
|
||||
project_ops: [{
|
||||
remove:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 1, toV: 2
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 2, deleted: true }
|
||||
})
|
||||
|
||||
it "should track single deletions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
remove:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 1, deleted: true }
|
||||
})
|
|
@ -0,0 +1,152 @@
|
|||
define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) ->
|
||||
describe "HistoryV2Manager", ->
|
||||
beforeEach ->
|
||||
@scope =
|
||||
$watch: sinon.stub()
|
||||
$on: sinon.stub()
|
||||
@ide = {}
|
||||
@historyManager = new HistoryV2Manager(@ide, @scope)
|
||||
|
||||
it "should setup the history scope on intialization", ->
|
||||
expect(@scope.history).to.deep.equal({
|
||||
isV2: true
|
||||
updates: []
|
||||
nextBeforeTimestamp: null
|
||||
atEnd: false
|
||||
selection: {
|
||||
updates: []
|
||||
pathname: null
|
||||
docs: {}
|
||||
range: {
|
||||
fromV: null
|
||||
toV: null
|
||||
}
|
||||
}
|
||||
diff: null
|
||||
})
|
||||
|
||||
describe "_perDocSummaryOfUpdates", ->
|
||||
it "should return the range of updates for the docs", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 7, toV: 9
|
||||
},{
|
||||
pathnames: ["main.tex", "foo.tex"]
|
||||
fromV: 4, toV: 6
|
||||
},{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 3, toV: 3
|
||||
},{
|
||||
pathnames: ["foo.tex"]
|
||||
fromV: 0, toV: 2
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 3, toV: 9 },
|
||||
"foo.tex": { fromV: 0, toV: 6 }
|
||||
})
|
||||
|
||||
it "should track renames", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main2.tex"]
|
||||
fromV: 5, toV: 9
|
||||
},{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main1.tex",
|
||||
newPathname: "main2.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 4, toV: 4
|
||||
},{
|
||||
pathnames: ["main1.tex"]
|
||||
fromV: 3, toV: 3
|
||||
},{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main0.tex",
|
||||
newPathname: "main1.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 2, toV: 2
|
||||
},{
|
||||
pathnames: ["main0.tex"]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main0.tex": { fromV: 0, toV: 9 }
|
||||
})
|
||||
|
||||
it "should track single renames", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
rename: {
|
||||
pathname: "main1.tex",
|
||||
newPathname: "main2.tex"
|
||||
}
|
||||
}],
|
||||
fromV: 4, toV: 5
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main1.tex": { fromV: 4, toV: 5 }
|
||||
})
|
||||
|
||||
it "should track additions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
add:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}, {
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 1, toV: 4
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 4 }
|
||||
})
|
||||
|
||||
it "should track single additions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
add:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 1 }
|
||||
})
|
||||
|
||||
it "should track deletions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
pathnames: ["main.tex"]
|
||||
fromV: 0, toV: 1
|
||||
}, {
|
||||
project_ops: [{
|
||||
remove:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 1, toV: 2
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 2, deleted: true }
|
||||
})
|
||||
|
||||
it "should track single deletions", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
project_ops: [{
|
||||
remove:
|
||||
pathname: "main.tex"
|
||||
}]
|
||||
fromV: 0, toV: 1
|
||||
}])
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
"main.tex": { fromV: 0, toV: 1, deleted: true }
|
||||
})
|
|
@ -1,68 +0,0 @@
|
|||
Path = require 'path'
|
||||
SandboxedModule = require "sandboxed-module"
|
||||
modulePath = Path.join __dirname, '../../../../../public/js/ide/history/util/displayNameForUser'
|
||||
sinon = require("sinon")
|
||||
expect = require("chai").expect
|
||||
|
||||
describe "displayNameForUser", ->
|
||||
beforeEach ->
|
||||
SandboxedModule.require modulePath, globals:
|
||||
"define": (dependencies, builder) =>
|
||||
@displayNameForUser = builder()
|
||||
"window": @window = {}
|
||||
@window.user = { id: 42 }
|
||||
|
||||
it "should return 'Anonymous' with no user", ->
|
||||
expect(
|
||||
@displayNameForUser(null)
|
||||
).to.equal "Anonymous"
|
||||
|
||||
it "should return 'you' when the user has the same id as the window", ->
|
||||
expect(
|
||||
@displayNameForUser({
|
||||
id: @window.user.id
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: "Allen"
|
||||
})
|
||||
).to.equal "you"
|
||||
|
||||
it "should return the first_name and last_name when present", ->
|
||||
expect(
|
||||
@displayNameForUser({
|
||||
id: @window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: "Allen"
|
||||
})
|
||||
).to.equal "James Allen"
|
||||
|
||||
it "should return only the firstAname if no last_name", ->
|
||||
expect(
|
||||
@displayNameForUser({
|
||||
id: @window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "James"
|
||||
|
||||
it "should return the email username if there are no names", ->
|
||||
expect(
|
||||
@displayNameForUser({
|
||||
id: @window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: ""
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "james.allen"
|
||||
|
||||
it "should return the '?' if it has nothing", ->
|
||||
expect(
|
||||
@displayNameForUser({
|
||||
id: @window.user.id + 1
|
||||
email: ""
|
||||
first_name: ""
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "?"
|
|
@ -0,0 +1,59 @@
|
|||
define ['ide/history/util/displayNameForUser'], (displayNameForUser) ->
|
||||
describe "displayNameForUser", ->
|
||||
beforeEach ->
|
||||
window.user = { id: 42 }
|
||||
|
||||
it "should return 'Anonymous' with no user", ->
|
||||
expect(
|
||||
displayNameForUser(null)
|
||||
).to.equal "Anonymous"
|
||||
|
||||
it "should return 'you' when the user has the same id as the window", ->
|
||||
expect(
|
||||
displayNameForUser({
|
||||
id: window.user.id
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: "Allen"
|
||||
})
|
||||
).to.equal "you"
|
||||
|
||||
it "should return the first_name and last_name when present", ->
|
||||
expect(
|
||||
displayNameForUser({
|
||||
id: window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: "Allen"
|
||||
})
|
||||
).to.equal "James Allen"
|
||||
|
||||
it "should return only the firstAname if no last_name", ->
|
||||
expect(
|
||||
displayNameForUser({
|
||||
id: window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: "James"
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "James"
|
||||
|
||||
it "should return the email username if there are no names", ->
|
||||
expect(
|
||||
displayNameForUser({
|
||||
id: window.user.id + 1
|
||||
email: "james.allen@overleaf.com"
|
||||
first_name: ""
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "james.allen"
|
||||
|
||||
it "should return the '?' if it has nothing", ->
|
||||
expect(
|
||||
displayNameForUser({
|
||||
id: window.user.id + 1
|
||||
email: ""
|
||||
first_name: ""
|
||||
last_name: ""
|
||||
})
|
||||
).to.equal "?"
|
14
services/web/test/unit_frontend/coffee/test-main.coffee
Normal file
14
services/web/test/unit_frontend/coffee/test-main.coffee
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Set up requirejs to load the tests
|
||||
# Uses heuristic that test filenames end with Tests.js
|
||||
tests = []
|
||||
for file of window.__karma__.files
|
||||
if window.__karma__.files.hasOwnProperty(file)
|
||||
if /Tests\.js$/.test(file)
|
||||
tests.push(file)
|
||||
|
||||
requirejs.config
|
||||
baseUrl: '/base/public/js'
|
||||
paths:
|
||||
"moment": "libs/moment-2.9.0"
|
||||
deps: tests
|
||||
callback: window.__karma__.start
|
Loading…
Add table
Reference in a new issue