Comparing version 0.3.2 to 0.3.3
@@ -62,2 +62,3 @@ #!/usr/bin/env node | ||
jake.NpmPublishTask = require(libPath + '/npm_publish_task').NpmPublishTask; | ||
jake.TestTask = require(libPath + '/test_task').TestTask; | ||
@@ -64,0 +65,0 @@ // Enhance env with any env vars passed in |
@@ -24,3 +24,4 @@ /* | ||
glob.globSync = function (pat) { | ||
var dirname = path.dirname(pat) | ||
// path.dirname can't handle paths with globstar (**) | ||
var dirname = path.dirname(pat).split(/\/|\\/)[0] | ||
, files = jake.readdirR(dirname) | ||
@@ -27,0 +28,0 @@ , matches; |
@@ -10,3 +10,3 @@ { | ||
], | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)", | ||
@@ -13,0 +13,0 @@ "bin": { |
@@ -720,2 +720,58 @@ ### Jake -- JavaScript build tool for Node.js | ||
## TestTask | ||
Instantiating a TestTask programmically creates a simple task for running tests | ||
for your project. The first argument of the constructor is the project-name | ||
(used in the description of the task), and the second argument is a function | ||
that defines the task. It allows you to specifify what files to run as tests, | ||
and what to name the task that gets created (defaults to "test" if unset). | ||
```javascript | ||
var t = new jake.TestTask('fonebone', function () { | ||
var fileList = [ | ||
'tests/*' | ||
, 'lib/adapters/**/test.js' | ||
]; | ||
this.testFiles.include(fileList); | ||
this.testFiles.exclude('tests/helper.js'); | ||
this.testName = 'testMainAndAdapters'; | ||
}); | ||
``` | ||
Tests in the specified file should be in the very simple format of | ||
test-functions hung off the export. These tests are converted into Jake tasks | ||
which Jake then runs normally. | ||
If a test needs to run asynchronously, simply define the test-function with a | ||
single argument, a callback. Jake will define this as an asynchronous task, and | ||
will wait until the callback is called in the test function to run the next test. | ||
Here's an example test-file: | ||
```javascript | ||
var assert = require('assert') | ||
, tests; | ||
tests = { | ||
'sync test': function () { | ||
// Assert something | ||
assert.ok(true); | ||
} | ||
, 'async test': function (next) { | ||
// Assert something else | ||
assert.ok(true); | ||
// Won't go next until this is called | ||
next(); | ||
} | ||
, 'another sync test': function () { | ||
// Assert something else | ||
assert.ok(true); | ||
} | ||
}; | ||
module.exports = tests; | ||
``` | ||
Jake's tests are also a good example of use of a TestTask. | ||
## NpmPublishTask | ||
@@ -722,0 +778,0 @@ |
@@ -8,6 +8,12 @@ var assert = require('assert') | ||
process.chdir('./tests'); | ||
var tests = { | ||
'before': function () { | ||
process.chdir('./tests'); | ||
} | ||
var tests = { | ||
'test basic exec': function () { | ||
, 'after': function () { | ||
process.chdir('../'); | ||
} | ||
, 'test basic exec': function (next) { | ||
var ex = jake.createExec('ls', function () {}) | ||
@@ -36,35 +42,35 @@ , evts = { // Events should fire in this order | ||
} | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test an exec failure': function () { | ||
, 'test an exec failure': function (next) { | ||
var ex = jake.createExec('false', function () {}); | ||
ex.addListener('error', function (msg, code) { | ||
assert.equal(1, code); | ||
next(); | ||
}); | ||
ex.run(); | ||
h.next(); | ||
} | ||
, 'test exec stdout events': function () { | ||
, 'test exec stdout events': function (next) { | ||
var ex = jake.createExec('echo "foo"', function () {}); | ||
ex.addListener('stdout', function (data) { | ||
assert.equal("foo", h.trim(data.toString())); | ||
next(); | ||
}); | ||
ex.run(); | ||
h.next(); | ||
} | ||
, 'test exec stderr events': function () { | ||
, 'test exec stderr events': function (next) { | ||
var ex = jake.createExec('echo "foo" 1>&2', function () {}); | ||
ex.addListener('stderr', function (data) { | ||
assert.equal("foo", h.trim(data.toString())); | ||
next(); | ||
}); | ||
ex.run(); | ||
h.next(); | ||
} | ||
, 'test piping results into next command': function () { | ||
, 'test piping results into next command': function (next) { | ||
var ex = jake.createExec('ls', function () {}) | ||
@@ -101,5 +107,5 @@ , data | ||
}); | ||
next(); | ||
}); | ||
ex.run(); | ||
h.next(); | ||
} | ||
@@ -109,6 +115,3 @@ | ||
h.run(tests, function () { | ||
process.chdir('../'); | ||
}); | ||
module.exports = tests; | ||
@@ -7,5 +7,3 @@ var assert = require('assert') | ||
process.chdir('./tests'); | ||
var cleanUpAndNext = function () { | ||
var cleanUpAndNext = function (callback) { | ||
exec('rm -fr ./foo', function (err, stdout, stderr) { | ||
@@ -16,3 +14,3 @@ if (err) { throw err } | ||
} | ||
h.next(); | ||
callback(); | ||
}); | ||
@@ -23,3 +21,11 @@ }; | ||
'test concating two files': function () { | ||
'before': function () { | ||
process.chdir('./tests'); | ||
} | ||
, 'after': function () { | ||
process.chdir('../'); | ||
} | ||
, 'test concating two files': function (next) { | ||
h.exec('../bin/cli.js fileTest:foo/concat.txt', function (out) { | ||
@@ -32,7 +38,7 @@ var data; | ||
assert.equal('src1src2', data.toString()); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
} | ||
, 'test where a file-task prereq does not change': function () { | ||
, 'test where a file-task prereq does not change': function (next) { | ||
h.exec('../bin/cli.js fileTest:foo/from-src1.txt', function (out) { | ||
@@ -43,3 +49,3 @@ assert.equal('fileTest:foo/src1.txt task\nfileTest:foo/from-src1.txt task', out); | ||
assert.equal('', out); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
@@ -49,3 +55,3 @@ }); | ||
, 'test where a file-task prereq does not change with --always-make': function () { | ||
, 'test where a file-task prereq does not change with --always-make': function (next) { | ||
h.exec('../bin/cli.js fileTest:foo/from-src1.txt', function (out) { | ||
@@ -57,3 +63,3 @@ assert.equal('fileTest:foo/src1.txt task\nfileTest:foo/from-src1.txt task', | ||
out); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
@@ -63,3 +69,3 @@ }); | ||
, 'test a preexisting file': function () { | ||
, 'test a preexisting file': function (next) { | ||
var prereqData = 'howdy'; | ||
@@ -76,3 +82,3 @@ h.exec('mkdir -p foo', function (out) { | ||
assert.equal('', out); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
@@ -83,3 +89,3 @@ }); | ||
, 'test a preexisting file with --always-make flag': function () { | ||
, 'test a preexisting file with --always-make flag': function (next) { | ||
var prereqData = 'howdy'; | ||
@@ -95,3 +101,3 @@ h.exec('mkdir -p foo', function (out) { | ||
assert.equal('fileTest:foo/from-prereq.txt task', out); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
@@ -102,7 +108,7 @@ }); | ||
, 'test nested directory-task': function () { | ||
, 'test nested directory-task': function (next) { | ||
h.exec('../bin/cli.js fileTest:foo/bar/baz/bamf.txt', function (out) { | ||
data = fs.readFileSync(process.cwd() + '/foo/bar/baz/bamf.txt'); | ||
assert.equal('w00t', data); | ||
cleanUpAndNext(); | ||
cleanUpAndNext(next); | ||
}); | ||
@@ -113,6 +119,3 @@ } | ||
h.run(tests, function () { | ||
process.chdir('../'); | ||
}); | ||
module.exports = tests; | ||
@@ -6,16 +6,13 @@ var assert = require('assert') | ||
// Kill output | ||
global.jake = { | ||
program: { | ||
opts: { | ||
quiet: true | ||
} | ||
var tests = { | ||
'before': function () { | ||
process.chdir('./tests'); | ||
} | ||
}; | ||
process.chdir('./tests'); | ||
, 'after': function () { | ||
process.chdir('../'); | ||
} | ||
var tests = { | ||
'test mkdirP': function () { | ||
, 'test mkdirP': function () { | ||
var expected = [ | ||
@@ -33,9 +30,8 @@ 'foo' | ||
} | ||
fileUtils.rmRf('foo'); | ||
h.next(); | ||
fileUtils.rmRf('foo', {silent: true}); | ||
} | ||
, 'test rmRf': function () { | ||
fileUtils.mkdirP('foo/bar/baz/qux'); | ||
fileUtils.rmRf('foo/bar'); | ||
fileUtils.mkdirP('foo/bar/baz/qux', {silent: true}); | ||
fileUtils.rmRf('foo/bar', {silent: true}); | ||
res = fileUtils.readdirR('foo'); | ||
@@ -45,3 +41,2 @@ assert.equal(1, res.length); | ||
fs.rmdirSync('foo'); | ||
h.next(); | ||
} | ||
@@ -51,7 +46,4 @@ | ||
module.exports = tests; | ||
h.run(tests, function () { | ||
process.chdir('../'); | ||
}); | ||
@@ -36,90 +36,112 @@ var parseargs = require('../lib/parseargs') | ||
// Long preemptive opt and val with equal-sign, ignore further opts | ||
res = p.parse(z('--tasks=foo --jakefile=asdf')); | ||
assert.equal('foo', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
var tests = { | ||
// Long preemptive opt and val without equal-sign, ignore further opts | ||
res = p.parse(z('--tasks foo --jakefile=asdf')); | ||
assert.equal('foo', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
'test long preemptive opt and val with equal-sign, ignore further opts': function () { | ||
res = p.parse(z('--tasks=foo --jakefile=asdf')); | ||
assert.equal('foo', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
} | ||
// Long preemptive opt and no val, ignore further opts | ||
res = p.parse(z('--tasks --jakefile=asdf')); | ||
assert.equal(true, res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
, 'test long preemptive opt and val without equal-sign, ignore further opts': function () { | ||
res = p.parse(z('--tasks foo --jakefile=asdf')); | ||
assert.equal('foo', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
} | ||
// Preemptive opt with no val, should be true | ||
res = p.parse(z('-T')); | ||
assert.equal(true, res.opts.tasks); | ||
, 'test long preemptive opt and no val, ignore further opts': function () { | ||
res = p.parse(z('--tasks --jakefile=asdf')); | ||
assert.equal(true, res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
} | ||
// Preemptive opt with no val, should be true and ignore further opts | ||
res = p.parse(z('-T -f')); | ||
assert.equal(true, res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
, 'test preemptive opt with no val, should be true': function () { | ||
res = p.parse(z('-T')); | ||
assert.equal(true, res.opts.tasks); | ||
} | ||
// Preemptive opt with val, should be val | ||
res = p.parse(z('-T zoobie -f foo/bar/baz')); | ||
assert.equal('zoobie', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
, 'test preemptive opt with no val, should be true and ignore further opts': function () { | ||
res = p.parse(z('-T -f')); | ||
assert.equal(true, res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
} | ||
// -f expects a value, -t does not (howdy is task-name) | ||
res = p.parse(z('-f zoobie -t howdy')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('howdy', res.taskNames[0]); | ||
, 'test preemptive opt with val, should be val': function () { | ||
res = p.parse(z('-T zoobie -f foo/bar/baz')); | ||
assert.equal('zoobie', res.opts.tasks); | ||
assert.equal(undefined, res.opts.jakefile); | ||
} | ||
// Different order, -f expects a value, -t does not (howdy is task-name) | ||
res = p.parse(z('-f zoobie howdy -t')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('howdy', res.taskNames[0]); | ||
, 'test -f expects a value, -t does not (howdy is task-name)': function () { | ||
res = p.parse(z('-f zoobie -t howdy')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('howdy', res.taskNames[0]); | ||
} | ||
// -f expects a value, -t does not (foo=bar is env var) | ||
res = p.parse(z('-f zoobie -t foo=bar')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal(undefined, res.taskName); | ||
, 'test different order, -f expects a value, -t does not (howdy is task-name)': function () { | ||
res = p.parse(z('-f zoobie howdy -t')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('howdy', res.taskNames[0]); | ||
} | ||
// -f expects a value, -t does not (foo=bar is env-var, task-name follows) | ||
res = p.parse(z('-f zoobie -t howdy foo=bar')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal('howdy', res.taskNames[0]); | ||
, 'test -f expects a value, -t does not (foo=bar is env var)': function () { | ||
res = p.parse(z('-f zoobie -t foo=bar')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal(undefined, res.taskName); | ||
} | ||
// -t does not expect a value, -f does (throw howdy away) | ||
res = p.parse(z('-t howdy -f zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
, 'test -f expects a value, -t does not (foo=bar is env-var, task-name follows)': function () { | ||
res = p.parse(z('-f zoobie -t howdy foo=bar')); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal('howdy', res.taskNames[0]); | ||
} | ||
// --trace does not expect a value, -f does (throw howdy away) | ||
res = p.parse(z('--trace howdy --jakefile zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
, 'test -t does not expect a value, -f does (throw howdy away)': function () { | ||
res = p.parse(z('-t howdy -f zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
// --trace does not expect a value, -f does (throw howdy away) | ||
res = p.parse(z('--trace=howdy --jakefile=zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
} | ||
, 'test --trace does not expect a value, -f does (throw howdy away)': function () { | ||
res = p.parse(z('--trace howdy --jakefile zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
} | ||
, 'test --trace does not expect a value, -f does (throw howdy away)': function () { | ||
res = p.parse(z('--trace=howdy --jakefile=zoobie')); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('zoobie', res.opts.jakefile); | ||
assert.equal(undefined, res.taskName); | ||
} | ||
/* | ||
// Task-name with positional args | ||
res = p.parse(z('foo:bar[asdf,qwer]')); | ||
assert.equal('asdf', p.taskArgs[0]); | ||
assert.equal('qwer', p.taskArgs[1]); | ||
, 'test task-name with positional args': function () { | ||
res = p.parse(z('foo:bar[asdf,qwer]')); | ||
assert.equal('asdf', p.taskArgs[0]); | ||
assert.equal('qwer', p.taskArgs[1]); | ||
} | ||
// Opts, env vars, task-name with positional args | ||
res = p.parse(z('-f ./tests/Jakefile -t default[asdf,qwer] foo=bar')); | ||
assert.equal('./tests/Jakefile', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal('default', res.taskName); | ||
assert.equal('asdf', p.taskArgs[0]); | ||
assert.equal('qwer', p.taskArgs[1]); | ||
, 'test opts, env vars, task-name with positional args': function () { | ||
res = p.parse(z('-f ./tests/Jakefile -t default[asdf,qwer] foo=bar')); | ||
assert.equal('./tests/Jakefile', res.opts.jakefile); | ||
assert.equal(true, res.opts.trace); | ||
assert.equal('bar', res.envVars.foo); | ||
assert.equal('default', res.taskName); | ||
assert.equal('asdf', p.taskArgs[0]); | ||
assert.equal('qwer', p.taskArgs[1]); | ||
} | ||
*/ | ||
}; | ||
module.exports = tests; | ||
var assert = require('assert') | ||
, h = require('./helpers'); | ||
process.chdir('./tests'); | ||
var tests = { | ||
var tests = { | ||
'test default task': function () { | ||
'before': function () { | ||
process.chdir('./tests'); | ||
} | ||
, 'after': function () { | ||
process.chdir('../'); | ||
} | ||
, 'test default task': function (next) { | ||
h.exec('../bin/cli.js', function (out) { | ||
assert.equal('default task', out); | ||
h.exec('../bin/cli.js default', function (out) { | ||
assert.equal('default task', out); | ||
next(); | ||
}); | ||
}); | ||
h.exec('../bin/cli.js default', function (out) { | ||
assert.equal('default task', out); | ||
}); | ||
h.next(); | ||
} | ||
, 'test task with no action': function () { | ||
, 'test task with no action': function (next) { | ||
h.exec('../bin/cli.js noAction', function (out) { | ||
assert.equal('default task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a task with no action and no prereqs': function () { | ||
h.exec('../bin/cli.js noActionNoPrereqs', function () {}); | ||
h.next(); | ||
, 'test a task with no action and no prereqs': function (next) { | ||
h.exec('../bin/cli.js noActionNoPrereqs', function () { | ||
next(); | ||
}); | ||
} | ||
, 'test passing args to a task': function () { | ||
, 'test passing args to a task': function (next) { | ||
h.exec('../bin/cli.js argsEnvVars[foo,bar]', function (out) { | ||
@@ -36,7 +43,7 @@ var parsed = h.parse(out) | ||
assert.equal(args[1], 'bar'); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a task with environment vars': function () { | ||
, 'test a task with environment vars': function (next) { | ||
h.exec('../bin/cli.js argsEnvVars foo=bar baz=qux', function (out) { | ||
@@ -47,7 +54,7 @@ var parsed = h.parse(out) | ||
assert.equal(env.baz, 'qux'); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test passing args and using environment vars': function () { | ||
, 'test passing args and using environment vars': function (next) { | ||
h.exec('../bin/cli.js argsEnvVars[foo,bar] foo=bar baz=qux', function (out) { | ||
@@ -61,68 +68,68 @@ var parsed = h.parse(out) | ||
assert.equal(env.baz, 'qux'); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a simple prereq': function () { | ||
, 'test a simple prereq': function (next) { | ||
h.exec('../bin/cli.js foo:baz', function (out) { | ||
assert.equal('foo:bar task\nfoo:baz task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a duplicate prereq only runs once': function () { | ||
, 'test a duplicate prereq only runs once': function (next) { | ||
h.exec('../bin/cli.js foo:asdf', function (out) { | ||
assert.equal('foo:bar task\nfoo:baz task\nfoo:asdf task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a prereq with command-line args': function () { | ||
, 'test a prereq with command-line args': function (next) { | ||
h.exec('../bin/cli.js foo:qux', function (out) { | ||
assert.equal('foo:bar[asdf,qwer] task\nfoo:qux task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test a prereq with args via invoke': function () { | ||
, 'test a prereq with args via invoke': function (next) { | ||
h.exec('../bin/cli.js foo:frang[zxcv,uiop]', function (out) { | ||
assert.equal('foo:bar[zxcv,uiop] task\nfoo:frang task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test prereq execution-order': function () { | ||
, 'test prereq execution-order': function (next) { | ||
h.exec('../bin/cli.js hoge:fuga', function (out) { | ||
assert.equal('hoge:hoge task\nhoge:piyo task\nhoge:fuga task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test basic async task': function () { | ||
, 'test basic async task': function (next) { | ||
h.exec('../bin/cli.js bar:bar', function (out) { | ||
assert.equal('bar:foo task\nbar:bar task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test that current-prereq index gets reset': function () { | ||
, 'test that current-prereq index gets reset': function (next) { | ||
h.exec('../bin/cli.js hoge:kira', function (out) { | ||
assert.equal('hoge:hoge task\nhoge:piyo task\nhoge:fuga task\n' + | ||
'hoge:charan task\nhoge:gero task\nhoge:kira task', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test modifying a task by adding prereq during execution': function () { | ||
, 'test modifying a task by adding prereq during execution': function (next) { | ||
h.exec('../bin/cli.js voom', function (out) { | ||
assert.equal(2, out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
, 'test listening for task error-event': function () { | ||
, 'test listening for task error-event': function (next) { | ||
h.exec('../bin/cli.js vronk:groo', function (out) { | ||
assert.equal('OMFGZONG', out); | ||
next(); | ||
}); | ||
h.next(); | ||
} | ||
@@ -132,5 +139,3 @@ | ||
h.run(tests, function () { | ||
process.chdir('../'); | ||
}); | ||
module.exports = tests; | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
129623
28
3116
847
25
8