Initial commit, from shield-studies-addon-template

This commit is contained in:
groovecoder 2016-10-19 12:19:02 -05:00
Коммит 2a029c1931
21 изменённых файлов: 525 добавлений и 0 удалений

3
.addonlinterrc Normal file
Просмотреть файл

@ -0,0 +1,3 @@
ignorerules:
LOW_LEVEL_MODULE: true
KNOWN_LIBRARY: true

7
.depcheckrc Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{
"ignore": ["addons-linter", "depcheck-ci", "jpm"],
"ignoreDirs": [
],
"strict": false,
"unused": true
}

2
.eslintignore Normal file
Просмотреть файл

@ -0,0 +1,2 @@
testing-env
coverage

19
.eslintrc.yml Normal file
Просмотреть файл

@ -0,0 +1,19 @@
env:
browser: true
es6: true
node: true
extends:
- eslint:recommended
rules:
comma-dangle: off
eol-last: error
eqeqeq: error
handle-callback-err: error
indent: [error, 2]
no-console: off
no-unused-vars: [error, {vars: all, args: none}]
one-var: [error, never]
quotes: [error, single]
semi: [error, always]

10
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
*.log
*.update.rdf
*.xpi
.DS_Store
coverage/
deprecated/*
npm-shrinkwrap.json
node_modules/*
test/test-z-ensure-coverage.js
testing-env

18
.jpmignore Normal file
Просмотреть файл

@ -0,0 +1,18 @@
# start by blocking everything
*
.*
# allow basic things
!/package.json
!/icon.png
## these node modules should ship
!/node_modules/shield-studies-addon-utils/**
## allow in lib and data
!/{lib,data}/**
# but not .DS_Store files!
{lib,data}/**/.DS_Store
{lib,data}/**/.eslintrc

4
.jpmignore-testing-env Normal file
Просмотреть файл

@ -0,0 +1,4 @@
# special for testing
!/node_modules/{deep-eql,type-detect,assertion-error}/**
!/node_modules/chai/**
!/node_modules/istanbul-jpm/**

28
.travis.yml Normal file
Просмотреть файл

@ -0,0 +1,28 @@
sudo: false
language: node_js
node_js:
- "6"
env:
global:
# for screen
- DISPLAY=:99.0
- TRAVIS=1
- JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox
# before_install:
# - cd to your src if needed
before_script:
- sh -e /etc/init.d/xvfb start
- sleep 2 # give xvfb some time to start
- npm i -g get-firefox
- cd ..
- get-firefox -ceb unbranded-release
- cd $TRAVIS_BUILD_DIR
notifications:
email: false

89
Gruntfile.js Normal file
Просмотреть файл

@ -0,0 +1,89 @@
module.exports = function (grunt) {
var istanbulJpm = require('istanbul-jpm');
// gross, put this in the process
process.env.coveragedir = require('os').tmpdir();
console.log('coveragedir: %s', process.env.coveragedir);
var fxBinary = process.env.JPM_FIREFOX_BINARY || 'Aurora';
grunt.initConfig({
eslint: {
files: '**/*.js',
options: {
quiet: true
}
},
shell: {
addonLintTest: {
command: 'scripts/addonLintTest',
},
cleanCoverage: {
command: 'rm -rf coverage'
},
'ensure-files-are-covered': {
command: 'scripts/ensure-files-are-covered'
},
makeTestEnv: {
command: 'scripts/makeTestEnv'
},
jpmTest: {
command: 'cd testing-env && node_modules/.bin/jpm test --tbpl -b ' + fxBinary
}
},
instrument: {
files: 'lib/**/*.js',
options: {
lazy: false,
basePath: 'coverage/instrument',
instrumenter: istanbulJpm.Instrumenter
}
},
storeCoverage: {
options: {
dir: 'coverage/reports'
}
},
makeReport: {
src: 'coverage/reports/**/*.json',
options: {
type: 'lcov',
dir: 'coverage/reports',
print: 'detail'
}
}
});
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-istanbul');
grunt.registerTask('readcoverageglobal', 'Reads the coverage global JPM wrote', function () {
global.__coverage__ = require('istanbul-jpm/global-node').global.__coverage__;
grunt.log.ok('Read __coverage__ global');
});
grunt.registerTask('reportLocation', function () {
grunt.log.writeln('report at:', 'coverage/reports/lcov-report/index.html'['blue']);
});
grunt.registerTask('coverageReport', [
'readcoverageglobal',
'storeCoverage',
'makeReport',
'reportLocation'
]);
grunt.registerTask('jpmtest', [
'shell:ensure-files-are-covered',
'shell:makeTestEnv',
'shell:jpmTest',
]);
grunt.registerTask('test', [
'shell:addonLintTest',
'shell:cleanCoverage',
'instrument',
'jpmtest',
'coverageReport'
]);
};

55
README.md Normal file
Просмотреть файл

@ -0,0 +1,55 @@
# Base Template for Shield Studies Addons
## Features
- `eslint`
- es6 for lib, data, test
- browser, not node for `data/`
- `addons-linter` with `.addonslinterrc`
- ci with Travis OR CircleCi (TODO)
- ability to do code coverage, using `grunt-istanbul` and [`istanbul-jpm`](https://github.com/freaktechnik/istanbul-jpm)
- uses Grunt to do some of the heavy lifting. Sorry if you hate Grunt. [I do as well](#1).
- TODO: Allow better build of React type things for front ends
## General Setup and Install
1. Clone / copy the directory
2. `npm install`
## Adding a new npm library
```
npm install --save-dev somelibrary
#edit .jpmignore to allow it in
```
## Contribute
Issues on this Github :)
## Assumptions and Opinions
1. All code lives in `lib` and is ES6.
2. All website stuff (web-workers, ui) lives in `data`
3. Index at `lib/index.js`
4. Grunt, b/c it makes instrument / coverage easier
- `grunt-istanbul` + `istanbul-jpm`
- if you want or need `make`, `gulp`, `webpack` you absolutely can
5. All the testing happens in a create `testing-env` folder, so that
- it can use a custom `.jpmignore` file
- it can do coverage with less silliness
6. As built, the tests will fail, until you fix the facade tests.
7. We use `chai` for testing. If you don't, remove it where it happens.
8. You are somewhere with some resemblence to Unix cli (Linux or OSX).

11
data/.eslintrc.yml Normal file
Просмотреть файл

@ -0,0 +1,11 @@
env:
browser: true
es6: true
node: false
worker: true
extends:
- eslint:recommended
rules:
no-console: off # it would be better to find the right env for this

17
lib/feature.js Normal file
Просмотреть файл

@ -0,0 +1,17 @@
/** feature.js **/
const prefSvc = require('sdk/preferences/service');
const ourpref = 'some.pref.somewhere';
exports.which = function (val) {
prefSvc.set(ourpref, val);
return val;
};
exports.isEligible = function () {
return !prefSvc.isSet(ourpref);
};
exports.reset = function () {
return prefSvc.reset(ourpref);
};

6
lib/index.js Normal file
Просмотреть файл

@ -0,0 +1,6 @@
/** index.js **/
const self = require('sdk/self');
console.log(Object.keys(require('./study')));
console.log(Object.keys(require('./study').study));
require('./study').study.startup(self.loadReason);

73
lib/study.js Normal file
Просмотреть файл

@ -0,0 +1,73 @@
/** study.js **/
const self = require('sdk/self');
const shield = require('shield-studies-addon-utils');
const tabs = require('sdk/tabs');
const { when: unload } = require('sdk/system/unload');
const feature = require('./feature');
const studyConfig = {
name: self.addonId,
duration: 14,
surveyUrls: {
'end-of-study': 'some/url',
'user-ended-study': 'some/url',
'ineligible': null
},
variations: {
'v1': () => feature.which('v1'),
'v2': () => feature.which('v2'),
'v3': () => feature.which('v3')
}
};
class OurStudy extends shield.Study {
constructor (config) {
super(config);
}
isEligible () {
// bool Already Has the feature. Stops install if true
return super.isEligible() && feature.isEligible();
}
whenIneligible () {
super.whenIneligible();
// additional actions for 'user isn't eligible'
tabs.open('data:text/html,Uninstalling, you are not eligible for this study');
}
whenInstalled () {
super.whenInstalled();
// orientation, unless our branch is 'notheme'
if (this.variation === 'notheme') {
// noop
}
feature.orientation(this.variation);
}
cleanup (reason) {
super.cleanup(); // cleanup simple-prefs, simple-storage
feature.cleanup();
// do things, maybe depending on reason, branch
}
whenComplete () {
// when the study is naturally complete after this.days
super.whenComplete(); // calls survey, uninstalls
}
whenUninstalled () {
// user uninstall
super.whenUninstalled();
}
decideVariation () {
return super.decideVariation(); // chooses at random
// unequal or non random allocation for example
}
}
const thisStudy = new OurStudy(studyConfig);
// for testing / linting
exports.OurStudy = OurStudy;
exports.studyConfig = studyConfig;
// for use by index.js
exports.study = thisStudy;
unload((reason) => thisStudy.shutdown(reason));

54
package.json Normal file
Просмотреть файл

@ -0,0 +1,54 @@
{
"name": "shield-study-privacy",
"description": "<some feature> as a Shield Study",
"version": "1.0.0",
"author": "Unknown",
"bugs": {
"url": "https://github.com/mozilla/shield-study-privacy/issues"
},
"dependencies": {},
"devDependencies": {
"addons-linter": "^0.15.5",
"chai": "^3.5.0",
"depcheck-ci": "^1.0.1",
"eslint": "^3.6.1",
"fixpack": "^2.3.1",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-istanbul": "^0.7.0",
"grunt-shell": "^1.3.0",
"istanbul-jpm": "^0.1.0",
"jpm": "^1.0.7",
"npm-run-all": "^3.1.0",
"nsp": "^2.6.2",
"shield-studies-addon-utils": "^2.0.0",
"yamljs": "^0.2.8"
},
"engines": {
"firefox": ">=38.0a1",
"fennec": ">=38.0a1"
},
"homepage": "http://github.com/mozilla/shield-study-privacy",
"keywords": [
"jetpack",
"shield-study"
],
"license": "MPL-2.0",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "git://github.com/mozilla/shield-study-privacy.git"
},
"scripts": {
"eslint": "grunt eslint",
"lint": "npm-run-all lint:*",
"lint:depcheck": "depcheck-ci # use coverage to catch missing",
"lint:eslint": "eslint .",
"lint:fixpack": "fixpack",
"lint:nsp": "nsp check",
"prepublish": "npm shrinkwrap",
"pretest": "npm-run-all lint:*",
"test": "grunt test && istanbul check-coverage --statements 100 --functions 100 --branches 100 --lines 100 coverage/reports/coverage.json"
},
"title": "Template for creating shield study add-ons"
}

73
scripts/addon-lint-consumer.js Executable file
Просмотреть файл

@ -0,0 +1,73 @@
#!/usr/bin/env node
/*
usage:
```
jpm xpi # makes myaddon.xpi
npm install addon-linter
./node_modules/.bin/addon-linter myaddon.xpi | node addon-lint-consumer.js
```
license: PUBLIC DOMAIN.
//example .addonlinterrc
ignorerules:
LOW_LEVEL_MODULE: true
KNOWN_LIBRARY: true
*/
var yamljs = require('yamljs');
function loadRules (fn) {
var ignored = {};
try {
ignored = (yamljs.load(fn)).ignorerules;
} catch (err) {
// ignore
}
return ignored;
}
function filterLint(lint, ignored) {
['errors', 'notices', 'warnings'].map(function (k) {
var filtered = lint[k].filter(function (seen) {
return !(seen.code in ignored);
});
lint[k] = filtered;
});
return lint;
}
function output(filteredLint) {
var show = 0;
['errors', 'notices', 'warnings'].map(function (k) {
if (filteredLint[k].length) {
show = 1;
}
});
if (show) {
console.error(filteredLint);
}
process.exit(show);
}
function doTheWork(content) {
// your code here
var ignored = loadRules('.addonlinterrc');
output(filterLint(JSON.parse(content),ignored));
}
// read in all the stdin
var content = '';
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (buf) {
content += buf.toString();
});
process.stdin.on('end', function () {
// your code here
doTheWork(content);
});

9
scripts/addonLintTest Executable file
Просмотреть файл

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -o nounset
set -o errexit
node_modules/.bin/jpm xpi
node_modules/.bin/addons-linter --output json --pretty *xpi |\
node scripts/addon-lint-consumer.js
echo "OK" $0

Просмотреть файл

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -o nounset
set -o errexit
cat << DONE > test/test-z-ensure-coverage.js
// automatically created by makeCoverageTest
DONE
git ls-tree -r HEAD --name-only lib | \
grep "js$" | \
xargs -I '{}' echo "require('../{}');" | \
egrep -v "(jetpack|index.js|main.js)" >> test/test-z-ensure-coverage.js
echo "OK" $0

15
scripts/makeTestEnv Executable file
Просмотреть файл

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -o nounset
set -o errexit
rm -rf testing-env
mkdir testing-env
cd testing-env
cat ../.jpmignore ../.jpmignore-testing-env > .jpmignore
ln -s ../Gruntfile.js .
ln -s ../node_modules .
ln -s ../data .
ln -s ../coverage/instrument/lib .
ln -s ../package.json .
ln -s ../test .
echo "OK" $0

Просмотреть файл

@ -0,0 +1,6 @@
// all the usual gregg questions
// grep for surveyUrl
// where is the variations?
// livecheck all the SG urls

12
test/test-index.js Normal file
Просмотреть файл

@ -0,0 +1,12 @@
//var main = require("../");
exports['test main'] = function(assert) {
assert.pass('Unit test running!');
};
exports['test main async'] = function(assert, done) {
assert.pass('async Unit test running!');
done();
};
require('sdk/test').run(exports);