mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-07-16 03:02:24 +00:00
Vue Project Setup (#8018)
* add files for new client side and reorg gulp tasks * add deps and script for new client * fix webpack paths so that building works * fix static assets not copied into prod build * fix linting * add eslint deps and re-enable it in webpack * add most missing deps for client side and split .babelrc for client * reorganize .eslintignore * update client tests paths and .gitignore * uncomment code * client: move App component * client: update oaths in App component * fix client tests and add more deps * add client side tests to npm test * fix typo in depencency name * update more deps * fix karma.conf.js and upgrade phantomjs * fix dep and move karma.conf to subdirectory * update karma.conf.js position in Gruntfile * try downgrading phantomjs * Fixup client tests (#8032) * Use phantom 2 * fix(tests): Fix refresher test * gitignore translation mock * Update karma version * disable e2e tests for new client from build * write vue templates with pug * add basic routing * remove unnecessary Function.bind shim * remove unused dependency
This commit is contained in:
parent
c615af82f8
commit
4f3a9802c1
59 changed files with 1095 additions and 216 deletions
|
|
@ -5,23 +5,22 @@ coverage/
|
|||
database_reports/
|
||||
website/build/
|
||||
website/transpiled-babel/
|
||||
dist/
|
||||
|
||||
# Not linted
|
||||
migrations/*
|
||||
|
||||
# The files in website/client-old/js should be moved out and browserified
|
||||
website/client-old/
|
||||
|
||||
# Temporarilly disabled. These should be removed when the linting errors are fixed
|
||||
website/common/script/content/index.js
|
||||
website/common/browserify.js
|
||||
|
||||
debug-scripts/*
|
||||
scripts/*
|
||||
tasks/*.js
|
||||
gulpfile.js
|
||||
Gruntfile.js
|
||||
newrelic.js
|
||||
|
||||
test/content/**/*
|
||||
test/server_side/**/*
|
||||
test/client-old/spec/**/*
|
||||
|
||||
# Temporarilly disabled. These should be removed when the linting errors are fixed TODO
|
||||
website/common/script/content/index.js
|
||||
website/common/browserify.js
|
||||
test/content/**/*
|
||||
Gruntfile.js
|
||||
gulpfile.js
|
||||
gulp
|
||||
webpack
|
||||
test/client
|
||||
12
.eslintrc
12
.eslintrc
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
"extends": [
|
||||
"habitrpg/server",
|
||||
"habitrpg/babel"
|
||||
"habitrpg/es6",
|
||||
"habitrpg"
|
||||
],
|
||||
"globals": {
|
||||
"Promise": true,
|
||||
"Set": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -32,8 +32,10 @@ website/client-old/docs
|
|||
coverage
|
||||
coverage.html
|
||||
common/dist/scripts/*
|
||||
|
||||
test/spec/mocks/translations.js
|
||||
dist
|
||||
test/client/unit/coverage
|
||||
test/client/e2e/reports
|
||||
test/client-old/spec/mocks/translations.js
|
||||
|
||||
# Elastic Beanstalk Files
|
||||
.elasticbeanstalk/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ website/client-old/**
|
|||
website/client/**
|
||||
website/views/**
|
||||
website/build/**
|
||||
dist/**
|
||||
test/**
|
||||
.git/**
|
||||
Gruntfile.js
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ module.exports = function(grunt) {
|
|||
|
||||
karma: {
|
||||
unit: {
|
||||
configFile: 'karma.conf.js'
|
||||
configFile: 'test/client-old/spec/karma.conf.js'
|
||||
},
|
||||
continuous: {
|
||||
configFile: 'karma.conf.js',
|
||||
configFile: 'test/client-old/spec/karma.conf.js',
|
||||
singleRun: true,
|
||||
autoWatch: false
|
||||
}
|
||||
|
|
|
|||
1
dist/habitrpg-shared.css
vendored
1
dist/habitrpg-shared.css
vendored
File diff suppressed because one or more lines are too long
10
gulp/.eslintrc
Normal file
10
gulp/.eslintrc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
"extends": [
|
||||
"habitrpg/server",
|
||||
"habitrpg/babel"
|
||||
],
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ gulp.task('apidoc', ['apidoc:clean'], (done) => {
|
|||
});
|
||||
|
||||
if (result === false) {
|
||||
done(new Error('There was a problem generating apiDoc documentation.'))
|
||||
done(new Error('There was a problem generating apiDoc documentation.'));
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
|
|
@ -10,11 +10,11 @@ let improveRepl = (context) => {
|
|||
|
||||
// Let "exit" and "quit" terminate the console
|
||||
['exit', 'quit'].forEach((term) => {
|
||||
Object.defineProperty(context, term, { get() { process.exit(); }});
|
||||
Object.defineProperty(context, term, { get () { process.exit(); }});
|
||||
});
|
||||
|
||||
// "clear" clears the screen
|
||||
Object.defineProperty(context, 'clear', { get() {
|
||||
Object.defineProperty(context, 'clear', { get () {
|
||||
process.stdout.write('\u001B[2J\u001B[0;0f');
|
||||
}});
|
||||
|
||||
|
|
@ -25,13 +25,13 @@ let improveRepl = (context) => {
|
|||
var isProd = nconf.get('NODE_ENV') === 'production';
|
||||
var mongooseOptions = !isProd ? {} : {
|
||||
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
|
||||
server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
|
||||
server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
|
||||
};
|
||||
autoinc.init(
|
||||
mongoose.connect(
|
||||
nconf.get('NODE_DB_URI'),
|
||||
mongooseOptions,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) throw err;
|
||||
logger.info('Connected with Mongoose');
|
||||
}
|
||||
|
|
@ -42,6 +42,6 @@ let improveRepl = (context) => {
|
|||
|
||||
gulp.task('console', (cb) => {
|
||||
improveRepl(repl.start({
|
||||
prompt: 'Habitica > '
|
||||
prompt: 'Habitica > ',
|
||||
}).context);
|
||||
});
|
||||
|
|
@ -52,7 +52,7 @@ gulp.task('sprites:checkCompiledDimensions', ['sprites:main', 'sprites:largeSpri
|
|||
}
|
||||
});
|
||||
|
||||
function createSpritesStream(name, src) {
|
||||
function createSpritesStream (name, src) {
|
||||
let spritesheetSliceIndicies = calculateSpritesheetsSrcIndicies(src);
|
||||
let stream = mergeStream();
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ function createSpritesStream(name, src) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
function calculateSpritesheetsSrcIndicies(src) {
|
||||
function calculateSpritesheetsSrcIndicies (src) {
|
||||
let totalPixels = 0;
|
||||
let slices = [0];
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ function calculateSpritesheetsSrcIndicies(src) {
|
|||
return slices;
|
||||
}
|
||||
|
||||
function calculateImgDimensions(img, addPadding) {
|
||||
function calculateImgDimensions (img, addPadding) {
|
||||
let dims = sizeOf(img);
|
||||
|
||||
let requiresSpecialTreatment = checkForSpecialTreatment(img);
|
||||
|
|
@ -109,7 +109,7 @@ function calculateImgDimensions(img, addPadding) {
|
|||
let newHeight = dims.height < 90 ? 90 : dims.height;
|
||||
dims = {
|
||||
width: newWidth,
|
||||
height: newHeight
|
||||
height: newHeight,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -119,19 +119,19 @@ function calculateImgDimensions(img, addPadding) {
|
|||
padding = (dims.width * 8) + (dims.height * 8);
|
||||
}
|
||||
|
||||
if(!dims.width || !dims.height) console.error('MISSING DIMENSIONS:', dims);
|
||||
if (!dims.width || !dims.height) console.error('MISSING DIMENSIONS:', dims);
|
||||
|
||||
let totalPixelSize = (dims.width * dims.height) + padding;
|
||||
|
||||
return totalPixelSize;
|
||||
}
|
||||
|
||||
function checkForSpecialTreatment(name) {
|
||||
function checkForSpecialTreatment (name) {
|
||||
let regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame/;
|
||||
return name.match(regex) || name === 'head_0';
|
||||
}
|
||||
|
||||
function cssVarMap(sprite) {
|
||||
function cssVarMap (sprite) {
|
||||
// For hair, skins, beards, etc. we want to output a '.customize-options.WHATEVER' class, which works as a
|
||||
// 60x60 image pointing at the proper part of the 90x90 sprite.
|
||||
// We set up the custom info here, and the template makes use of it.
|
||||
|
|
@ -142,9 +142,9 @@ function cssVarMap(sprite) {
|
|||
offset_x: `-${ sprite.x + 25 }px`,
|
||||
offset_y: `-${ sprite.y + 15 }px`,
|
||||
width: '60px',
|
||||
height: '60px'
|
||||
}
|
||||
}
|
||||
height: '60px',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (~sprite.name.indexOf('shirt'))
|
||||
sprite.custom.px.offset_y = `-${ sprite.y + 30 }px`; // even more for shirts
|
||||
|
|
@ -12,6 +12,6 @@ gulp.task('nodemon', () => {
|
|||
'website/client-old/*',
|
||||
'website/views/*',
|
||||
'common/dist/script/content/*',
|
||||
]
|
||||
],
|
||||
});
|
||||
});
|
||||
|
|
@ -16,7 +16,7 @@ import nconf from 'nconf';
|
|||
|
||||
// TODO rewrite
|
||||
|
||||
const TEST_SERVER_PORT = 3003
|
||||
const TEST_SERVER_PORT = 3003;
|
||||
let server;
|
||||
|
||||
const TEST_DB_URI = nconf.get('TEST_DB_URI');
|
||||
|
|
@ -33,11 +33,11 @@ let testResults = [];
|
|||
let testCount = (stdout, regexp) => {
|
||||
let match = stdout.match(regexp);
|
||||
return parseInt(match && match[1] || 0);
|
||||
}
|
||||
};
|
||||
|
||||
let testBin = (string, additionalEnvVariables = '') => {
|
||||
if(os.platform() === "win32") {
|
||||
if(additionalEnvVariables != '') {
|
||||
if (os.platform() === 'win32') {
|
||||
if (additionalEnvVariables != '') {
|
||||
additionalEnvVariables = additionalEnvVariables.split(' ').join('&&set ');
|
||||
additionalEnvVariables = 'set ' + additionalEnvVariables + '&&';
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ let testBin = (string, additionalEnvVariables = '') => {
|
|||
|
||||
gulp.task('test:nodemon', (done) => {
|
||||
process.env.PORT = TEST_SERVER_PORT;
|
||||
process.env.NODE_DB_URI=TEST_DB_URI;
|
||||
process.env.NODE_DB_URI = TEST_DB_URI;
|
||||
|
||||
runSequence('nodemon');
|
||||
});
|
||||
|
|
@ -65,7 +65,7 @@ gulp.task('test:prepare:mongo', (cb) => {
|
|||
|
||||
gulp.task('test:prepare:server', ['test:prepare:mongo'], () => {
|
||||
if (!server) {
|
||||
server = exec(testBin(`node ./website/server/index.js`, `NODE_DB_URI=${TEST_DB_URI} PORT=${TEST_SERVER_PORT}`), (error, stdout, stderr) => {
|
||||
server = exec(testBin('node ./website/server/index.js', `NODE_DB_URI=${TEST_DB_URI} PORT=${TEST_SERVER_PORT}`), (error, stdout, stderr) => {
|
||||
if (error) { throw `Problem with the server: ${error}`; }
|
||||
if (stderr) { console.error(stderr); }
|
||||
});
|
||||
|
|
@ -83,7 +83,7 @@ gulp.task('test:prepare:webdriver', (cb) => {
|
|||
gulp.task('test:prepare', [
|
||||
'test:prepare:build',
|
||||
'test:prepare:mongo',
|
||||
'test:prepare:webdriver'
|
||||
'test:prepare:webdriver',
|
||||
]);
|
||||
|
||||
gulp.task('test:sanity', (cb) => {
|
||||
|
|
@ -128,7 +128,7 @@ gulp.task('test:common:safe', ['test:prepare:build'], (cb) => {
|
|||
suite: 'Common Specs\t',
|
||||
pass: testCount(stdout, /(\d+) passing/),
|
||||
fail: testCount(stdout, /(\d+) failing/),
|
||||
pend: testCount(stdout, /(\d+) pending/)
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
cb();
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ gulp.task('test:content:safe', ['test:prepare:build'], (cb) => {
|
|||
suite: 'Content Specs\t',
|
||||
pass: testCount(stdout, /(\d+) passing/),
|
||||
fail: testCount(stdout, /(\d+) failing/),
|
||||
pend: testCount(stdout, /(\d+) pending/)
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
cb();
|
||||
}
|
||||
|
|
@ -193,7 +193,7 @@ gulp.task('test:server_side:safe', ['test:prepare:build'], (cb) => {
|
|||
suite: 'Server Side Specs',
|
||||
pass: testCount(stdout, /(\d+) passing/),
|
||||
fail: testCount(stdout, /(\d+) failing/),
|
||||
pend: testCount(stdout, /(\d+) pending/)
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
cb();
|
||||
}
|
||||
|
|
@ -232,7 +232,7 @@ gulp.task('test:karma:safe', ['test:prepare:build'], (cb) => {
|
|||
suite: 'Karma Specs\t',
|
||||
pass: testCount(stdout, /(\d+) tests? completed/),
|
||||
fail: testCount(stdout, /(\d+) tests? failed/),
|
||||
pend: testCount(stdout, /(\d+) tests? skipped/)
|
||||
pend: testCount(stdout, /(\d+) tests? skipped/),
|
||||
});
|
||||
cb();
|
||||
}
|
||||
|
|
@ -249,7 +249,7 @@ gulp.task('test:e2e', ['test:prepare', 'test:prepare:server'], (cb) => {
|
|||
|
||||
Bluebird.all([
|
||||
awaitPort(TEST_SERVER_PORT),
|
||||
awaitPort(4444)
|
||||
awaitPort(4444),
|
||||
]).then(() => {
|
||||
let runner = exec(
|
||||
'npm run test:e2e',
|
||||
|
|
@ -273,7 +273,7 @@ gulp.task('test:e2e:safe', ['test:prepare', 'test:prepare:server'], (cb) => {
|
|||
|
||||
Bluebird.all([
|
||||
awaitPort(TEST_SERVER_PORT),
|
||||
awaitPort(4444)
|
||||
awaitPort(4444),
|
||||
]).then(() => {
|
||||
let runner = exec(
|
||||
'npm run test:e2e',
|
||||
|
|
@ -284,7 +284,7 @@ gulp.task('test:e2e:safe', ['test:prepare', 'test:prepare:server'], (cb) => {
|
|||
suite: 'End-to-End Specs\t',
|
||||
pass: testCount(stdout, /(\d+) passing/),
|
||||
fail: testCount(stdout, /(\d+) failing/),
|
||||
pend: testCount(stdout, /(\d+) pending/)
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
support.forEach(kill);
|
||||
cb();
|
||||
|
|
@ -303,7 +303,7 @@ gulp.task('test:api-v3:unit', (done) => {
|
|||
}
|
||||
done();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
|
@ -315,14 +315,14 @@ gulp.task('test:api-v3:unit:watch', () => {
|
|||
gulp.task('test:api-v3:integration', (done) => {
|
||||
let runner = exec(
|
||||
testBin('mocha test/api/v3/integration --recursive'),
|
||||
{maxBuffer: 500*1024},
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err, stdout, stderr) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
done();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
|
@ -335,9 +335,9 @@ gulp.task('test:api-v3:integration:watch', () => {
|
|||
gulp.task('test:api-v3:integration:separate-server', (done) => {
|
||||
let runner = exec(
|
||||
testBin('mocha test/api/v3/integration --recursive', 'LOAD_SERVER=0'),
|
||||
{maxBuffer: 500*1024},
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err, stdout, stderr) => done(err)
|
||||
)
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
|
@ -7,8 +7,8 @@ import { postToSlack, conf } from './taskHelper';
|
|||
const SLACK_CONFIG = {
|
||||
channel: conf.get('TRANSIFEX_SLACK_CHANNEL'),
|
||||
username: 'Transifex',
|
||||
emoji: 'transifex'
|
||||
}
|
||||
emoji: 'transifex',
|
||||
};
|
||||
|
||||
const LOCALES = './website/common/locales/';
|
||||
const ENGLISH_LOCALE = `${LOCALES}en/`;
|
||||
|
|
@ -17,8 +17,8 @@ const ALL_LANGUAGES = getArrayOfLanguages();
|
|||
const malformedStringExceptions = {
|
||||
messageDropFood: true,
|
||||
armoireFood: true,
|
||||
feedPet: true
|
||||
}
|
||||
feedPet: true,
|
||||
};
|
||||
|
||||
gulp.task('transifex', ['transifex:missingFiles', 'transifex:missingStrings', 'transifex:malformedStrings']);
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ gulp.task('transifex:missingFiles', () => {
|
|||
let missingStrings = [];
|
||||
|
||||
eachTranslationFile(ALL_LANGUAGES, (error) => {
|
||||
if(error) {
|
||||
if (error) {
|
||||
missingStrings.push(error.path);
|
||||
}
|
||||
});
|
||||
|
|
@ -67,13 +67,13 @@ gulp.task('transifex:malformedStrings', () => {
|
|||
let stringsWithIncorrectNumberOfInterpolations = [];
|
||||
|
||||
let count = 0;
|
||||
_(ALL_LANGUAGES).each(function(lang) {
|
||||
_(ALL_LANGUAGES).each(function (lang) {
|
||||
|
||||
_.each(stringsToLookFor, function(strings, file) {
|
||||
_.each(stringsToLookFor, function (strings, file) {
|
||||
let translationFile = fs.readFileSync(LOCALES + lang + '/' + file);
|
||||
let parsedTranslationFile = JSON.parse(translationFile);
|
||||
|
||||
_.each(strings, function(value, key) {
|
||||
_.each(strings, function (value, key) {
|
||||
let translationString = parsedTranslationFile[key];
|
||||
if (!translationString) return;
|
||||
|
||||
|
|
@ -104,14 +104,14 @@ gulp.task('transifex:malformedStrings', () => {
|
|||
}
|
||||
});
|
||||
|
||||
function getArrayOfLanguages() {
|
||||
function getArrayOfLanguages () {
|
||||
let languages = fs.readdirSync(LOCALES);
|
||||
languages.shift(); // Remove README.md from array of languages
|
||||
|
||||
return languages;
|
||||
}
|
||||
|
||||
function eachTranslationFile(languages, cb) {
|
||||
function eachTranslationFile (languages, cb) {
|
||||
let jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||
|
||||
_(languages).each((lang) => {
|
||||
|
|
@ -126,12 +126,12 @@ function eachTranslationFile(languages, cb) {
|
|||
let englishFile = fs.readFileSync(ENGLISH_LOCALE + filename);
|
||||
let parsedEnglishFile = JSON.parse(englishFile);
|
||||
|
||||
cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile)
|
||||
cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile);
|
||||
});
|
||||
}).value();
|
||||
}
|
||||
|
||||
function eachTranslationString(languages, cb) {
|
||||
function eachTranslationString (languages, cb) {
|
||||
eachTranslationFile(languages, (error, language, filename, englishJSON, translationJSON) => {
|
||||
if (error) return;
|
||||
_.each(englishJSON, (string, key) => {
|
||||
|
|
@ -141,7 +141,7 @@ function eachTranslationString(languages, cb) {
|
|||
});
|
||||
}
|
||||
|
||||
function formatMessageForPosting(msg, items) {
|
||||
function formatMessageForPosting (msg, items) {
|
||||
let body = `*Warning:* ${msg}`;
|
||||
body += '\n\n```\n';
|
||||
body += items.join('\n');
|
||||
|
|
@ -150,24 +150,24 @@ function formatMessageForPosting(msg, items) {
|
|||
return body;
|
||||
}
|
||||
|
||||
function getStringsWith(json, interpolationRegex) {
|
||||
function getStringsWith (json, interpolationRegex) {
|
||||
var strings = {};
|
||||
|
||||
_(json).each(function(file_name) {
|
||||
_(json).each(function (file_name) {
|
||||
var raw_file = fs.readFileSync(ENGLISH_LOCALE + file_name);
|
||||
var parsed_json = JSON.parse(raw_file);
|
||||
|
||||
strings[file_name] = {};
|
||||
_.each(parsed_json, function(value, key) {
|
||||
_.each(parsed_json, function (value, key) {
|
||||
var match = value.match(interpolationRegex);
|
||||
if(match) strings[file_name][key] = match;
|
||||
if (match) strings[file_name][key] = match;
|
||||
});
|
||||
}).value();
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
function stripOutNonJsonFiles(collection) {
|
||||
function stripOutNonJsonFiles (collection) {
|
||||
let onlyJson = _.filter(collection, (file) => {
|
||||
return file.match(/[a-zA-Z]*\.json/);
|
||||
});
|
||||
|
|
@ -19,23 +19,23 @@ export var conf = nconf;
|
|||
* This is necessary to ensure that Gulp will terminate when it has completed
|
||||
* its tasks.
|
||||
*/
|
||||
export function kill(proc) {
|
||||
export function kill (proc) {
|
||||
let killProcess = (pid) => {
|
||||
psTree(pid, (_, pids) => {
|
||||
if(pids.length) {
|
||||
pids.forEach(kill); return
|
||||
if (pids.length) {
|
||||
pids.forEach(kill); return;
|
||||
}
|
||||
try {
|
||||
exec(/^win/.test(process.platform)
|
||||
? `taskkill /PID ${pid} /T /F`
|
||||
: `kill -9 ${pid}`)
|
||||
: `kill -9 ${pid}`);
|
||||
}
|
||||
catch(e) { console.log(e) }
|
||||
catch (e) { console.log(e); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
killProcess(proc.PID || proc.pid);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a promise that will execute when Node is able to connect on a
|
||||
|
|
@ -43,7 +43,7 @@ export function kill(proc) {
|
|||
* has fully spun up. Optionally provide a maximum number of seconds to wait
|
||||
* before failing.
|
||||
*/
|
||||
export function awaitPort (port, max=60) {
|
||||
export function awaitPort (port, max = 60) {
|
||||
return new Bluebird((reject, resolve) => {
|
||||
let socket, timeout, interval;
|
||||
|
||||
|
|
@ -58,23 +58,23 @@ export function awaitPort (port, max=60) {
|
|||
clearTimeout(timeout);
|
||||
socket.destroy();
|
||||
resolve();
|
||||
}).on('error', () => { socket.destroy });
|
||||
}).on('error', () => { socket.destroy; });
|
||||
}, 1000);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Pipe the child's stdin and stderr to the parent process.
|
||||
*/
|
||||
export function pipe(child) {
|
||||
child.stdout.on('data', (data) => { process.stdout.write(data) });
|
||||
child.stderr.on('data', (data) => { process.stderr.write(data) });
|
||||
};
|
||||
export function pipe (child) {
|
||||
child.stdout.on('data', (data) => { process.stdout.write(data); });
|
||||
child.stderr.on('data', (data) => { process.stderr.write(data); });
|
||||
}
|
||||
|
||||
/*
|
||||
* Post request to notify configured slack channel
|
||||
*/
|
||||
export function postToSlack(msg, config={}) {
|
||||
export function postToSlack (msg, config = {}) {
|
||||
let slackUrl = nconf.get('SLACK_URL');
|
||||
|
||||
if (!slackUrl) {
|
||||
|
|
@ -89,14 +89,14 @@ export function postToSlack(msg, config={}) {
|
|||
channel: `#${config.channel || '#general'}`,
|
||||
username: config.username || 'gulp task',
|
||||
text: msg,
|
||||
icon_emoji: `:${config.emoji || 'gulp'}:`
|
||||
icon_emoji: `:${config.emoji || 'gulp'}:`,
|
||||
})
|
||||
.end((err, res) => {
|
||||
if (err) console.error('Unable to post to slack', err);
|
||||
});
|
||||
}
|
||||
|
||||
export function runMochaTests(files, server, cb) {
|
||||
export function runMochaTests (files, server, cb) {
|
||||
require('../test/helpers/globals.helper');
|
||||
|
||||
let mocha = new Mocha({reporter: 'spec'});
|
||||
10
gulpfile.js
10
gulpfile.js
|
|
@ -9,11 +9,11 @@
|
|||
require('babel-register');
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
require('./tasks/gulp-apidoc');
|
||||
require('./tasks/gulp-newstuff');
|
||||
require('./tasks/gulp-build');
|
||||
require('./tasks/gulp-babelify');
|
||||
require('./gulp/gulp-apidoc');
|
||||
require('./gulp/gulp-newstuff');
|
||||
require('./gulp/gulp-build');
|
||||
require('./gulp/gulp-babelify');
|
||||
} else {
|
||||
require('glob').sync('./tasks/gulp-*').forEach(require);
|
||||
require('glob').sync('./gulp/gulp-*').forEach(require);
|
||||
require('gulp').task('default', ['test']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
// Karma configuration
|
||||
// http://karma-runner.github.io/0.10/config/configuration-file.html
|
||||
|
||||
module.exports = function karmaConfig (config) {
|
||||
config.set({
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath: '',
|
||||
|
||||
// testing framework to use (jasmine/mocha/qunit/...)
|
||||
frameworks: ['mocha', 'chai', 'chai-as-promised', 'sinon-chai'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'website/client-old/bower_components/jquery/dist/jquery.js',
|
||||
'website/client-old/bower_components/pnotify/jquery.pnotify.js',
|
||||
'website/client-old/bower_components/angular/angular.js',
|
||||
'website/client-old/bower_components/angular-loading-bar/build/loading-bar.min.js',
|
||||
'website/client-old/bower_components/angular-resource/angular-resource.min.js',
|
||||
'website/client-old/bower_components/hello/dist/hello.all.min.js',
|
||||
'website/client-old/bower_components/angular-sanitize/angular-sanitize.js',
|
||||
'website/client-old/bower_components/bootstrap/dist/js/bootstrap.js',
|
||||
'website/client-old/bower_components/angular-bootstrap/ui-bootstrap.js',
|
||||
'website/client-old/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
|
||||
'website/client-old/bower_components/angular-ui-router/release/angular-ui-router.js',
|
||||
'website/client-old/bower_components/angular-filter/dist/angular-filter.js',
|
||||
'website/client-old/bower_components/angular-ui/build/angular-ui.js',
|
||||
'website/client-old/bower_components/angular-ui-utils/ui-utils.min.js',
|
||||
'website/client-old/bower_components/Angular-At-Directive/src/at.js',
|
||||
'website/client-old/bower_components/Angular-At-Directive/src/caret.js',
|
||||
'website/client-old/bower_components/angular-mocks/angular-mocks.js',
|
||||
'website/client-old/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
|
||||
'website/client-old/bower_components/select2/select2.js',
|
||||
'website/client-old/bower_components/angular-ui-select2/src/select2.js',
|
||||
'website/client-old/bower_components/habitica-markdown/dist/habitica-markdown.min.js',
|
||||
'website/client-old/js/habitrpg-shared.js',
|
||||
|
||||
'test/client-old/spec/mocks/**/*.js',
|
||||
|
||||
'website/client-old/js/env.js',
|
||||
'website/client-old/js/app.js',
|
||||
'common/script/public/config.js',
|
||||
'common/script/public/directives.js',
|
||||
|
||||
'website/client-old/js/services/**/*.js',
|
||||
'website/client-old/js/filters/**/*.js',
|
||||
'website/client-old/js/directives/**/*.js',
|
||||
'website/client-old/js/controllers/**/*.js',
|
||||
|
||||
'test/client-old/spec/specHelper.js',
|
||||
'test/client-old/spec/**/*.js',
|
||||
],
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [],
|
||||
|
||||
// web server port
|
||||
port: 8080,
|
||||
|
||||
// level of logging
|
||||
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera
|
||||
// - Safari (only Mac)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows)
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
preprocessors: {
|
||||
'website/client-old/js/**/*.js': ['coverage'],
|
||||
'test/**/*.js': ['babel'],
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
type: 'lcov',
|
||||
dir: 'coverage/karma',
|
||||
},
|
||||
|
||||
// Enable mocha-style reporting, for better test visibility
|
||||
reporters: ['mocha', 'coverage'],
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun: false,
|
||||
});
|
||||
};
|
||||
7
npm-shrinkwrap.json
generated
7
npm-shrinkwrap.json
generated
|
|
@ -655,7 +655,7 @@
|
|||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.11.6",
|
||||
"from": "babel-runtime@>=6.0.0 <7.0.0",
|
||||
"from": "babel-runtime@>=6.11.6 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.11.6.tgz"
|
||||
},
|
||||
"babel-template": {
|
||||
|
|
@ -8820,6 +8820,11 @@
|
|||
"from": "void-elements@>=2.0.1 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz"
|
||||
},
|
||||
"vue": {
|
||||
"version": "2.0.0-rc.6",
|
||||
"from": "vue@>=2.0.0-rc.6 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.0.0-rc.6.tgz"
|
||||
},
|
||||
"w3counter": {
|
||||
"version": "2.0.1",
|
||||
"from": "w3counter@>=2.0.0 <3.0.0",
|
||||
|
|
|
|||
63
package.json
63
package.json
|
|
@ -16,6 +16,7 @@
|
|||
"babel-polyfill": "^6.6.1",
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-register": "^6.6.0",
|
||||
"babel-runtime": "^6.11.6",
|
||||
"babelify": "^7.2.0",
|
||||
"bluebird": "^3.3.5",
|
||||
"body-parser": "^1.15.0",
|
||||
|
|
@ -93,6 +94,8 @@
|
|||
"validator": "^4.9.0",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"vue": "^2.0.0-rc.6",
|
||||
"vue-router": "^2.0.0-rc.5",
|
||||
"winston": "^2.1.0",
|
||||
"xml2js": "^0.4.4"
|
||||
},
|
||||
|
|
@ -102,8 +105,8 @@
|
|||
"npm": "^3.8.9"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "npm run lint && gulp test",
|
||||
"lint": "eslint --ext .js,.vue .",
|
||||
"test": "npm run lint && gulp test && npm run client:unit",
|
||||
"test:api-v3": "gulp test:api-v3",
|
||||
"test:api-v3:unit": "gulp test:api-v3:unit",
|
||||
"test:api-v3:integration": "gulp test:api-v3:integration",
|
||||
|
|
@ -111,8 +114,8 @@
|
|||
"test:sanity": "mocha test/sanity --recursive",
|
||||
"test:common": "mocha test/common --recursive",
|
||||
"test:content": "mocha test/content --recursive",
|
||||
"test:karma": "karma start --single-run",
|
||||
"test:karma:watch": "karma start",
|
||||
"test:karma": "karma start test/client-old/spec/karma.conf.js --single-run",
|
||||
"test:karma:watch": "karma start test/client-old/spec/karma.conf.js",
|
||||
"test:prepare:webdriver": "webdriver-manager update",
|
||||
"test:e2e:webdriver": "webdriver-manager start",
|
||||
"test:e2e": "protractor test/client-old/e2e/protractor.conf.js",
|
||||
|
|
@ -120,43 +123,83 @@
|
|||
"start": "gulp run:dev",
|
||||
"sprites": "gulp sprites:compile",
|
||||
"postinstall": "bower --config.interactive=false install -f; gulp build;",
|
||||
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html"
|
||||
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html",
|
||||
"client:dev": "node webpack/dev-server.js",
|
||||
"client:build": "node webpack/build.js",
|
||||
"client:unit": "karma start test/client/unit/karma.conf.js --single-run",
|
||||
"client:e2e": "node test/client/e2e/runner.js",
|
||||
"client:test": "npm run client:unit && npm run client:e2e"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.4.0",
|
||||
"babel-core": "^6.0.0",
|
||||
"babel-eslint": "^6.0.0",
|
||||
"babel-loader": "^6.0.0",
|
||||
"babel-plugin-transform-runtime": "^6.0.0",
|
||||
"chai": "^3.4.0",
|
||||
"chai-as-promised": "^5.1.0",
|
||||
"chalk": "^1.1.3",
|
||||
"chromedriver": "^2.21.2",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"coveralls": "^2.11.2",
|
||||
"cross-spawn": "^2.1.5",
|
||||
"css-loader": "^0.23.0",
|
||||
"csv": "~0.3.6",
|
||||
"deep-diff": "~0.1.4",
|
||||
"eslint": "~2.12.0",
|
||||
"eslint-config-habitrpg": "^1.0.0",
|
||||
"eslint-friendly-formatter": "^2.0.5",
|
||||
"eslint-loader": "^1.3.0",
|
||||
"eslint-plugin-babel": "^3.0.0",
|
||||
"eslint-plugin-html": "^1.3.0",
|
||||
"eslint-plugin-mocha": "^2.1.0",
|
||||
"event-stream": "^3.2.2",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"expect.js": "~0.2.0",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.4",
|
||||
"html-webpack-plugin": "^2.8.1",
|
||||
"http-proxy-middleware": "^0.12.0",
|
||||
"inject-loader": "^2.0.1",
|
||||
"isparta-loader": "^2.0.0",
|
||||
"istanbul": "^0.3.14",
|
||||
"karma": "~0.13.15",
|
||||
"json-loader": "^0.5.4",
|
||||
"karma": "^1.3.0",
|
||||
"karma-babel-preprocessor": "^6.0.1",
|
||||
"karma-chai-plugins": "~0.6.0",
|
||||
"karma-coverage": "^0.5.3",
|
||||
"karma-mocha": "^0.2.0",
|
||||
"karma-mocha-reporter": "^1.1.1",
|
||||
"karma-phantomjs-launcher": "~0.2.1",
|
||||
"karma-phantomjs-launcher": "^1.0.0",
|
||||
"karma-sinon-chai": "^1.2.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.24",
|
||||
"karma-webpack": "^1.7.0",
|
||||
"lcov-result-merger": "^1.0.2",
|
||||
"lolex": "^1.4.0",
|
||||
"mocha": "^2.3.3",
|
||||
"mongodb": "^2.0.46",
|
||||
"mongoskin": "~2.1.0",
|
||||
"phantomjs": "^1.9",
|
||||
"nightwatch": "^0.8.18",
|
||||
"ora": "^0.2.0",
|
||||
"phantomjs-prebuilt": "^2.1.12",
|
||||
"protractor": "^3.1.1",
|
||||
"pug": "^2.0.0-beta6",
|
||||
"require-again": "^2.0.0",
|
||||
"rewire": "^2.3.3",
|
||||
"shelljs": "^0.7.0",
|
||||
"selenium-server": "2.53.0",
|
||||
"shelljs": "^0.6.0",
|
||||
"sinon": "^1.17.2",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"superagent-defaults": "^0.1.13",
|
||||
"url-loader": "^0.5.7",
|
||||
"vinyl-source-stream": "^1.0.0",
|
||||
"vinyl-transform": "^1.0.0"
|
||||
"vinyl-transform": "^1.0.0",
|
||||
"vue-hot-reload-api": "^1.2.0",
|
||||
"vue-loader": "^9.4.0",
|
||||
"webpack": "^1.12.2",
|
||||
"webpack-dev-middleware": "^1.4.0",
|
||||
"webpack-hot-middleware": "^2.6.0",
|
||||
"webpack-merge": "^0.8.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
"habitrpg/mocha",
|
||||
"habitrpg/babel"
|
||||
],
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
"globals": {
|
||||
"_": true,
|
||||
"Promise": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs';
|
||||
import { resetHabiticaDB } from '../../helpers/api-integration/mongo';
|
||||
import { resetHabiticaDB } from '../../helpers/mongo';
|
||||
|
||||
before(async () => {
|
||||
await resetHabiticaDB();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ describe('AppJS', function() {
|
|||
|
||||
it('should call refresher if idle time is 6 hours or greater', function() {
|
||||
window.awaitIdle();
|
||||
clock.tick(21600000);
|
||||
clock.tick(21900000);
|
||||
expect(window.refresher).to.be.called;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
94
test/client-old/spec/karma.conf.js
Normal file
94
test/client-old/spec/karma.conf.js
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
// Karma configuration
|
||||
// http://karma-runner.github.io/0.10/config/configuration-file.html
|
||||
|
||||
module.exports = function karmaConfig (config) {
|
||||
config.set({
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath: '',
|
||||
|
||||
// testing framework to use (jasmine/mocha/qunit/...)
|
||||
frameworks: ['mocha', 'chai', 'chai-as-promised', 'sinon-chai'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'../../../website/client-old/bower_components/jquery/dist/jquery.js',
|
||||
'../../../website/client-old/bower_components/pnotify/jquery.pnotify.js',
|
||||
'../../../website/client-old/bower_components/angular/angular.js',
|
||||
'../../../website/client-old/bower_components/angular-loading-bar/build/loading-bar.min.js',
|
||||
'../../../website/client-old/bower_components/angular-resource/angular-resource.min.js',
|
||||
'../../../website/client-old/bower_components/hello/dist/hello.all.min.js',
|
||||
'../../../website/client-old/bower_components/angular-sanitize/angular-sanitize.js',
|
||||
'../../../website/client-old/bower_components/bootstrap/dist/js/bootstrap.js',
|
||||
'../../../website/client-old/bower_components/angular-bootstrap/ui-bootstrap.js',
|
||||
'../../../website/client-old/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
|
||||
'../../../website/client-old/bower_components/angular-ui-router/release/angular-ui-router.js',
|
||||
'../../../website/client-old/bower_components/angular-filter/dist/angular-filter.js',
|
||||
'../../../website/client-old/bower_components/angular-ui/build/angular-ui.js',
|
||||
'../../../website/client-old/bower_components/angular-ui-utils/ui-utils.min.js',
|
||||
'../../../website/client-old/bower_components/Angular-At-Directive/src/at.js',
|
||||
'../../../website/client-old/bower_components/Angular-At-Directive/src/caret.js',
|
||||
'../../../website/client-old/bower_components/angular-mocks/angular-mocks.js',
|
||||
'../../../website/client-old/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
|
||||
'../../../website/client-old/bower_components/select2/select2.js',
|
||||
'../../../website/client-old/bower_components/angular-ui-select2/src/select2.js',
|
||||
'../../../website/client-old/bower_components/habitica-markdown/dist/habitica-markdown.min.js',
|
||||
'../../../website/client-old/js/habitrpg-shared.js',
|
||||
|
||||
'../../../test/client-old/spec/mocks/**/*.js',
|
||||
|
||||
'../../../website/client-old/js/env.js',
|
||||
'../../../website/client-old/js/app.js',
|
||||
'../../../website/client-old/js/config.js',
|
||||
|
||||
'../../../website/client-old/js/services/**/*.js',
|
||||
'../../../website/client-old/js/filters/**/*.js',
|
||||
'../../../website/client-old/js/directives/**/*.js',
|
||||
'../../../website/client-old/js/controllers/**/*.js',
|
||||
|
||||
'../../../test/client-old/spec/specHelper.js',
|
||||
'../../../test/client-old/spec/**/*.js',
|
||||
],
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [],
|
||||
|
||||
// web server port
|
||||
port: 8080,
|
||||
|
||||
// level of logging
|
||||
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera
|
||||
// - Safari (only Mac)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows)
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
preprocessors: {
|
||||
'../../../website/client-old/js/**/*.js': ['coverage'],
|
||||
'../../../test/**/*.js': ['babel'],
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
type: 'lcov',
|
||||
dir: 'coverage/karma',
|
||||
},
|
||||
|
||||
// Enable mocha-style reporting, for better test visibility
|
||||
reporters: ['mocha', 'coverage'],
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun: false,
|
||||
});
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
3
test/client/README.md
Normal file
3
test/client/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
This folder contains the test files for the new client side that is being developed.
|
||||
|
||||
The old client side tests can be found in /test/client-old.
|
||||
26
test/client/e2e/custom-assertions/elementCount.js
Normal file
26
test/client/e2e/custom-assertions/elementCount.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// A custom Nightwatch assertion.
|
||||
// the name of the method is the filename.
|
||||
// can be used in tests like this:
|
||||
//
|
||||
// browser.assert.elementCount(selector, count)
|
||||
//
|
||||
// for how to write custom assertions see
|
||||
// http://nightwatchjs.org/guide#writing-custom-assertions
|
||||
exports.assertion = function (selector, count) {
|
||||
this.message = 'Testing if element <' + selector + '> has count: ' + count;
|
||||
this.expected = count;
|
||||
this.pass = function (val) {
|
||||
return val === this.expected;
|
||||
};
|
||||
this.value = function (res) {
|
||||
return res.value;
|
||||
};
|
||||
this.command = function (cb) {
|
||||
var self = this;
|
||||
return this.api.execute(function (selector) {
|
||||
return document.querySelectorAll(selector).length;
|
||||
}, [selector], function (res) {
|
||||
cb.call(self, res);
|
||||
});
|
||||
};
|
||||
};
|
||||
46
test/client/e2e/nightwatch.conf.js
Normal file
46
test/client/e2e/nightwatch.conf.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
require('babel-register');
|
||||
var config = require('../../../webpack/config');
|
||||
|
||||
// http://nightwatchjs.org/guide#settings-file
|
||||
module.exports = {
|
||||
'src_folders': ['test/client/e2e/specs'],
|
||||
'output_folder': 'test/client/e2e/reports',
|
||||
'custom_assertions_path': ['test/client/e2e/custom-assertions'],
|
||||
|
||||
'selenium': {
|
||||
'start_process': true,
|
||||
'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar',
|
||||
'host': '127.0.0.1',
|
||||
'port': 4444,
|
||||
'cli_args': {
|
||||
'webdriver.chrome.driver': require('chromedriver').path,
|
||||
},
|
||||
},
|
||||
|
||||
'test_settings': {
|
||||
'default': {
|
||||
'selenium_port': 4444,
|
||||
'selenium_host': 'localhost',
|
||||
'silent': true,
|
||||
'globals': {
|
||||
'devServerURL': 'http://localhost:' + (process.env.PORT || config.dev.port),
|
||||
},
|
||||
},
|
||||
|
||||
'chrome': {
|
||||
'desiredCapabilities': {
|
||||
'browserName': 'chrome',
|
||||
'javascriptEnabled': true,
|
||||
'acceptSslCerts': true,
|
||||
},
|
||||
},
|
||||
|
||||
'firefox': {
|
||||
'desiredCapabilities': {
|
||||
'browserName': 'firefox',
|
||||
'javascriptEnabled': true,
|
||||
'acceptSslCerts': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
31
test/client/e2e/runner.js
Normal file
31
test/client/e2e/runner.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// 1. start the dev server using production config
|
||||
process.env.NODE_ENV = 'testing';
|
||||
var server = require('../../../webpack/dev-server.js');
|
||||
|
||||
// 2. run the nightwatch test suite against it
|
||||
// to run in additional browsers:
|
||||
// 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
|
||||
// 2. add it to the --env flag below
|
||||
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
|
||||
// For more information on Nightwatch's config file, see
|
||||
// http://nightwatchjs.org/guide#settings-file
|
||||
var opts = process.argv.slice(2);
|
||||
if (opts.indexOf('--config') === -1) {
|
||||
opts = opts.concat(['--config', 'test/client/e2e/nightwatch.conf.js']);
|
||||
}
|
||||
if (opts.indexOf('--env') === -1) {
|
||||
opts = opts.concat(['--env', 'chrome']);
|
||||
}
|
||||
|
||||
var spawn = require('cross-spawn');
|
||||
var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' });
|
||||
|
||||
runner.on('exit', function (code) {
|
||||
server.close();
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
runner.on('error', function (err) {
|
||||
server.close();
|
||||
throw err;
|
||||
});
|
||||
20
test/client/e2e/specs/test.js
Normal file
20
test/client/e2e/specs/test.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// For authoring Nightwatch tests, see
|
||||
// http://nightwatchjs.org/guide#usage
|
||||
|
||||
module.exports = {
|
||||
'default e2e tests': function (browser) {
|
||||
|
||||
// automatically uses dev Server port from /config.index.js
|
||||
// default: http://localhost:8080
|
||||
// see nightwatch.conf.js
|
||||
var devServer = browser.globals.devServerURL;
|
||||
|
||||
browser
|
||||
.url(devServer)
|
||||
.waitForElementVisible('#app', 5000)
|
||||
.assert.elementPresent('.logo')
|
||||
.assert.containsText('h1', 'Hello Vue!')
|
||||
.assert.elementCount('p', 3)
|
||||
.end();
|
||||
},
|
||||
};
|
||||
7
test/client/unit/index.js
Normal file
7
test/client/unit/index.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// require all test files (files that ends with .spec.js)
|
||||
var testsContext = require.context('./specs', true, /\.spec$/);
|
||||
testsContext.keys().forEach(testsContext);
|
||||
|
||||
// require all src files except main.js/ README.md / index.html for coverage.
|
||||
var srcContext = require.context('../../../website/client', true, /^\.\/(?!(main\.js|README\.md|index\.html)?$)/);
|
||||
srcContext.keys().forEach(srcContext);
|
||||
75
test/client/unit/karma.conf.js
Normal file
75
test/client/unit/karma.conf.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// This is a karma config file. For more details see
|
||||
// http://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
// we are also using it with karma-webpack
|
||||
// https://github.com/webpack/karma-webpack
|
||||
|
||||
var path = require('path');
|
||||
var merge = require('webpack-merge');
|
||||
var baseConfig = require('../../../webpack/webpack.base.conf');
|
||||
var utils = require('../../../webpack/utils');
|
||||
var webpack = require('webpack');
|
||||
var projectRoot = path.resolve(__dirname, '../../../');
|
||||
|
||||
var webpackConfig = merge(baseConfig, {
|
||||
// use inline sourcemap for karma-sourcemap-loader
|
||||
module: {
|
||||
loaders: utils.styleLoaders(),
|
||||
},
|
||||
devtool: '#inline-source-map',
|
||||
vue: {
|
||||
loaders: {
|
||||
js: 'isparta',
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../../../webpack/config/test.env'),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// no need for app entry during tests
|
||||
delete webpackConfig.entry;
|
||||
|
||||
// make sure isparta loader is applied before eslint
|
||||
webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || [];
|
||||
webpackConfig.module.preLoaders.unshift({
|
||||
test: /\.js$/,
|
||||
loader: 'isparta',
|
||||
include: path.resolve(projectRoot, 'website/client'),
|
||||
});
|
||||
|
||||
// only apply babel for test files when using isparta
|
||||
webpackConfig.module.loaders.some(function (loader, i) {
|
||||
if (loader.loader === 'babel') {
|
||||
loader.include = path.resolve(projectRoot, 'test/client/unit');
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// to run in additional browsers:
|
||||
// 1. install corresponding karma launcher
|
||||
// http://karma-runner.github.io/0.13/config/browsers.html
|
||||
// 2. add it to the `browsers` array below.
|
||||
browsers: ['PhantomJS'],
|
||||
frameworks: ['mocha', 'sinon-chai'],
|
||||
reporters: ['spec', 'coverage'],
|
||||
files: ['./index.js'],
|
||||
preprocessors: {
|
||||
'./index.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
noInfo: true,
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: './coverage',
|
||||
reporters: [
|
||||
{ type: 'lcov', subdir: '.' },
|
||||
{ type: 'text-summary' },
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
12
test/client/unit/specs/Hello.spec.js
Normal file
12
test/client/unit/specs/Hello.spec.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import Vue from 'vue';
|
||||
import Hello from 'src/components/Hello';
|
||||
|
||||
describe('Hello.vue', () => {
|
||||
it('should render correct contents', () => {
|
||||
const vm = new Vue({
|
||||
el: document.createElement('div'),
|
||||
render: (h) => h(Hello),
|
||||
});
|
||||
expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Hello Vue!');
|
||||
});
|
||||
});
|
||||
35
webpack/build.js
Normal file
35
webpack/build.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// https://github.com/shelljs/shelljs
|
||||
require('shelljs/global');
|
||||
env.NODE_ENV = 'production';
|
||||
|
||||
var path = require('path');
|
||||
var config = require('./config');
|
||||
var ora = require('ora');
|
||||
var webpack = require('webpack');
|
||||
var webpackConfig = require('./webpack.prod.conf');
|
||||
|
||||
console.log(
|
||||
' Tip:\n' +
|
||||
' Built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
);
|
||||
|
||||
var spinner = ora('building for production...');
|
||||
spinner.start();
|
||||
|
||||
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory);
|
||||
rm('-rf', assetsPath);
|
||||
mkdir('-p', assetsPath);
|
||||
cp('-R', config.build.staticAssetsDirectory, assetsPath);
|
||||
|
||||
webpack(webpackConfig, function (err, stats) {
|
||||
spinner.stop();
|
||||
if (err) throw err;
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
}) + '\n');
|
||||
});
|
||||
6
webpack/config/dev.env.js
Normal file
6
webpack/config/dev.env.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
var merge = require('webpack-merge');
|
||||
var prodEnv = require('./prod.env');
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"',
|
||||
});
|
||||
35
webpack/config/index.js
Normal file
35
webpack/config/index.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
var path = require('path');
|
||||
|
||||
var staticAssetsDirectory = './website/static/.'; // The folder where static files (not processed) live
|
||||
module.exports = {
|
||||
build: {
|
||||
env: require('./prod.env'),
|
||||
index: path.resolve(__dirname, '../../dist/index.html'),
|
||||
assetsRoot: path.resolve(__dirname, '../../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
staticAssetsDirectory: staticAssetsDirectory,
|
||||
productionSourceMap: true,
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
},
|
||||
dev: {
|
||||
env: require('./dev.env'),
|
||||
port: 8080,
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
staticAssetsDirectory: staticAssetsDirectory,
|
||||
proxyTable: {},
|
||||
// CSS Sourcemaps off by default because relative paths are "buggy"
|
||||
// with this option, according to the CSS-Loader README
|
||||
// (https://github.com/webpack/css-loader#sourcemaps)
|
||||
// In our experience, they generally work as expected,
|
||||
// just be aware of this issue when enabling this option.
|
||||
cssSourceMap: false,
|
||||
},
|
||||
};
|
||||
3
webpack/config/prod.env.js
Normal file
3
webpack/config/prod.env.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
NODE_ENV: '"production"',
|
||||
};
|
||||
6
webpack/config/test.env.js
Normal file
6
webpack/config/test.env.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
var merge = require('webpack-merge');
|
||||
var devEnv = require('./dev.env');
|
||||
|
||||
module.exports = merge(devEnv, {
|
||||
NODE_ENV: '"testing"',
|
||||
});
|
||||
9
webpack/dev-client.js
Normal file
9
webpack/dev-client.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* eslint-disable */
|
||||
require('eventsource-polyfill')
|
||||
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
|
||||
|
||||
hotClient.subscribe(function (event) {
|
||||
if (event.action === 'reload') {
|
||||
window.location.reload()
|
||||
}
|
||||
})
|
||||
65
webpack/dev-server.js
Normal file
65
webpack/dev-server.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
var path = require('path');
|
||||
var express = require('express');
|
||||
var webpack = require('webpack');
|
||||
var config = require('./config');
|
||||
var proxyMiddleware = require('http-proxy-middleware');
|
||||
var webpackConfig = process.env.NODE_ENV === 'testing'
|
||||
? require('./webpack.prod.conf')
|
||||
: require('./webpack.dev.conf');
|
||||
|
||||
// default port where dev server listens for incoming traffic
|
||||
var port = process.env.PORT || config.dev.port;
|
||||
// Define HTTP proxies to your custom API backend
|
||||
// https://github.com/chimurai/http-proxy-middleware
|
||||
var proxyTable = config.dev.proxyTable;
|
||||
|
||||
var app = express();
|
||||
var compiler = webpack(webpackConfig);
|
||||
|
||||
var devMiddleware = require('webpack-dev-middleware')(compiler, {
|
||||
publicPath: webpackConfig.output.publicPath,
|
||||
stats: {
|
||||
colors: true,
|
||||
chunks: false,
|
||||
},
|
||||
});
|
||||
|
||||
var hotMiddleware = require('webpack-hot-middleware')(compiler);
|
||||
// force page reload when html-webpack-plugin template changes
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
|
||||
hotMiddleware.publish({ action: 'reload' });
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
// proxy api requests
|
||||
Object.keys(proxyTable).forEach(function (context) {
|
||||
var options = proxyTable[context];
|
||||
if (typeof options === 'string') {
|
||||
options = { target: options };
|
||||
}
|
||||
app.use(proxyMiddleware(context, options));
|
||||
});
|
||||
|
||||
// handle fallback for HTML5 history API
|
||||
app.use(require('connect-history-api-fallback')());
|
||||
|
||||
// serve webpack bundle output
|
||||
app.use(devMiddleware);
|
||||
|
||||
// enable hot-reload and state-preserving
|
||||
// compilation error display
|
||||
app.use(hotMiddleware);
|
||||
|
||||
// serve pure static assets
|
||||
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory);
|
||||
app.use(staticPath, express.static(config.dev.staticAssetsDirectory));
|
||||
|
||||
module.exports = app.listen(port, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
console.log('Listening at http://localhost:' + port + '\n');
|
||||
});
|
||||
59
webpack/utils.js
Normal file
59
webpack/utils.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
var path = require('path');
|
||||
var config = require('./config');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
var assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory;
|
||||
return path.posix.join(assetsSubDirectory, _path);
|
||||
};
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {};
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loaders) {
|
||||
var sourceLoader = loaders.map(function (loader) {
|
||||
var extraParamChar;
|
||||
if (/\?/.test(loader)) {
|
||||
loader = loader.replace(/\?/, '-loader?');
|
||||
extraParamChar = '&';
|
||||
} else {
|
||||
loader = loader + '-loader';
|
||||
extraParamChar = '?';
|
||||
}
|
||||
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '');
|
||||
}).join('!');
|
||||
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract('vue-style-loader', sourceLoader);
|
||||
} else {
|
||||
return ['vue-style-loader', sourceLoader].join('!');
|
||||
}
|
||||
}
|
||||
|
||||
// http://vuejs.github.io/vue-loader/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(['css']),
|
||||
postcss: generateLoaders(['css']),
|
||||
less: generateLoaders(['css', 'less']),
|
||||
sass: generateLoaders(['css', 'sass?indentedSyntax']),
|
||||
scss: generateLoaders(['css', 'sass']),
|
||||
stylus: generateLoaders(['css', 'stylus']),
|
||||
styl: generateLoaders(['css', 'stylus']),
|
||||
};
|
||||
};
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
var output = [];
|
||||
var loaders = exports.cssLoaders(options);
|
||||
for (var extension in loaders) {
|
||||
var loader = loaders[extension];
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
loader: loader,
|
||||
});
|
||||
}
|
||||
return output;
|
||||
};
|
||||
86
webpack/webpack.base.conf.js
Normal file
86
webpack/webpack.base.conf.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
var path = require('path');
|
||||
var config = require('./config');
|
||||
var utils = require('./utils');
|
||||
var projectRoot = path.resolve(__dirname, '../');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: './website/client/main.js',
|
||||
},
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
|
||||
filename: '[name].js',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.vue'],
|
||||
fallback: [path.join(__dirname, '../node_modules')],
|
||||
alias: {
|
||||
'src': path.resolve(__dirname, '../website/client'),
|
||||
'assets': path.resolve(__dirname, '../website/client/assets'),
|
||||
'components': path.resolve(__dirname, '../website/client/components'),
|
||||
},
|
||||
},
|
||||
resolveLoader: {
|
||||
fallback: [path.join(__dirname, '../node_modules')],
|
||||
},
|
||||
module: {
|
||||
preLoaders: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'eslint',
|
||||
include: projectRoot,
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'eslint',
|
||||
include: projectRoot,
|
||||
exclude: /node_modules/
|
||||
}
|
||||
],
|
||||
loaders: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue',
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel',
|
||||
include: projectRoot,
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]'),
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
eslint: {
|
||||
formatter: require('eslint-friendly-formatter'),
|
||||
},
|
||||
vue: {
|
||||
loaders: utils.cssLoaders(),
|
||||
postcss: [
|
||||
require('autoprefixer')({
|
||||
browsers: ['last 2 versions'],
|
||||
}),
|
||||
],
|
||||
},
|
||||
};
|
||||
34
webpack/webpack.dev.conf.js
Normal file
34
webpack/webpack.dev.conf.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
var config = require('./config');
|
||||
var webpack = require('webpack');
|
||||
var merge = require('webpack-merge');
|
||||
var utils = require('./utils');
|
||||
var baseWebpackConfig = require('./webpack.base.conf');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
// add hot-reload related code to entry chunks
|
||||
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
|
||||
baseWebpackConfig.entry[name] = ['./webpack/dev-client'].concat(baseWebpackConfig.entry[name]);
|
||||
});
|
||||
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }),
|
||||
},
|
||||
// eval-source-map is faster for development
|
||||
devtool: '#eval-source-map',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': config.dev.env,
|
||||
}),
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NoErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: './website/client/index.html',
|
||||
inject: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
102
webpack/webpack.prod.conf.js
Normal file
102
webpack/webpack.prod.conf.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
var path = require('path');
|
||||
var config = require('./config');
|
||||
var utils = require('./utils');
|
||||
var webpack = require('webpack');
|
||||
var merge = require('webpack-merge');
|
||||
var baseWebpackConfig = require('./webpack.base.conf');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
var env = process.env.NODE_ENV === 'testing'
|
||||
? require('./config/test.env')
|
||||
: config.build.env;
|
||||
|
||||
var webpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }),
|
||||
},
|
||||
devtool: config.build.productionSourceMap ? '#source-map' : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
|
||||
},
|
||||
vue: {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
extract: true,
|
||||
}),
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env,
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
},
|
||||
}),
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: process.env.NODE_ENV === 'testing'
|
||||
? 'index.html'
|
||||
: config.build.index,
|
||||
template: './website/client/index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true,
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency',
|
||||
}),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks: function (module, count) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
);
|
||||
},
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
chunks: ['vendor'],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
var CompressionWebpackPlugin = require('compression-webpack-plugin');
|
||||
|
||||
webpackConfig.plugins.push(
|
||||
new CompressionWebpackPlugin({
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = webpackConfig;
|
||||
|
|
@ -3,13 +3,13 @@
|
|||
/* Refresh page if idle > 6h */
|
||||
var REFRESH_FREQUENCY = 21600000;
|
||||
var refresh;
|
||||
var refresher = function() {
|
||||
window.refresher = function() {
|
||||
window.location.reload(true);
|
||||
};
|
||||
|
||||
var awaitIdle = function() {
|
||||
if(refresh) clearTimeout(refresh);
|
||||
refresh = setTimeout(refresher, REFRESH_FREQUENCY);
|
||||
refresh = setTimeout(window.refresher, REFRESH_FREQUENCY);
|
||||
};
|
||||
|
||||
awaitIdle();
|
||||
|
|
|
|||
5
website/client/.babelrc
Normal file
5
website/client/.babelrc
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"presets": ["es2015"],
|
||||
"plugins": ["transform-runtime"],
|
||||
"comments": false
|
||||
}
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
{
|
||||
"extends": "habitrpg/browser"
|
||||
"extends": [
|
||||
"habitrpg/browser",
|
||||
"habitrpg/babel"
|
||||
],
|
||||
"plugins": [
|
||||
"html"
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
This folder contains the source files for the new client side of that is being developed.
|
||||
This folder contains the source files for the new client side that is being developed.
|
||||
|
||||
The old client side files can be found in /website/client-old, they are still used on Habitica.com while the redesign is in progress.
|
||||
BIN
website/client/assets/logo.png
Normal file
BIN
website/client/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
64
website/client/components/App.vue
Normal file
64
website/client/components/App.vue
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<template lang="pug">
|
||||
#app
|
||||
img.logo(src='../assets/logo.png')
|
||||
ul
|
||||
li
|
||||
router-link(to='/') Home
|
||||
li
|
||||
router-link(to='/sub') Sub
|
||||
router-view.view
|
||||
p Welcome to your Vue.js app!
|
||||
p
|
||||
| To get a better understanding of how this boilerplate works, check out
|
||||
| <a href="http://vuejs-templates.github.io/webpack" target="_blank">its documentation</a>.
|
||||
| It is also recommended to go through the docs for
|
||||
| <a href="http://webpack.github.io/" target="_blank">Webpack</a> and
|
||||
| <a href="http://vuejs.github.io/vue-loader/" target="_blank">vue-loader</a>.
|
||||
| If you have any issues with the setup, please file an issue at this boilerplate's
|
||||
| <a href="https://github.com/vuejs-templates/webpack" target="_blank">repository</a>.
|
||||
p
|
||||
| You may also want to checkout
|
||||
| <a href="https://github.com/vuejs/vue-router/" target="_blank">vue-router</a> for routing and
|
||||
| <a href="https://github.com/vuejs/vuex/" target="_blank">vuex</a> for state management.
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Hello from './Hello';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Hello,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#app {
|
||||
color: #2c3e50;
|
||||
margin-top: -100px;
|
||||
max-width: 600px;
|
||||
font-family: Source Sans Pro, Helvetica, sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#app a {
|
||||
color: #42b983;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100px;
|
||||
height: 100px
|
||||
}
|
||||
</style>
|
||||
21
website/client/components/Hello.vue
Normal file
21
website/client/components/Hello.vue
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<template lang="pug">
|
||||
.hello
|
||||
h1 {{ msg }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Hello Vue!',
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1 {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
21
website/client/components/Sub.vue
Normal file
21
website/client/components/Sub.vue
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<template lang="pug">
|
||||
.hello
|
||||
h1 {{ msg }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Hello Sub Route!',
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1 {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1 +1,11 @@
|
|||
Hello World!
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Habitica</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
9
website/client/main.js
Normal file
9
website/client/main.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import Vue from 'vue';
|
||||
import App from './components/App';
|
||||
import router from './router';
|
||||
|
||||
new Vue({ // eslint-disable-line no-new
|
||||
router,
|
||||
el: '#app',
|
||||
render: h => h(App),
|
||||
});
|
||||
15
website/client/router.js
Normal file
15
website/client/router.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import Hello from './components/Hello';
|
||||
import Sub from './components/Sub';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
export default new VueRouter({
|
||||
mode: 'history',
|
||||
base: __dirname,
|
||||
routes: [
|
||||
{ path: '/', component: Hello },
|
||||
{ path: '/sub', component: Sub },
|
||||
],
|
||||
});
|
||||
6
website/server/.eslintrc
Normal file
6
website/server/.eslintrc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": [
|
||||
"habitrpg/server",
|
||||
"habitrpg/babel"
|
||||
]
|
||||
}
|
||||
3
website/static/README.md
Normal file
3
website/static/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
This folder contains the source files for static assets used in the new client side that is being developed.
|
||||
|
||||
These files are served without passing through any preprocessor.
|
||||
1
website/static/test.txt
Normal file
1
website/static/test.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Hello World!
|
||||
Loading…
Reference in a new issue