Best JavaScript code snippet using storybook-root
cli.js
Source:cli.js
1"use strict";2var path = require("path");3var shjs = require("shelljs");4var sinon = require("sinon");5var cliPath = path.resolve(__dirname, "../src/cli.js");6var cli;7exports.setUp = function(done) {8 this.sinon = sinon.sandbox.create();9 // The CLI module maintains some internal state in order to optimize10 // filesystem operations. This state can lead to undesirable test case11 // interdependencies. While re-loading the CLI module for every test may12 // negatively effect the execution time of this test suite, it is the most13 // maintainable way to avoid any current or future problems relating to14 // shared internal state.15 cli = require("../src/cli.js");16 done();17};18exports.tearDown = function(done) {19 this.sinon.restore();20 cli = null;21 delete require.cache[cliPath];22 done();23};24exports.group = {25 setUp: function (cb) {26 this.sinon.stub(cli, "exit");27 cb();28 },29 config: {30 setUp: function (done) {31 this.sinon.stub(shjs, "cat")32 .withArgs(sinon.match(/file\.js$/))33 .returns("var a = function () {}; a();")34 .withArgs(sinon.match(/file1\.json$/))35 .returns("wat")36 .withArgs(sinon.match(/file2\.json$/))37 .returns("{\"node\":true,\"globals\":{\"foo\":true,\"bar\":true}}")38 .withArgs(sinon.match(/file4\.json$/))39 .returns("{\"extends\":\"file3.json\"}")40 .withArgs(sinon.match(/file5\.json$/))41 .returns("{\"extends\":\"file2.json\"}")42 .withArgs(sinon.match(/file6\.json$/))43 .returns("{\"extends\":\"file2.json\",\"node\":false}")44 .withArgs(sinon.match(/file7\.json$/))45 .returns("{\"extends\":\"file2.json\",\"globals\":{\"bar\":false,\"baz\":true}}")46 .withArgs(sinon.match(/file8\.json$/)).returns(JSON.stringify({47 extends: "file7.json",48 overrides: {49 "file.js": {50 globals: {51 foo: true,52 bar: true53 }54 }55 }56 }))57 .withArgs(sinon.match(/file9\.json$/)).returns(JSON.stringify({58 extends: "file8.json",59 overrides: {60 "file.js": {61 globals: {62 baz: true,63 bar: false64 }65 }66 }67 }));68 this.sinon.stub(shjs, "test")69 .withArgs("-e", sinon.match(/file\.js$/)).returns(true)70 .withArgs("-e", sinon.match(/file1\.json$/)).returns(true)71 .withArgs("-e", sinon.match(/file2\.json$/)).returns(true)72 .withArgs("-e", sinon.match(/file3\.json$/)).returns(false)73 .withArgs("-e", sinon.match(/file4\.json$/)).returns(true)74 .withArgs("-e", sinon.match(/file5\.json$/)).returns(true)75 .withArgs("-e", sinon.match(/file6\.json$/)).returns(true);76 var _cli = require("cli");77 this.out = this.sinon.stub(_cli, "error");78 done();79 },80 normal: function (test) {81 this.sinon.stub(cli, "run").returns(true);82 // Merges existing valid files83 cli.interpret([84 "node", "jshint", "file.js", "--config", "file5.json"85 ]);86 test.equal(cli.run.lastCall.args[0].config.node, true);87 test.equal(cli.run.lastCall.args[0].config['extends'], void 0);88 // Overwrites options after extending89 cli.interpret([90 "node", "jshint", "file.js", "--config", "file6.json"91 ]);92 test.equal(cli.run.lastCall.args[0].config.node, false);93 // Valid config94 cli.interpret([95 "node", "jshint", "file.js", "--config", "file2.json"96 ]);97 // Performs a deep merge of configuration98 cli.interpret([99 "node", "jshint", "file2.js", "--config", "file7.json"100 ]);101 test.deepEqual(cli.run.lastCall.args[0].config.globals, { foo: true, bar: false, baz: true });102 // Performs a deep merge of configuration with overrides103 cli.interpret([104 "node", "jshint", "file.js", "--config", "file8.json"105 ]);106 test.deepEqual(cli.run.lastCall.args[0].config.overrides["file.js"].globals, { foo: true, bar: true });107 // Performs a deep merge of configuration with overrides for the same glob108 cli.interpret([109 "node", "jshint", "file.js", "--config", "file9.json"110 ]);111 test.deepEqual(cli.run.lastCall.args[0].config.overrides["file.js"].globals, { foo: true, bar: false, baz: true });112 test.done();113 },114 failure: function (test) {115 var out = this.out;116 cli.exit.throws("ProcessExit");117 // File doesn't exist.118 try {119 cli.interpret([120 "node", "jshint", "file.js", "--config", "file3.json"121 ]);122 } catch (err) {123 var msg = out.args[0][0];124 test.equal(msg.slice(0, 23), "Can't find config file:");125 test.equal(msg.slice(msg.length - 10), "file3.json");126 test.equal(err, "ProcessExit");127 }128 // Invalid config129 try {130 cli.interpret([131 "node", "jshint", "file.js", "--config", "file1.json"132 ]);133 } catch (err) {134 var msg = out.args[1][0];135 test.equal(msg.slice(0, 24), "Can't parse config file:");136 test.equal(msg.slice(25, 35), "file1.json");137 test.equal(msg.slice(msg.length - 37), "Error:SyntaxError: Unexpected token w");138 test.equal(err, "ProcessExit");139 }140 // Invalid merged filed141 try {142 cli.interpret([143 "node", "jshint", "file.js", "--config", "file4.json"144 ]);145 } catch (err) {146 var msg = out.args[2][0];147 test.equal(msg.slice(0, 23), "Can't find config file:");148 test.equal(msg.slice(msg.length - 10), "file3.json");149 test.equal(err, "ProcessExit");150 }151 test.done();152 }153 },154 testPrereq: function (test) {155 this.sinon.stub(shjs, "cat")156 .withArgs(sinon.match(/file\.js$/)).returns("a();")157 .withArgs(sinon.match(/prereq.js$/)).returns("var a = 1;")158 .withArgs(sinon.match(/config.json$/))159 .returns("{\"undef\":true,\"prereq\":[\"prereq.js\", \"prereq2.js\"]}");160 this.sinon.stub(shjs, "test")161 .withArgs("-e", sinon.match(/file\.js$/)).returns(true)162 .withArgs("-e", sinon.match(/prereq.js$/)).returns(true)163 .withArgs("-e", sinon.match(/config.json$/)).returns(true);164 cli.exit.withArgs(0).returns(true)165 .withArgs(2).throws("ProcessExit");166 cli.interpret([167 "node", "jshint", "file.js", "--config", "config.json"168 ]);169 shjs.cat.restore();170 shjs.test.restore();171 test.done();172 },173 // CLI prereqs174 testPrereqCLIOption: function (test) {175 this.sinon.stub(shjs, "cat")176 .withArgs(sinon.match(/file\.js$/)).returns("a();")177 .withArgs(sinon.match(/prereq.js$/)).returns("var a = 1;")178 .withArgs(sinon.match(/config.json$/)).returns("{\"undef\":true}");179 this.sinon.stub(shjs, "test")180 .withArgs("-e", sinon.match(/file\.js$/)).returns(true)181 .withArgs("-e", sinon.match(/prereq.js$/)).returns(true)182 .withArgs("-e", sinon.match(/config.json$/)).returns(true);183 cli.exit.restore();184 this.sinon.stub(cli, "exit")185 .withArgs(0).returns(true)186 .withArgs(2).throws("ProcessExit");187 cli.interpret([188 "node", "jshint", "file.js",189 "--config", "config.json",190 "--prereq", "prereq.js , prereq2.js"191 ]);192 shjs.cat.restore();193 shjs.test.restore();194 test.done();195 },196 // CLI prereqs should get merged with config prereqs197 testPrereqBothConfigAndCLIOption: function (test) {198 this.sinon.stub(shjs, "cat")199 .withArgs(sinon.match(/file\.js$/)).returns("a(); b();")200 .withArgs(sinon.match(/prereq.js$/)).returns("var a = 1;")201 .withArgs(sinon.match(/prereq2.js$/)).returns("var b = 2;")202 .withArgs(sinon.match(/config.json$/))203 .returns("{\"undef\":true,\"prereq\":[\"prereq.js\"]}");204 this.sinon.stub(shjs, "test")205 .withArgs("-e", sinon.match(/file\.js$/)).returns(true)206 .withArgs("-e", sinon.match(/prereq.js$/)).returns(true)207 .withArgs("-e", sinon.match(/prereq2.js$/)).returns(true)208 .withArgs("-e", sinon.match(/config.json$/)).returns(true);209 cli.exit.restore();210 this.sinon.stub(cli, "exit")211 .withArgs(0).returns(true)212 .withArgs(2).throws("ProcessExit");213 cli.interpret([214 "node", "jshint", "file.js",215 "--config", "config.json",216 "--prereq", "prereq2.js,prereq3.js"217 ]);218 shjs.cat.restore();219 shjs.test.restore();220 test.done();221 },222 testOverrides: function (test) {223 var dir = __dirname + "/../examples/";224 var rep = require("../examples/reporter.js");225 var config = {226 "asi": true,227 "overrides": {228 "bar.js": {229 "asi": false230 }231 }232 };233 this.sinon.stub(process, "cwd").returns(dir);234 this.sinon.stub(rep, "reporter");235 this.sinon.stub(shjs, "cat")236 .withArgs(sinon.match(/foo\.js$/)).returns("a()")237 .withArgs(sinon.match(/bar\.js$/)).returns("a()")238 .withArgs(sinon.match(/config\.json$/))239 .returns(JSON.stringify(config));240 this.sinon.stub(shjs, "test")241 .withArgs("-e", sinon.match(/foo\.js$/)).returns(true)242 .withArgs("-e", sinon.match(/bar\.js$/)).returns(true)243 .withArgs("-e", sinon.match(/config\.json$/)).returns(true);244 cli.exit.withArgs(0).returns(true)245 .withArgs(1).throws("ProcessExit");246 // Test successful file247 cli.interpret([248 "node", "jshint", "foo.js", "--config", "config.json", "--reporter", "reporter.js"249 ]);250 test.ok(rep.reporter.args[0][0].length === 0);251 // Test overriden, failed file252 cli.interpret([253 "node", "jshint", "bar.js", "--config", "config.json", "--reporter", "reporter.js"254 ]);255 test.ok(rep.reporter.args[1][0].length > 0, "Error was expected but not thrown");256 test.equal(rep.reporter.args[1][0][0].error.code, "W033");257 test.done();258 },259 testOverridesMatchesRelativePaths: function (test) {260 var dir = __dirname + "/../examples/";261 var rep = require("../examples/reporter.js");262 var config = {263 "asi": true,264 "overrides": {265 "src/bar.js": {266 "asi": false267 }268 }269 };270 this.sinon.stub(process, "cwd").returns(dir);271 this.sinon.stub(rep, "reporter");272 this.sinon.stub(shjs, "cat")273 .withArgs(sinon.match(/bar\.js$/)).returns("a()")274 .withArgs(sinon.match(/config\.json$/))275 .returns(JSON.stringify(config));276 this.sinon.stub(shjs, "test")277 .withArgs("-e", sinon.match(/bar\.js$/)).returns(true)278 .withArgs("-e", sinon.match(/config\.json$/)).returns(true);279 cli.exit.withArgs(0).returns(true)280 .withArgs(1).throws("ProcessExit");281 cli.interpret([282 "node", "jshint", "./src/bar.js", "--config", "config.json", "--reporter", "reporter.js"283 ]);284 test.ok(rep.reporter.args[0][0].length === 1);285 test.done();286 },287 testReporter: function (test) {288 test.expect(5);289 var _cli = require("cli");290 var rep = require("../examples/reporter.js");291 var run = this.sinon.stub(cli, "run");292 var out = this.sinon.stub(_cli, "error");293 var dir = __dirname + "/../examples/";294 this.sinon.stub(process, "cwd").returns(dir);295 cli.exit.throws("ProcessExit");296 // Test failed attempt.297 try {298 cli.interpret([299 "node", "jshint", "file.js", "--reporter", "invalid.js"300 ]);301 } catch (err) {302 var msg = out.args[0][0];303 test.equal(msg.slice(0, 25), "Can't load reporter file:");304 test.equal(msg.slice(msg.length - 10), "invalid.js");305 test.equal(err, "ProcessExit");306 }307 // Test successful attempt.308 run.restore();309 this.sinon.stub(rep, "reporter");310 this.sinon.stub(shjs, "test")311 .withArgs("-e", sinon.match(/file\.js$/)).returns(true);312 this.sinon.stub(shjs, "cat")313 .withArgs(sinon.match(/file\.js$/)).returns("func()");314 try {315 cli.interpret([316 "node", "jshint", "file.js", "--reporter", "reporter.js"317 ]);318 } catch (err) {319 if (err.name !== "ProcessExit") {320 throw err;321 }322 test.equal(rep.reporter.args[0][0][0].error.raw, "Missing semicolon.");323 test.ok(rep.reporter.calledOnce);324 }325 test.done();326 },327 testJSLintReporter: function (test) {328 var rep = require("../src/reporters/jslint_xml.js");329 var run = this.sinon.stub(cli, "run");330 cli.interpret([331 "node", "jshint", "file.js", "--reporter", "jslint"332 ]);333 test.equal(run.args[0][0].reporter, rep.reporter);334 cli.interpret([335 "node", "jshint", "file.js", "--jslint-reporter"336 ]);337 test.equal(run.args[1][0].reporter, rep.reporter);338 test.done();339 },340 testCheckStyleReporter: function (test) {341 var rep = require("../src/reporters/checkstyle.js");342 var run = this.sinon.stub(cli, "run");343 cli.interpret([344 "node", "jshint", "file.js", "--reporter", "checkstyle"345 ]);346 test.equal(run.args[0][0].reporter, rep.reporter);347 cli.interpret([348 "node", "jshint", "file.js", "--checkstyle-reporter"349 ]);350 test.equal(run.args[1][0].reporter, rep.reporter);351 test.done();352 },353 testShowNonErrors: function (test) {354 var rep = require("../src/reporters/non_error.js");355 var run = this.sinon.stub(cli, "run");356 cli.interpret([357 "node", "jshint", "file.js", "--show-non-errors"358 ]);359 test.equal(run.args[0][0].reporter, rep.reporter);360 test.done();361 },362 testExtensions: function (test) {363 var run = this.sinon.stub(cli, "run");364 cli.interpret([365 "node", "jshint", "file.js"366 ]);367 test.equal(run.args[0][0].extensions, "");368 cli.interpret([369 "node", "jshint", "file.js", "--extra-ext", ".json"370 ]);371 test.equal(run.args[1][0].extensions, ".json");372 test.done();373 },374 testMalformedNpmFile: function (test) {375 this.sinon.stub(process, "cwd").returns(__dirname);376 var localNpm = path.normalize(__dirname + "/package.json");377 var localRc = path.normalize(__dirname + "/.jshintrc");378 var testStub = this.sinon.stub(shjs, "test");379 var catStub = this.sinon.stub(shjs, "cat");380 // stub rc file381 testStub.withArgs("-e", localRc).returns(true);382 catStub.withArgs(localRc).returns('{"evil": true}');383 // stub npm file384 testStub.withArgs("-e", localNpm).returns(true);385 catStub.withArgs(localNpm).returns('{'); // malformed package.json386 // stub src file387 testStub.withArgs("-e", sinon.match(/file\.js$/)).returns(true);388 catStub.withArgs(sinon.match(/file\.js$/)).returns("eval('a=2');");389 cli.interpret([390 "node", "jshint", "file.js"391 ]);392 test.equal(cli.exit.args[0][0], 0); // lint with wrong package.json393 test.done();394 },395 testRcFile: function (test) {396 this.sinon.stub(process, "cwd").returns(__dirname);397 var localRc = path.normalize(__dirname + "/.jshintrc");398 var testStub = this.sinon.stub(shjs, "test");399 var catStub = this.sinon.stub(shjs, "cat");400 // stub rc file401 testStub.withArgs("-e", localRc).returns(true);402 catStub.withArgs(localRc).returns('{"evil": true}');403 // stub src file404 testStub.withArgs("-e", sinon.match(/file\.js$/)).returns(true);405 catStub.withArgs(sinon.match(/file\.js$/)).returns("eval('a=2');");406 cli.interpret([407 "node", "jshint", "file.js"408 ]);409 test.equal(cli.exit.args[0][0], 0); // eval allowed = rc file found410 test.done();411 },412 testHomeRcFile: function (test) {413 var homeRc = path.join(process.env.HOME || process.env.HOMEPATH, ".jshintrc");414 var testStub = this.sinon.stub(shjs, "test");415 var catStub = this.sinon.stub(shjs, "cat");416 // stub rc file417 testStub.withArgs("-e", homeRc).returns(true);418 catStub.withArgs(homeRc).returns('{"evil": true}');419 // stub src file (in root where we are unlikely to find a .jshintrc)420 testStub.withArgs("-e", sinon.match(/\/file\.js$/)).returns(true);421 catStub.withArgs(sinon.match(/\/file\.js$/)).returns("eval('a=2');");422 cli.interpret([423 "node", "jshint", "/file.js"424 ]);425 test.equal(cli.exit.args[0][0], 0); // eval allowed = rc file found426 test.done();427 },428 testNoHomeDir: function (test) {429 var prevEnv = {};430 // Remove all home dirs from env.431 [ 'USERPROFILE', 'HOME', 'HOMEPATH' ].forEach(function (key) {432 prevEnv[key] = process.env[key];433 delete process.env[key];434 });435 this.sinon.stub(process, "cwd").returns(__dirname);436 var localRc = path.normalize(__dirname + "/.jshintrc");437 var testStub = this.sinon.stub(shjs, "test");438 var catStub = this.sinon.stub(shjs, "cat");439 // stub rc file440 testStub.withArgs("-e", localRc).returns(true);441 catStub.withArgs(localRc).returns('{"evil": true}');442 // stub src file443 testStub.withArgs("-e", sinon.match(/file\.js$/)).returns(true);444 catStub.withArgs(sinon.match(/file\.js$/)).returns("eval('a=2');");445 cli.interpret([446 "node", "jshint", "file.js"447 ]);448 test.equal(cli.exit.args[0][0], 0); // eval allowed = rc file found449 test.done();450 // Restore environemnt451 Object.keys(prevEnv).forEach(function (key) {452 process.env[key] = prevEnv[key];453 });454 },455 testOneLevelRcLookup: function (test) {456 var srcDir = __dirname + "../src/";457 var parentRc = path.join(srcDir, ".jshintrc");458 var cliDir = path.join(srcDir, "cli/");459 this.sinon.stub(process, "cwd").returns(cliDir);460 var testStub = this.sinon.stub(shjs, "test");461 var catStub = this.sinon.stub(shjs, "cat");462 // stub rc file463 testStub.withArgs("-e", parentRc).returns(true);464 catStub.withArgs(parentRc).returns('{"evil": true}');465 // stub src file466 testStub.withArgs("-e", sinon.match(/file\.js$/)).returns(true);467 catStub.withArgs(sinon.match(/file\.js$/)).returns("eval('a=2');");468 cli.interpret([469 "node", "jshint", "file.js"470 ]);471 test.equal(cli.exit.args[0][0], 0); // eval allowed = rc file found472 test.done();473 },474 testTargetRelativeRcLookup: function (test) {475 // working from outside the project476 this.sinon.stub(process, "cwd").returns(process.env.HOME || process.env.HOMEPATH);477 var projectRc = path.normalize(__dirname + "/.jshintrc");478 var srcFile = __dirname + "/sub/file.js";479 var testStub = this.sinon.stub(shjs, "test");480 var catStub = this.sinon.stub(shjs, "cat");481 // stub rc file482 testStub.withArgs("-e", projectRc).returns(true);483 catStub.withArgs(projectRc).returns('{"evil": true}');484 // stub src file485 testStub.withArgs("-e", srcFile).returns(true);486 catStub.withArgs(srcFile).returns("eval('a=2');");487 cli.interpret([488 "node", "jshint", srcFile489 ]);490 test.equal(cli.exit.args[0][0], 0); // eval allowed = rc file found491 test.done();492 },493 testIgnores: function (test) {494 var run = this.sinon.stub(cli, "run");495 var dir = __dirname + "/../examples/";496 this.sinon.stub(process, "cwd").returns(dir);497 cli.interpret([498 "node", "jshint", "file.js", "--exclude=exclude.js"499 ]);500 test.equal(run.args[0][0].ignores[0], path.resolve(dir, "exclude.js"));501 test.equal(run.args[0][0].ignores[1], path.resolve(dir, "ignored.js"));502 test.equal(run.args[0][0].ignores[2], path.resolve(dir, "another.js"));503 run.restore();504 process.cwd.returns(__dirname + "/../");505 this.sinon.stub(shjs, "cat")506 .withArgs(sinon.match(/file.js$/)).returns("console.log('Hello');")507 .withArgs(sinon.match(/\.jshintignore$/)).returns("examples");508 test.equal(shjs.cat.args.length, 0);509 test.done();510 },511 512 testMultipleIgnores: function (test) {513 var run = this.sinon.stub(cli, "run");514 var dir = __dirname + "/../examples/";515 this.sinon.stub(process, "cwd").returns(dir);516 cli.interpret([517 "node", "jshint", "file.js", "--exclude=foo.js,bar.js"518 ]);519 520 test.equal(run.args[0][0].ignores[0], path.resolve(dir, "foo.js"));521 test.equal(run.args[0][0].ignores[1], path.resolve(dir, "bar.js"));522 523 test.done();524 },525 testExcludePath: function (test) {526 var run = this.sinon.stub(cli, "run");527 var dir = __dirname + "/../examples/";528 this.sinon.stub(process, "cwd").returns(dir);529 cli.interpret([530 "node", "jshint", "file.js", "--exclude-path=../examples/.customignore"531 ]);532 test.equal(run.args[0][0].ignores[0], path.resolve(dir, "exclude.js"));533 run.restore();534 process.cwd.returns(__dirname + "/../");535 this.sinon.stub(shjs, "cat")536 .withArgs(sinon.match(/file.js$/)).returns("console.log('Hello');")537 .withArgs(sinon.match(/\.jshintignore$/)).returns("examples");538 test.equal(shjs.cat.args.length, 0);539 test.done();540 },541 testAPIIgnores: function (test) {542 var dir = __dirname + "/../data/";543 this.sinon.stub(process, "cwd").returns(dir);544 var result = null;545 cli.run({546 args: [dir + "../tests/unit/fixtures/ignored.js"],547 cwd: dir + "../tests/unit/fixtures/",548 reporter: function (results) { result = results; }549 });550 test.deepEqual(result, []);551 test.done();552 },553 testCollectFiles: function (test) {554 var gather = this.sinon.stub(cli, "gather");555 var args = [];556 gather.returns([]);557 this.sinon.stub(shjs, "test")558 .withArgs("-e", sinon.match(/.*/)).returns(true);559 this.sinon.stub(shjs, "cat")560 .withArgs(sinon.match(/file2?\.js$/)).returns("console.log('Hello');")561 .withArgs(sinon.match(/ignore[\/\\]file\d\.js$/)).returns("console.log('Hello, ignore me');")562 .withArgs(sinon.match(/ignore[\/\\]dir[\/\\]file\d\.js$/)).returns("print('Ignore me');")563 .withArgs(sinon.match(/node_script$/)).returns("console.log('Hello, ignore me');")564 .withArgs(sinon.match(/\.jshintignore$/)).returns(path.join("ignore", "**"));565 cli.interpret([566 "node", "jshint", "file.js", "file2.js", "node_script", path.join("ignore", "file1.js"),567 path.join("ignore", "file2.js"), path.join("ignore", "dir", "file1.js")568 ]);569 args = gather.args[0][0];570 test.equal(args.args[0], "file.js");571 test.equal(args.args[1], "file2.js");572 test.equal(args.args[2], "node_script");573 test.equal(args.args[3], path.join("ignore", "file1.js"));574 test.equal(args.args[4], path.join("ignore", "file2.js"));575 test.equal(args.args[5], path.join("ignore", "dir", "file1.js"));576 test.equal(args.ignores, path.resolve(path.join("ignore", "**")));577 shjs.cat.restore();578 shjs.test.withArgs("-d", sinon.match(/src$/)).returns(true)579 .withArgs("-d", sinon.match(/src[\/\\]lib$/)).returns(true);580 this.sinon.stub(shjs, "ls")581 .withArgs(sinon.match(/src$/)).returns(["lib", "file4.js"])582 .withArgs(sinon.match(/src[\/\\]lib$/)).returns(["file5.js"]);583 this.sinon.stub(shjs, "cat")584 .withArgs(sinon.match(/file2?\.js$/)).returns("console.log('Hello');")585 .withArgs(sinon.match(/file3\.json$/)).returns("{}")586 .withArgs(sinon.match(/src[\/\\]file4\.js$/)).returns("print('Hello');")587 .withArgs(sinon.match(/src[\/\\]lib[\/\\]file5\.js$/)).returns("print('Hello');")588 .withArgs(sinon.match(/\.jshintignore$/)).returns("");589 cli.interpret([590 "node", "jshint", "file.js", "file2.js", "file3.json", "--extra-ext=json", "src"591 ]);592 args = gather.args[1][0];593 test.equal(args.args.length, 4);594 test.equal(args.args[0], "file.js");595 test.equal(args.args[1], "file2.js");596 test.equal(args.args[2], "file3.json");597 test.equal(args.args[3], "src");598 test.equal(args.ignores, false);599 shjs.cat600 .withArgs(sinon.match(/reporter\.js$/)).returns("console.log('Hello');");601 cli.interpret([602 "node", "jshint", "examples"603 ]);604 args = gather.args[2][0];605 test.equal(args.args.length, 1);606 test.equal(args.args[0], "examples");607 test.equal(args.ignores.length, 0);608 test.done();609 },610 testGatherOptionalParameters: function (test) {611 this.sinon.stub(shjs, "test")612 .withArgs("-e", sinon.match(/file.js$/)).returns(true);613 var files = cli.gather({614 args: ["file.js"]615 });616 test.equal(files.length, 1);617 test.equal(files[0], "file.js");618 test.done();619 },620 testGather: function (test) {621 var dir = __dirname + "/../examples/";622 var files = [];623 this.sinon.stub(process, "cwd").returns(dir);624 var demoFiles = [625 [ /file2?\.js$/, "console.log('Hello');" ],626 [ /ignore[\/\\]file\d\.js$/, "console.log('Hello, ignore me');" ],627 [ /ignore[\/\\]dir[\/\\]file\d\.js$/, "print('Ignore me');" ],628 [ /node_script$/, "console.log('Hello, ignore me');" ]629 ];630 var testStub = this.sinon.stub(shjs, "test");631 demoFiles.forEach(function (file) {632 testStub = testStub.withArgs("-e", sinon.match(file[0])).returns(true);633 });634 var catStub = this.sinon.stub(shjs, "cat");635 demoFiles.forEach(function (file) {636 catStub = catStub.withArgs(sinon.match(file[0])).returns(file[1]);637 });638 files = cli.gather({639 args: ["file.js", "file2.js", "node_script",640 path.join("ignore", "file1.js"),641 path.join("ignore", "file2.js"),642 path.join("ignore", "dir", "file1.js")643 ],644 ignores: [path.join("ignore", "**")],645 extensions: ""646 });647 test.equal(shjs.cat.args.length, 0);648 test.equal(files.length, 3);649 test.equal(files[0], "file.js");650 test.equal(files[1], "file2.js");651 test.equal(files[2], "node_script");652 demoFiles = [653 [ /file2?\.js$/, "console.log('Hello');" ],654 [ /file3\.json$/, "{}" ],655 [ /src[\/\\]file4\.js$/, "print('Hello');" ],656 [ /src[\/\\]lib[\/\\]file5\.js$/, "print('Hello'); "]657 ];658 demoFiles.forEach(function (file) {659 testStub = testStub.withArgs("-e", sinon.match(file[0])).returns(true);660 });661 testStub = testStub662 .withArgs("-e", sinon.match(/src$/)).returns(true)663 .withArgs("-e", sinon.match(/src[\/\\]lib$/)).returns(true)664 .withArgs("-d", sinon.match(/src$/)).returns(true)665 .withArgs("-d", sinon.match(/src[\/\\]lib$/)).returns(true);666 this.sinon.stub(shjs, "ls")667 .withArgs(sinon.match(/src$/)).returns(["lib", "file4.js"])668 .withArgs(sinon.match(/src[\/\\]lib$/)).returns(["file5.js"]);669 demoFiles.forEach(function (file) {670 catStub = catStub.withArgs(sinon.match(file[0])).returns(file[1]);671 });672 cli.interpret([673 "node", "jshint", "file.js", "file2.js", "file3.json", "--extra-ext=json", "src"674 ]);675 files = cli.gather({676 args: ["file.js", "file2.js", "file3.json", "src"],677 extensions: "json",678 ignores: []679 });680 test.equal(shjs.cat.args.length, 5);681 test.equal(files.length, 5);682 test.equal(files[0], "file.js");683 test.equal(files[1], "file2.js");684 test.equal(files[2], "file3.json");685 test.equal(files[3], path.join("src", "lib", "file5.js"));686 test.equal(files[4], path.join("src", "file4.js"));687 shjs.test.restore();688 shjs.ls.restore();689 shjs.cat.restore();690 process.cwd.restore();691 this.sinon.stub(process, "cwd").returns(__dirname + "/../");692 this.sinon.stub(shjs, "cat")693 .withArgs(sinon.match(/reporter\.js$/)).returns("console.log('Hello');");694 files = cli.gather({695 args: ["examples"],696 extensions: "json",697 ignores: []698 });699 test.equal(shjs.cat.args.length, 0);700 test.equal(files.length, 1);701 test.equal(files[0], path.join("examples", "reporter.js"));702 test.done();703 },704 testStatusCode: function (test) {705 var rep = require("../examples/reporter.js");706 var dir = __dirname + "/../examples/";707 this.sinon.stub(rep, "reporter");708 this.sinon.stub(process, "cwd").returns(dir);709 this.sinon.stub(shjs, "test")710 .withArgs("-e", sinon.match(/(pass\.js|fail\.js)$/)).returns(true);711 this.sinon.stub(shjs, "cat")712 .withArgs(sinon.match(/pass\.js$/)).returns("function test() { return 0; }")713 .withArgs(sinon.match(/fail\.js$/)).returns("console.log('Hello')");714 cli.interpret([715 "node", "jshint", "pass.js", "--reporter=reporter.js"716 ]);717 cli.interpret([718 "node", "jshint", "fail.js", "--reporter=reporter.js"719 ]);720 test.strictEqual(cli.exit.args[0][0], 0);721 test.equal(cli.exit.args[1][0], 2);722 test.done();723 }724};725exports.extract = {726 setUp: function (cb) {727 this.sinon.stub(cli, "exit");728 cb();729 },730 basic: function (test) {731 var html = "<html>text<script>var a = 1;</script></html>";732 var text = "hello world";733 var js = "var a = 1;";734 test.equal(cli.extract(html, "never"), html);735 test.equal(cli.extract(html, "auto"), js);736 test.equal(cli.extract(html, "always"), js);737 test.equal(cli.extract(js, "never"), js);738 test.equal(cli.extract(js, "auto"), js);739 test.equal(cli.extract(js, "always"), "");740 test.equal(cli.extract(text, "never"), text);741 test.equal(cli.extract(text, "auto"), text);742 test.equal(cli.extract(text, "always"), "");743 html = [744 "<html>",745 "<script type='text/javascript'>",746 "var a = 1;",747 "</script>",748 "<h1>Hello!</h1>",749 "<script type='text/coffeescript'>",750 "a = 1",751 "</script>",752 "<script>",753 "var b = 1;",754 "</script>",755 "</html>" ].join("\n");756 js = ["\n", "var a = 1;", "\n\n\n\n\n", "var b = 1;\n" ].join("\n");757 test.equal(cli.extract(html, "auto"), js);758 test.done();759 },760 withIndent: function (test) {761 var html = [762 "<html>",763 "<script type='text/javascript'>",764 " var a = 1;",765 " var b = 1;",766 "</script>",767 "</html>" ].join("\n");768 // leading whitespace is removed by amount from first js line769 var js = ["\n", "var a = 1;", " var b = 1;\n"].join("\n");770 test.equal(cli.extract(html, "auto"), js);771 test.done();772 },773 withIndentReportLocation: function (test) {774 var rep = require("../examples/reporter.js");775 var errors = [];776 this.sinon.stub(rep, "reporter", function (res) {777 errors = errors.concat(res);778 });779 var dir = __dirname + "/../examples/";780 this.sinon.stub(process, "cwd").returns(dir);781 var html = [782 "<html>",783 "<script type='text/javascript'>",784 " /* jshint indent: 2*/",785 " var a = 1;",786 " var b = 1",787 "</script>",788 "</html>"789 ].join("\n");790 this.sinon.stub(shjs, "cat")791 .withArgs(sinon.match(/indent\.html$/)).returns(html);792 this.sinon.stub(shjs, "test")793 .withArgs("-e", sinon.match(/indent\.html$/)).returns(true);794 cli.interpret([795 "node", "jshint", "indent.html", "--extract", "always", "--reporter=reporter.js"796 ]);797 test.equal(cli.exit.args[0][0], 2);798 test.equal(errors.length, 1, "found single error");799 var lintError = errors[0].error;800 test.ok(lintError, "have error object");801 test.equal(lintError.code, "W033", "found missing semicolon warning");802 test.equal(lintError.line, 5, "misaligned line");803 test.equal(lintError.character, 14, "first misaligned character at column 5");804 test.done();805 },806 withIndentReportLocationMultipleFragments: function (test) {807 var rep = require("../examples/reporter.js");808 var errors = [];809 this.sinon.stub(rep, "reporter", function (res) {810 errors = errors.concat(res);811 });812 var dir = __dirname + "/../examples/";813 this.sinon.stub(process, "cwd").returns(dir);814 var html = [815 "<html>",816 "<script type='text/javascript'>",817 " /* jshint indent: 2*/",818 " var a = 1;",819 " var b = 1", // misindented on purpose820 "</script>",821 "<p>nothing</p>",822 "<script type='text/javascript'>",823 " /* jshint indent: 2*/",824 " var a = 1", // misindented on purpose825 "</script>",826 "</html>"827 ].join("\n");828 this.sinon.stub(shjs, "cat")829 .withArgs(sinon.match(/indent\.html$/)).returns(html);830 this.sinon.stub(shjs, "test")831 .withArgs("-e", sinon.match(/indent\.html$/)).returns(true);832 cli.interpret([833 "node", "jshint", "indent.html", "--extract", "always", "--reporter=reporter.js"834 ]);835 test.equal(cli.exit.args[0][0], 2);836 test.equal(errors.length, 2, "found two errors");837 test.equal(errors[0].error.line, 5, "first error line");838 test.equal(errors[0].error.character, 14, "first error column");839 test.equal(errors[1].error.line, 10, "second error line");840 test.equal(errors[1].error.character, 16, "second error column");841 test.done();842 },843 firstLine: function (test) {844 var rep = require("../examples/reporter.js");845 var errors = [];846 this.sinon.stub(rep, "reporter", function (res) {847 errors = errors.concat(res);848 });849 var dir = __dirname + "/../examples/";850 this.sinon.stub(process, "cwd").returns(dir);851 var html = [852 "<script>",853 " function a() {",854 " return 5;",855 " }",856 "</script>"857 ].join("\n");858 this.sinon.stub(shjs, "cat")859 .withArgs(sinon.match(/firstLine\.html$/)).returns(html);860 this.sinon.stub(shjs, "test")861 .withArgs("-e", sinon.match(/firstLine\.html$/)).returns(true);862 cli.interpret([863 "node", "jshint", "firstLine.html", "--extract", "always", "--reporter=reporter.js"864 ]);865 test.equal(cli.exit.args[0][0], 0);866 test.equal(errors.length, 0, "found no errors");867 var js = [868 "",869 "function a() {",870 " return 5;",871 "}",872 ""873 ].join("\n");874 test.equal(cli.extract(html, "auto"), js);875 test.done();876 },877 sameLine: function (test) {878 var rep = require("../examples/reporter.js");879 var errors = [];880 this.sinon.stub(rep, "reporter", function (res) {881 errors = errors.concat(res);882 });883 var dir = __dirname + "/../examples/";884 this.sinon.stub(process, "cwd").returns(dir);885 var html = [886 "<script>",887 " function a() {",888 " return 5;",889 " }",890 "</script><script>",891 " function b() {",892 " return 'hello world';",893 " }",894 "</script>"895 ].join("\n");896 this.sinon.stub(shjs, "cat")897 .withArgs(sinon.match(/sameLine\.html$/)).returns(html);898 this.sinon.stub(shjs, "test")899 .withArgs("-e", sinon.match(/sameLine\.html$/)).returns(true);900 cli.interpret([901 "node", "jshint", "sameLine.html", "--extract", "always", "--reporter=reporter.js"902 ]);903 test.equal(cli.exit.args[0][0], 0);904 test.equal(errors.length, 0, "found no errors");905 var js = [906 "",907 "function a() {",908 " return 5;",909 "}",910 "",911 "function b() {",912 " return 'hello world';",913 "}",914 ""915 ].join("\n");916 test.equal(cli.extract(html, "auto"), js);917 test.done();918 }919};920exports.useStdin = {921 setUp: function (cb) {922 this.stdin = require('mock-stdin').stdin();923 this.sinon.stub(cli, "exit");924 cb();925 },926 testFilenameOption: function (test) {927 var rep = require("../examples/reporter.js");928 var errors = [];929 this.sinon.stub(rep, "reporter", function (res) {930 errors = errors.concat(res);931 });932 var dir = __dirname + "/../examples/";933 this.sinon.stub(process, "cwd").returns(dir);934 var jshintrc = JSON.stringify({ undef: true });935 this.sinon.stub(shjs, "cat")936 .withArgs(sinon.match(/[\/\\]fake[\/\\]\.jshintrc$/)).returns(jshintrc);937 this.sinon.stub(shjs, "test")938 .withArgs("-e", sinon.match(/fake[\/\\]\.jshintrc$/)).returns(true);939 cli.interpret([940 "node", "jshint", "--filename", "fake/fakescript.js", "--reporter=reporter.js", "-"941 ]);942 var bad = [943 'function returnUndef() {',944 ' return undefinedVariable;',945 '}',946 'returnUndef();'947 ];948 this.stdin.send(bad);949 this.stdin.end();950 test.equal(errors.length, 1, "should be a single error.");951 test.equal(cli.exit.args[0][0], 2, "status code should be 2 when there is a linting error.");952 test.done();953 },954 testFilenameOverridesOption: function (test) {955 test.expect(4);956 var rep = require("../examples/reporter.js");957 var errors = [];958 this.sinon.stub(rep, "reporter", function (res) {959 errors = errors.concat(res);960 });961 var dir = __dirname + "/../examples/";962 this.sinon.stub(process, "cwd").returns(dir);963 var jshintrc = JSON.stringify({964 undef: false,965 overrides: {966 "**/fake/**": {967 undef: true968 }969 }970 });971 this.sinon.stub(shjs, "cat")972 .withArgs(sinon.match(/\.jshintrc$/)).returns(jshintrc);973 this.sinon.stub(shjs, "test")974 .withArgs("-e", sinon.match(/fake[\/\\]\.jshintrc$/)).returns(true)975 .withArgs("-e", sinon.match(/\.jshintrc$/)).returns(true);976 cli.interpret([977 "node", "jshint", "--filename", "fake/fakescript.js", "--reporter=reporter.js", "-"978 ]);979 var bad = [980 'function returnUndef() {',981 ' return undefinedVariable;',982 '}',983 'returnUndef();'984 ];985 this.stdin.send(bad);986 this.stdin.end();987 test.equal(errors.length, 1, "should be a single error.");988 test.equal(cli.exit.args[0][0], 2, "status code should be 2 when there is a linting error.");989 errors.length = 0;990 cli.exit.restore();991 this.sinon.stub(cli, "exit");992 this.stdin.restore();993 this.stdin = require('mock-stdin').stdin();994 cli.interpret([995 "node", "jshint", "--filename", "fake2/fakescript.js", "--reporter=reporter.js", "-"996 ]);997 this.stdin.send(bad);998 this.stdin.end();999 test.equal(errors.length, 0, "should be no errors.");1000 test.equal(cli.exit.args[0][0], 0, "status code should be 0 when there is no linting error.");1001 test.done();1002 }...
IndexedNarwhalRouter.spec.ts
Source:IndexedNarwhalRouter.spec.ts
1import { createFixtureLoader } from '@ethereum-waffle/provider'2import { expect } from 'chai'3import { BigNumber, constants, ContractTransaction } from 'ethers'4import { ethers, waffle } from 'hardhat'5import { IIndexPool, IndexedNarwhalRouter, IUniswapV2Pair, IUniswapV2Factory, IERC20, IWETH, WETH9 } from '../typechain'6import { narwhalFixture } from './shared/fixtures'7import { expandTo18Decimals, swapInGivenOut, swapOutGivenIn } from './shared/utilities'8describe('IndexedNarwhalRouter', () => {9 const wallets = waffle.provider.getWallets()10 const [wallet] = wallets;11 const loadFixture = createFixtureLoader(wallets, waffle.provider)12 let weth: WETH913 let token0: IERC2014 let token1: IERC2015 let uniswapFactory: IUniswapV2Factory16 let sushiswapFactory: IUniswapV2Factory17 let pair_0_1_sushi: IUniswapV2Pair18 let pair_0_1_uni: IUniswapV2Pair19 let pair_0_weth_uni: IUniswapV2Pair20 let indexPool: IIndexPool21 let router: IndexedNarwhalRouter22 let allInGivenPoolOut: (n: BigNumber) => BigNumber[]23 let poolOutGivenTokenIn: (n: BigNumber) => BigNumber24 let tokenInGivenPoolOut: (n: BigNumber) => BigNumber25 let tokenOutGivenPoolIn: (n: BigNumber) => BigNumber26 let poolInGivenTokenOut: (n: BigNumber) => BigNumber27 let allOutGivenPoolIn: (n: BigNumber) => BigNumber[]28 beforeEach(async () => {29 const fixture = await loadFixture(narwhalFixture)30 weth = fixture.weth31 token0 = fixture.token032 token1 = fixture.token133 uniswapFactory = fixture.uniswapFactory34 sushiswapFactory = fixture.sushiswapFactory35 pair_0_1_sushi = fixture.pair_0_1_sushi36 pair_0_1_uni = fixture.pair_0_1_uni37 pair_0_weth_uni = fixture.pair_0_weth_uni38 indexPool = fixture.indexPool39 router = fixture.router40 poolOutGivenTokenIn = fixture.poolOutGivenTokenIn41 tokenInGivenPoolOut = fixture.tokenInGivenPoolOut42 tokenOutGivenPoolIn = fixture.tokenOutGivenPoolIn43 poolInGivenTokenOut = fixture.poolInGivenTokenOut44 allInGivenPoolOut = fixture.allInGivenPoolOut45 allOutGivenPoolIn = fixture.allOutGivenPoolIn46 })47 function encodePathToken(token: string, sushi: boolean) {48 return [49 '0x',50 token.slice(2).padStart(62, '0'),51 sushi ? '01' : '00'52 ].join('');53 }54 function encodeIntermediary(token: string, sushiPrevious: boolean, sushiNext: boolean) {55 return [56 `0x${'00'.repeat(10)}`,57 sushiPrevious ? '01' : '00',58 token.slice(2).padStart(40, '0'),59 sushiNext ? '01' : '00'60 ].join('');61 }62 async function addLiquidity() {63 await token0.transfer(pair_0_1_sushi.address, expandTo18Decimals(1000))64 await token0.transfer(pair_0_1_uni.address, expandTo18Decimals(1000))65 await token1.transfer(pair_0_1_sushi.address, expandTo18Decimals(1000))66 await token1.transfer(pair_0_1_uni.address, expandTo18Decimals(1000))67 await token0.transfer(pair_0_weth_uni.address, expandTo18Decimals(1000))68 await weth.deposit({ value: expandTo18Decimals(1000) })69 await weth.transfer(pair_0_weth_uni.address, expandTo18Decimals(1000))70 await pair_0_1_sushi.mint(wallet.address)71 await pair_0_1_uni.mint(wallet.address)72 await pair_0_weth_uni.mint(wallet.address)73 }74 async function getTransactionCost(tx: Promise<ContractTransaction>) {75 const { gasPrice, wait } = await tx;76 const { gasUsed } = await wait();77 return gasUsed.mul(gasPrice);78 }79 describe('swapExactETHForTokensAndMint', () => {80 const swapAmount = expandTo18Decimals(1)81 const expectedOutput0 = swapOutGivenIn(swapAmount, expandTo18Decimals(1000), expandTo18Decimals(1000));82 const expectedOutput1 = swapOutGivenIn(expectedOutput0, expandTo18Decimals(1000), expandTo18Decimals(1000));83 let expectedPoolOutput0: BigNumber84 let expectedPoolOutput1: BigNumber85 beforeEach(async () => {86 await addLiquidity()87 expectedPoolOutput0 = poolOutGivenTokenIn(expectedOutput1)88 expectedPoolOutput1 = poolOutGivenTokenIn(expectedOutput0)89 })90 it('Uni -> Sushi -> Pool', async () => {91 await expect(92 router.swapExactETHForTokensAndMint(93 [encodePathToken(weth.address, false), encodePathToken(token0.address, true), encodePathToken(token1.address, false)],94 indexPool.address,95 0,96 { value: swapAmount }97 )98 )99 .to.emit(weth, 'Transfer')100 .withArgs(router.address, pair_0_weth_uni.address, swapAmount)101 .to.emit(token0, 'Transfer')102 .withArgs(pair_0_weth_uni.address, pair_0_1_sushi.address, expectedOutput0)103 .to.emit(token1, 'Transfer')104 .withArgs(pair_0_1_sushi.address, router.address, expectedOutput1)105 .to.emit(token1, 'Transfer')106 .withArgs(router.address, indexPool.address, expectedOutput1)107 .to.emit(indexPool, 'Transfer')108 .withArgs(indexPool.address, router.address, expectedPoolOutput0)109 .to.emit(indexPool, 'Transfer')110 .withArgs(router.address, wallet.address, expectedPoolOutput0)111 })112 it('Uni -> Pool', async () => {113 await expect(114 router.swapExactETHForTokensAndMint(115 [encodePathToken(weth.address, false), encodePathToken(token0.address, true)],116 indexPool.address,117 0,118 { value: swapAmount }119 )120 )121 .to.emit(weth, 'Transfer')122 .withArgs(router.address, pair_0_weth_uni.address, swapAmount)123 .to.emit(token0, 'Transfer')124 .withArgs(pair_0_weth_uni.address, router.address, expectedOutput0)125 .to.emit(token0, 'Transfer')126 .withArgs(router.address, indexPool.address, expectedOutput0)127 .to.emit(indexPool, 'Transfer')128 .withArgs(indexPool.address, router.address, expectedPoolOutput1)129 .to.emit(indexPool, 'Transfer')130 .withArgs(router.address, wallet.address, expectedPoolOutput1)131 })132 })133 describe('swapExactTokensForTokensAndMint', () => {134 const swapAmount = expandTo18Decimals(1)135 const expectedOutput0 = swapOutGivenIn(swapAmount, expandTo18Decimals(1000), expandTo18Decimals(1000));136 let expectedPoolOutput: BigNumber137 beforeEach(async () => {138 await addLiquidity()139 expectedPoolOutput = poolOutGivenTokenIn(expectedOutput0)140 })141 it('Sushi -> Pool', async () => {142 await token0.approve(router.address, swapAmount)143 await expect(144 router.swapExactTokensForTokensAndMint(145 swapAmount,146 [encodePathToken(token0.address, true), encodePathToken(token1.address, false)],147 indexPool.address,148 0,149 )150 )151 .to.emit(token0, 'Transfer')152 .withArgs(wallet.address, pair_0_1_sushi.address, swapAmount)153 .to.emit(token1, 'Transfer')154 .withArgs(pair_0_1_sushi.address, router.address, expectedOutput0)155 .to.emit(token1, 'Transfer')156 .withArgs(router.address, indexPool.address, expectedOutput0)157 .to.emit(indexPool, 'Transfer')158 .withArgs(indexPool.address, router.address, expectedPoolOutput)159 .to.emit(indexPool, 'Transfer')160 .withArgs(router.address, wallet.address, expectedPoolOutput)161 })162 it('Uni -> Pool', async () => {163 await token0.approve(router.address, swapAmount)164 await expect(165 router.swapExactTokensForTokensAndMint(166 swapAmount,167 [encodePathToken(token0.address, false), encodePathToken(token1.address, false)],168 indexPool.address,169 0,170 )171 )172 .to.emit(token0, 'Transfer')173 .withArgs(wallet.address, pair_0_1_uni.address, swapAmount)174 .to.emit(token1, 'Transfer')175 .withArgs(pair_0_1_uni.address, router.address, expectedOutput0)176 .to.emit(token1, 'Transfer')177 .withArgs(router.address, indexPool.address, expectedOutput0)178 .to.emit(indexPool, 'Transfer')179 .withArgs(indexPool.address, router.address, expectedPoolOutput)180 .to.emit(indexPool, 'Transfer')181 .withArgs(router.address, wallet.address, expectedPoolOutput)182 })183 })184 describe('burnExactAndSwapForTokens', () => {185 const poolAmount = expandTo18Decimals(1)186 let expectedPoolOutput: BigNumber187 let expectedOutput0: BigNumber188 let expectedOutput1: BigNumber189 beforeEach(async () => {190 await addLiquidity()191 expectedPoolOutput = tokenOutGivenPoolIn(poolAmount)192 expectedOutput0 = swapOutGivenIn(expectedPoolOutput, expandTo18Decimals(1000), expandTo18Decimals(1000));193 expectedOutput1 = swapOutGivenIn(expectedOutput0, expandTo18Decimals(1000), expandTo18Decimals(1000));194 })195 it('Pool -> Sushi', async () => {196 await indexPool.approve(router.address, poolAmount)197 await expect(198 router.burnExactAndSwapForTokens(199 indexPool.address,200 poolAmount,201 [encodePathToken(token0.address, true), encodePathToken(token1.address, false)],202 0,203 )204 )205 .to.emit(indexPool, 'Transfer')206 .withArgs(wallet.address, router.address, poolAmount)207 .to.emit(indexPool, 'Transfer')208 .withArgs(router.address, indexPool.address, poolAmount)209 .to.emit(token0, 'Transfer')210 .withArgs(indexPool.address, router.address, expectedPoolOutput)211 .to.emit(token0, 'Transfer')212 .withArgs(router.address, pair_0_1_sushi.address, expectedPoolOutput)213 .to.emit(token1, 'Transfer')214 .withArgs(pair_0_1_sushi.address, wallet.address, expectedOutput0)215 })216 it('Pool -> Uni', async () => {217 await indexPool.approve(router.address, poolAmount)218 await expect(219 router.burnExactAndSwapForTokens(220 indexPool.address,221 poolAmount,222 [encodePathToken(token0.address, false), encodePathToken(token1.address, false)],223 0,224 )225 )226 .to.emit(indexPool, 'Transfer')227 .withArgs(wallet.address, router.address, poolAmount)228 .to.emit(indexPool, 'Transfer')229 .withArgs(router.address, indexPool.address, poolAmount)230 .to.emit(token0, 'Transfer')231 .withArgs(indexPool.address, router.address, expectedPoolOutput)232 .to.emit(token0, 'Transfer')233 .withArgs(router.address, pair_0_1_uni.address, expectedPoolOutput)234 .to.emit(token1, 'Transfer')235 .withArgs(pair_0_1_uni.address, wallet.address, expectedOutput0)236 })237 })238 describe('burnExactAndSwapForETH', () => {239 const poolAmount = expandTo18Decimals(1)240 let expectedPoolOutput: BigNumber241 let expectedOutput0: BigNumber242 let expectedOutput1: BigNumber243 beforeEach(async () => {244 await addLiquidity()245 expectedPoolOutput = tokenOutGivenPoolIn(poolAmount)246 expectedOutput0 = swapOutGivenIn(expectedPoolOutput, expandTo18Decimals(1000), expandTo18Decimals(1000));247 expectedOutput1 = swapOutGivenIn(expectedOutput0, expandTo18Decimals(1000), expandTo18Decimals(1000));248 })249 it('Pool -> Sushi -> Uni', async () => {250 await indexPool.approve(router.address, poolAmount)251 await expect(252 router.burnExactAndSwapForETH(253 indexPool.address,254 poolAmount,255 [encodePathToken(token1.address, true), encodePathToken(token0.address, false), encodePathToken(weth.address, false)],256 0,257 )258 )259 .to.emit(indexPool, 'Transfer')260 .withArgs(wallet.address, router.address, poolAmount)261 .to.emit(indexPool, 'Transfer')262 .withArgs(router.address, indexPool.address, poolAmount)263 .to.emit(token1, 'Transfer')264 .withArgs(indexPool.address, router.address, expectedPoolOutput)265 .to.emit(token1, 'Transfer')266 .withArgs(router.address, pair_0_1_sushi.address, expectedPoolOutput)267 .to.emit(token0, 'Transfer')268 .withArgs(pair_0_1_sushi.address, pair_0_weth_uni.address, expectedOutput0)269 .to.emit(weth, 'Transfer')270 .withArgs(pair_0_weth_uni.address, router.address, expectedOutput1)271 .to.emit(weth, 'Withdrawal')272 .withArgs(router.address, expectedOutput1)273 })274 it('Pool -> Uni -> Uni', async () => {275 await indexPool.approve(router.address, poolAmount)276 await expect(277 router.burnExactAndSwapForETH(278 indexPool.address,279 poolAmount,280 [encodePathToken(token1.address, false), encodePathToken(token0.address, false), encodePathToken(weth.address, false)],281 0,282 )283 )284 .to.emit(indexPool, 'Transfer')285 .withArgs(wallet.address, router.address, poolAmount)286 .to.emit(indexPool, 'Transfer')287 .withArgs(router.address, indexPool.address, poolAmount)288 .to.emit(token1, 'Transfer')289 .withArgs(indexPool.address, router.address, expectedPoolOutput)290 .to.emit(token1, 'Transfer')291 .withArgs(router.address, pair_0_1_uni.address, expectedPoolOutput)292 .to.emit(token0, 'Transfer')293 .withArgs(pair_0_1_uni.address, pair_0_weth_uni.address, expectedOutput0)294 .to.emit(weth, 'Transfer')295 .withArgs(pair_0_weth_uni.address, router.address, expectedOutput1)296 .to.emit(weth, 'Withdrawal')297 .withArgs(router.address, expectedOutput1)298 })299 })300 describe('swapETHForTokensAndMintExact', () => {301 const mintAmount = expandTo18Decimals(1)302 let expectedAmount0: BigNumber303 let expectedAmount1: BigNumber304 let expectedPoolInput: BigNumber305 beforeEach(async () => {306 await addLiquidity()307 expectedPoolInput = tokenInGivenPoolOut(mintAmount)308 expectedAmount1 = swapInGivenOut(expectedPoolInput, expandTo18Decimals(1000), expandTo18Decimals(1000))309 expectedAmount0 = swapInGivenOut(expectedAmount1, expandTo18Decimals(1000), expandTo18Decimals(1000))310 })311 it('Uni -> Sushi -> Pool', async () => {312 await expect(313 router.swapETHForTokensAndMintExact(314 [encodePathToken(weth.address, false), encodePathToken(token0.address, true), encodePathToken(token1.address, false)],315 indexPool.address,316 mintAmount,317 { value: expectedAmount0.mul(2) }318 )319 )320 .to.emit(weth, 'Deposit')321 .withArgs(router.address, expectedAmount0)322 .to.emit(weth, 'Transfer')323 .withArgs(router.address, pair_0_weth_uni.address, expectedAmount0)324 .to.emit(token0, 'Transfer')325 .withArgs(pair_0_weth_uni.address, pair_0_1_sushi.address, expectedAmount1)326 .to.emit(token1, 'Transfer')327 .withArgs(pair_0_1_sushi.address, router.address, expectedPoolInput)328 .to.emit(token1, 'Transfer')329 .withArgs(router.address, indexPool.address, expectedPoolInput)330 .to.emit(indexPool, 'Transfer')331 .withArgs(indexPool.address, router.address, mintAmount)332 .to.emit(indexPool, 'Transfer')333 .withArgs(router.address, wallet.address, mintAmount)334 expect(await weth.balanceOf(router.address)).to.eq(0)335 expect(await ethers.provider.getBalance(router.address)).to.eq(0)336 })337 it('Uni -> Uni -> Pool', async () => {338 await expect(339 router.swapETHForTokensAndMintExact(340 [encodePathToken(weth.address, false), encodePathToken(token0.address, false), encodePathToken(token1.address, false)],341 indexPool.address,342 mintAmount,343 { value: expectedAmount0.mul(2) }344 )345 )346 .to.emit(weth, 'Deposit')347 .withArgs(router.address, expectedAmount0)348 .to.emit(weth, 'Transfer')349 .withArgs(router.address, pair_0_weth_uni.address, expectedAmount0)350 .to.emit(token0, 'Transfer')351 .withArgs(pair_0_weth_uni.address, pair_0_1_uni.address, expectedAmount1)352 .to.emit(token1, 'Transfer')353 .withArgs(pair_0_1_uni.address, router.address, expectedPoolInput)354 .to.emit(token1, 'Transfer')355 .withArgs(router.address, indexPool.address, expectedPoolInput)356 .to.emit(indexPool, 'Transfer')357 .withArgs(indexPool.address, router.address, mintAmount)358 .to.emit(indexPool, 'Transfer')359 .withArgs(router.address, wallet.address, mintAmount)360 expect(await weth.balanceOf(router.address)).to.eq(0)361 expect(await ethers.provider.getBalance(router.address)).to.eq(0)362 })363 })364 describe('swapTokensForTokensAndMintExact', () => {365 const mintAmount = expandTo18Decimals(1)366 let expectedAmount0: BigNumber367 let expectedPoolInput: BigNumber368 beforeEach(async () => {369 await addLiquidity()370 expectedPoolInput = tokenInGivenPoolOut(mintAmount)371 expectedAmount0 = swapInGivenOut(expectedPoolInput, expandTo18Decimals(1000), expandTo18Decimals(1000))372 })373 it('Sushi -> Pool', async () => {374 await token0.approve(router.address, expectedAmount0)375 await expect(376 router.swapTokensForTokensAndMintExact(377 expectedAmount0,378 [encodePathToken(token0.address, true), encodePathToken(token1.address, false)],379 indexPool.address,380 mintAmount,381 )382 )383 .to.emit(token0, 'Transfer')384 .withArgs(wallet.address, pair_0_1_sushi.address, expectedAmount0)385 .to.emit(token1, 'Transfer')386 .withArgs(pair_0_1_sushi.address, router.address, expectedPoolInput)387 .to.emit(token1, 'Transfer')388 .withArgs(router.address, indexPool.address, expectedPoolInput)389 .to.emit(indexPool, 'Transfer')390 .withArgs(indexPool.address, router.address, mintAmount)391 .to.emit(indexPool, 'Transfer')392 .withArgs(router.address, wallet.address, mintAmount)393 expect(await token0.balanceOf(router.address)).to.eq(0)394 })395 it('Uni -> Pool', async () => {396 await token1.approve(router.address, expectedAmount0)397 await expect(398 router.swapTokensForTokensAndMintExact(399 expectedAmount0,400 [encodePathToken(token1.address, false), encodePathToken(token0.address, false)],401 indexPool.address,402 mintAmount,403 )404 )405 .to.emit(token1, 'Transfer')406 .withArgs(wallet.address, pair_0_1_uni.address, expectedAmount0)407 .to.emit(token0, 'Transfer')408 .withArgs(pair_0_1_uni.address, router.address, expectedPoolInput)409 .to.emit(token0, 'Transfer')410 .withArgs(router.address, indexPool.address, expectedPoolInput)411 .to.emit(indexPool, 'Transfer')412 .withArgs(indexPool.address, router.address, mintAmount)413 .to.emit(indexPool, 'Transfer')414 .withArgs(router.address, wallet.address, mintAmount)415 expect(await token1.balanceOf(router.address)).to.eq(0)416 })417 })418 describe('burnAndSwapForExactTokens', () => {419 const amountOut = expandTo18Decimals(1)420 let expectedPoolAmount: BigNumber421 let expectedSwapInput: BigNumber422 beforeEach(async () => {423 await addLiquidity()424 expectedSwapInput = swapInGivenOut(amountOut, expandTo18Decimals(1000), expandTo18Decimals(1000))425 expectedPoolAmount = poolInGivenTokenOut(expectedSwapInput)426 })427 it('Pool -> Sushi', async () => {428 await indexPool.approve(router.address, expectedPoolAmount)429 await expect(430 router.burnAndSwapForExactTokens(431 indexPool.address,432 expectedPoolAmount,433 [encodePathToken(token0.address, true), encodePathToken(token1.address, false)],434 amountOut,435 )436 )437 .to.emit(indexPool, 'Transfer')438 .withArgs(wallet.address, router.address, expectedPoolAmount)439 .to.emit(indexPool, 'Transfer')440 .withArgs(router.address, indexPool.address, expectedPoolAmount)441 .to.emit(token0, 'Transfer')442 .withArgs(indexPool.address, router.address, expectedSwapInput)443 .to.emit(token0, 'Transfer')444 .withArgs(router.address, pair_0_1_sushi.address, expectedSwapInput)445 .to.emit(token1, 'Transfer')446 .withArgs(pair_0_1_sushi.address, wallet.address, amountOut)447 })448 it('Pool -> Uni', async () => {449 await indexPool.approve(router.address, expectedPoolAmount)450 await expect(451 router.burnAndSwapForExactTokens(452 indexPool.address,453 expectedPoolAmount,454 [encodePathToken(token1.address, false), encodePathToken(token0.address, false)],455 amountOut,456 )457 )458 .to.emit(indexPool, 'Transfer')459 .withArgs(wallet.address, router.address, expectedPoolAmount)460 .to.emit(indexPool, 'Transfer')461 .withArgs(router.address, indexPool.address, expectedPoolAmount)462 .to.emit(token1, 'Transfer')463 .withArgs(indexPool.address, router.address, expectedSwapInput)464 .to.emit(token1, 'Transfer')465 .withArgs(router.address, pair_0_1_uni.address, expectedSwapInput)466 .to.emit(token0, 'Transfer')467 .withArgs(pair_0_1_uni.address, wallet.address, amountOut)468 })469 })470 describe('burnAndSwapForExactETH', () => {471 const amountOut = expandTo18Decimals(1)472 let expectedPoolAmount0: BigNumber473 let expectedPoolAmount1: BigNumber474 let expectedSwapInput1: BigNumber475 let expectedSwapInput0: BigNumber476 beforeEach(async () => {477 await addLiquidity()478 expectedSwapInput1 = swapInGivenOut(amountOut, expandTo18Decimals(1000), expandTo18Decimals(1000))479 expectedSwapInput0 = swapInGivenOut(expectedSwapInput1, expandTo18Decimals(1000), expandTo18Decimals(1000))480 expectedPoolAmount0 = poolInGivenTokenOut(expectedSwapInput1)481 expectedPoolAmount1 = poolInGivenTokenOut(expectedSwapInput0)482 })483 it('Pool -> Uni', async () => {484 await indexPool.approve(router.address, expectedPoolAmount0)485 const balanceBefore = await ethers.provider.getBalance(wallet.address)486 const tx = router.burnAndSwapForExactETH(487 indexPool.address,488 expectedPoolAmount0,489 [encodePathToken(token0.address, false), encodePathToken(weth.address, false)],490 amountOut,491 )492 await expect(tx)493 .to.emit(indexPool, 'Transfer')494 .withArgs(wallet.address, router.address, expectedPoolAmount0)495 .to.emit(indexPool, 'Transfer')496 .withArgs(router.address, indexPool.address, expectedPoolAmount0)497 .to.emit(token0, 'Transfer')498 .withArgs(indexPool.address, router.address, expectedSwapInput1)499 .to.emit(token0, 'Transfer')500 .withArgs(router.address, pair_0_weth_uni.address, expectedSwapInput1)501 .to.emit(weth, 'Transfer')502 .withArgs(pair_0_weth_uni.address, router.address, amountOut)503 .to.emit(weth, 'Withdrawal')504 .withArgs(router.address, amountOut)505 expect(506 await ethers.provider.getBalance(wallet.address)507 ).to.eq(balanceBefore.sub(await getTransactionCost(tx)).add(amountOut))508 })509 it('Pool -> Sushi -> Uni', async () => {510 await indexPool.approve(router.address, expectedPoolAmount1)511 const balanceBefore = await ethers.provider.getBalance(wallet.address)512 const tx = router.burnAndSwapForExactETH(513 indexPool.address,514 expectedPoolAmount1,515 [encodePathToken(token1.address, true), encodePathToken(token0.address, false), encodePathToken(weth.address, false)],516 amountOut,517 );518 await expect(tx)519 .to.emit(indexPool, 'Transfer')520 .withArgs(wallet.address, router.address, expectedPoolAmount1)521 .to.emit(indexPool, 'Transfer')522 .withArgs(router.address, indexPool.address, expectedPoolAmount1)523 .to.emit(token1, 'Transfer')524 .withArgs(indexPool.address, router.address, expectedSwapInput0)525 .to.emit(token1, 'Transfer')526 .withArgs(router.address, pair_0_1_sushi.address, expectedSwapInput0)527 .to.emit(token0, 'Transfer')528 .withArgs(pair_0_1_sushi.address, pair_0_weth_uni.address, expectedSwapInput1)529 .to.emit(weth, 'Transfer')530 .withArgs(pair_0_weth_uni.address, router.address, amountOut)531 .to.emit(weth, 'Withdrawal')532 .withArgs(router.address, amountOut)533 expect(534 await ethers.provider.getBalance(wallet.address)535 ).to.eq(balanceBefore.sub(await getTransactionCost(tx)).add(amountOut))536 })537 })538 describe('swapTokensForAllTokensAndMintExact', () => {539 const mintAmount = expandTo18Decimals(1)540 let expectedPoolInput0: BigNumber541 let expectedPoolInput1: BigNumber542 let input_weth_0: BigNumber543 let input_weth_0_1: BigNumber544 let input_0_1: BigNumber545 beforeEach(async () => {546 await addLiquidity();547 ([expectedPoolInput0, expectedPoolInput1] = allInGivenPoolOut(mintAmount));548 // weth -> token0549 input_weth_0 = swapInGivenOut(expectedPoolInput0, expandTo18Decimals(1000), expandTo18Decimals(1000))550 // token0 -> token1551 input_0_1 = swapInGivenOut(expectedPoolInput1, expandTo18Decimals(1000), expandTo18Decimals(1000))552 // weth -> token0 -> token1553 input_weth_0_1 = swapInGivenOut(554 input_0_1,555 expandTo18Decimals(1000).add(input_weth_0),556 expandTo18Decimals(1000).sub(expectedPoolInput0)557 )558 })559 it('Sushi -> Pool & User -> Pool', async () => {560 const amountIn = input_0_1.add(expectedPoolInput0)561 await token0.approve(router.address, amountIn)562 await expect(563 router.swapTokensForAllTokensAndMintExact(564 indexPool.address,565 [encodePathToken(constants.AddressZero, false), encodeIntermediary(constants.AddressZero, true, false)],566 mintAmount,567 token0.address,568 amountIn,569 )570 )571 .to.emit(token0, 'Transfer')572 .withArgs(wallet.address, router.address, amountIn)573 .to.emit(token0, 'Transfer')574 .withArgs(router.address, indexPool.address, expectedPoolInput0)575 .to.emit(token0, 'Transfer')576 .withArgs(router.address, pair_0_1_sushi.address, input_0_1)577 .to.emit(token1, 'Transfer')578 .withArgs(pair_0_1_sushi.address, router.address, expectedPoolInput1)579 .to.emit(token1, 'Transfer')580 .withArgs(router.address, indexPool.address, expectedPoolInput1)581 .to.emit(indexPool, 'Transfer')582 .withArgs(indexPool.address, router.address, mintAmount)583 .to.emit(indexPool, 'Transfer')584 .withArgs(router.address, wallet.address, mintAmount)585 })586 it('Sushi -> Pool & Uni -> Sushi -> Pool', async () => {587 const amountIn = input_weth_0.add(input_weth_0_1).add(expandTo18Decimals(1))588 await weth.deposit({ value: amountIn })589 await weth.approve(router.address, amountIn)590 await expect(591 router.swapTokensForAllTokensAndMintExact(592 indexPool.address,593 [encodePathToken(constants.AddressZero, false), encodeIntermediary(token0.address, false, true)],594 mintAmount,595 weth.address,596 amountIn,597 )598 )599 .to.emit(weth, 'Transfer')600 .withArgs(wallet.address, router.address, amountIn)601 .to.emit(weth, 'Transfer')602 .withArgs(router.address, pair_0_weth_uni.address, input_weth_0)603 .to.emit(token0, 'Transfer')604 .withArgs(pair_0_weth_uni.address, router.address, expectedPoolInput0)605 .to.emit(token0, 'Transfer')606 .withArgs(router.address, indexPool.address, expectedPoolInput0)607 .to.emit(weth, 'Transfer')608 .withArgs(router.address, pair_0_weth_uni.address, input_weth_0_1)609 .to.emit(token0, 'Transfer')610 .withArgs(pair_0_weth_uni.address, pair_0_1_sushi.address, input_0_1)611 .to.emit(token1, 'Transfer')612 .withArgs(pair_0_1_sushi.address, router.address, expectedPoolInput1)613 .to.emit(token1, 'Transfer')614 .withArgs(router.address, indexPool.address, expectedPoolInput1)615 .to.emit(indexPool, 'Transfer')616 .withArgs(indexPool.address, router.address, mintAmount)617 .to.emit(indexPool, 'Transfer')618 .withArgs(router.address, wallet.address, mintAmount)619 .to.emit(weth, 'Transfer') // refund620 .withArgs(router.address, wallet.address, expandTo18Decimals(1))621 })622 })623 describe('swapETHForAllTokensAndMintExact', () => {624 const mintAmount = expandTo18Decimals(1)625 let expectedPoolInput0: BigNumber626 let expectedPoolInput1: BigNumber627 let input_weth_0: BigNumber628 let input_weth_0_1: BigNumber629 let input_0_1: BigNumber630 beforeEach(async () => {631 await addLiquidity();632 ([expectedPoolInput0, expectedPoolInput1] = allInGivenPoolOut(mintAmount));633 // weth -> token0634 input_weth_0 = swapInGivenOut(expectedPoolInput0, expandTo18Decimals(1000), expandTo18Decimals(1000))635 // token0 -> token1636 input_0_1 = swapInGivenOut(expectedPoolInput1, expandTo18Decimals(1000), expandTo18Decimals(1000))637 // weth -> token0 -> token1638 input_weth_0_1 = swapInGivenOut(639 input_0_1,640 expandTo18Decimals(1000).add(input_weth_0),641 expandTo18Decimals(1000).sub(expectedPoolInput0)642 )643 })644 it('Sushi -> Pool & Uni -> Sushi -> Pool', async () => {645 const amountIn = input_weth_0.add(input_weth_0_1)646 const balanceBefore = await ethers.provider.getBalance(wallet.address)647 const tx = router.swapETHForAllTokensAndMintExact(648 indexPool.address,649 [encodePathToken(constants.AddressZero, false), encodeIntermediary(token0.address, false, true)],650 mintAmount,651 { value: amountIn.add(expandTo18Decimals(1)) }652 )653 await expect(tx)654 .to.emit(weth, 'Deposit')655 .withArgs(router.address, amountIn.add(expandTo18Decimals(1)))656 .to.emit(weth, 'Transfer')657 .withArgs(router.address, pair_0_weth_uni.address, input_weth_0)658 .to.emit(token0, 'Transfer')659 .withArgs(pair_0_weth_uni.address, router.address, expectedPoolInput0)660 .to.emit(token0, 'Transfer')661 .withArgs(router.address, indexPool.address, expectedPoolInput0)662 .to.emit(weth, 'Transfer')663 .withArgs(router.address, pair_0_weth_uni.address, input_weth_0_1)664 .to.emit(token0, 'Transfer')665 .withArgs(pair_0_weth_uni.address, pair_0_1_sushi.address, input_0_1)666 .to.emit(token1, 'Transfer')667 .withArgs(pair_0_1_sushi.address, router.address, expectedPoolInput1)668 .to.emit(token1, 'Transfer')669 .withArgs(router.address, indexPool.address, expectedPoolInput1)670 .to.emit(indexPool, 'Transfer')671 .withArgs(indexPool.address, router.address, mintAmount)672 .to.emit(indexPool, 'Transfer')673 .withArgs(router.address, wallet.address, mintAmount)674 .to.emit(weth, 'Withdrawal') // refund675 .withArgs(router.address, expandTo18Decimals(1))676 expect(677 await ethers.provider.getBalance(wallet.address)678 ).to.eq(balanceBefore.sub(await getTransactionCost(tx)).sub(amountIn))679 })680 })681 describe('burnForAllTokensAndSwapForTokens', () => {682 const poolIn = expandTo18Decimals(1)683 let input_0: BigNumber684 let input_1: BigNumber685 let output_0_weth: BigNumber686 let output_1_0: BigNumber687 let output_0_weth_1: BigNumber688 beforeEach(async () => {689 await addLiquidity();690 ([input_0, input_1] = allOutGivenPoolIn(poolIn));691 // weth -> token0692 output_0_weth = swapOutGivenIn(input_0, expandTo18Decimals(1000), expandTo18Decimals(1000))693 // token1 -> token0694 output_1_0 = swapOutGivenIn(input_1, expandTo18Decimals(1000), expandTo18Decimals(1000))695 // token1 -> token0 -> weth696 output_0_weth_1 = swapOutGivenIn(697 output_1_0,698 expandTo18Decimals(1000).add(input_0),699 expandTo18Decimals(1000).sub(output_0_weth)700 )701 })702 it('Pool -> Uni & Pool -> Sushi -> Uni', async () => {703 await indexPool.approve(router.address, poolIn)704 await expect(705 router.burnForAllTokensAndSwapForTokens(706 indexPool.address,707 [0, 0],708 [encodePathToken(constants.AddressZero, false), encodeIntermediary(token0.address, true, false)],709 poolIn,710 weth.address,711 0712 )713 )714 .to.emit(indexPool, 'Transfer')715 .withArgs(wallet.address, router.address, poolIn)716 .to.emit(indexPool, 'Transfer')717 .withArgs(router.address, indexPool.address, poolIn)718 .to.emit(token0, 'Transfer')719 .withArgs(indexPool.address, router.address, input_0)720 .to.emit(token0, 'Transfer')721 .withArgs(router.address, pair_0_weth_uni.address, input_0)722 .to.emit(weth, 'Transfer')723 .withArgs(pair_0_weth_uni.address, wallet.address, output_0_weth)724 .to.emit(token1, 'Transfer')725 .withArgs(indexPool.address, router.address, input_1)726 .to.emit(token1, 'Transfer')727 .withArgs(router.address, pair_0_1_sushi.address, input_1)728 .to.emit(token0, 'Transfer')729 .withArgs(pair_0_1_sushi.address, pair_0_weth_uni.address, output_1_0)730 .to.emit(weth, 'Transfer')731 .withArgs(pair_0_weth_uni.address, wallet.address, output_0_weth_1)732 })733 it('Pool -> Sushi & Pool -> User', async () => {734 await indexPool.approve(router.address, poolIn)735 await expect(736 router.burnForAllTokensAndSwapForTokens(737 indexPool.address,738 [0, 0],739 [encodePathToken(constants.AddressZero, false), encodeIntermediary(constants.AddressZero, true, false)],740 poolIn,741 token0.address,742 0743 )744 )745 .to.emit(indexPool, 'Transfer')746 .withArgs(wallet.address, router.address, poolIn)747 .to.emit(indexPool, 'Transfer')748 .withArgs(router.address, indexPool.address, poolIn)749 .to.emit(token0, 'Transfer')750 .withArgs(indexPool.address, router.address, input_0)751 .to.emit(token0, 'Transfer')752 .withArgs(router.address, wallet.address, input_0)753 .to.emit(token1, 'Transfer')754 .withArgs(indexPool.address, router.address, input_1)755 .to.emit(token1, 'Transfer')756 .withArgs(router.address, pair_0_1_sushi.address, input_1)757 .to.emit(token0, 'Transfer')758 .withArgs(pair_0_1_sushi.address, wallet.address, output_1_0)759 })760 })761 describe('burnForAllTokensAndSwapForETH', () => {762 const poolIn = expandTo18Decimals(1)763 let input_0: BigNumber764 let input_1: BigNumber765 let output_0_weth: BigNumber766 let output_1_0: BigNumber767 let output_0_weth_1: BigNumber768 beforeEach(async () => {769 await addLiquidity();770 ([input_0, input_1] = allOutGivenPoolIn(poolIn));771 // weth -> token0772 output_0_weth = swapOutGivenIn(input_0, expandTo18Decimals(1000), expandTo18Decimals(1000))773 // token1 -> token0774 output_1_0 = swapOutGivenIn(input_1, expandTo18Decimals(1000), expandTo18Decimals(1000))775 // token1 -> token0 -> weth776 output_0_weth_1 = swapOutGivenIn(777 output_1_0,778 expandTo18Decimals(1000).add(input_0),779 expandTo18Decimals(1000).sub(output_0_weth)780 )781 })782 it('Pool -> Uni & Pool -> Sushi -> Uni', async () => {783 await indexPool.approve(router.address, poolIn)784 const balanceBefore = await ethers.provider.getBalance(wallet.address)785 const tx = router.burnForAllTokensAndSwapForETH(786 indexPool.address,787 [0, 0],788 [encodePathToken(constants.AddressZero, false), encodeIntermediary(token0.address, true, false)],789 poolIn,790 0791 )792 await expect(tx)793 .to.emit(indexPool, 'Transfer')794 .withArgs(wallet.address, router.address, poolIn)795 .to.emit(indexPool, 'Transfer')796 .withArgs(router.address, indexPool.address, poolIn)797 .to.emit(token0, 'Transfer')798 .withArgs(indexPool.address, router.address, input_0)799 .to.emit(token0, 'Transfer')800 .withArgs(router.address, pair_0_weth_uni.address, input_0)801 .to.emit(weth, 'Transfer')802 .withArgs(pair_0_weth_uni.address, router.address, output_0_weth)803 .to.emit(token1, 'Transfer')804 .withArgs(indexPool.address, router.address, input_1)805 .to.emit(token1, 'Transfer')806 .withArgs(router.address, pair_0_1_sushi.address, input_1)807 .to.emit(token0, 'Transfer')808 .withArgs(pair_0_1_sushi.address, pair_0_weth_uni.address, output_1_0)809 .to.emit(weth, 'Transfer')810 .withArgs(pair_0_weth_uni.address, router.address, output_0_weth_1)811 .to.emit(weth, 'Withdrawal')812 .withArgs(router.address, output_0_weth.add(output_0_weth_1))813 expect(814 await ethers.provider.getBalance(wallet.address)815 ).to.eq(816 balanceBefore817 .sub(await getTransactionCost(tx))818 .add(output_0_weth_1)819 .add(output_0_weth)820 )821 })822 })...
Lottery.test.ts
Source:Lottery.test.ts
1import { expect } from "chai";2import { Contract } from "ethers";3import { ethers } from "hardhat";4const games = [5 [1, false, 0, 0, 0],6 [2, false, 0, 0, 0],7];8const entrance = ethers.utils.parseEther('0.0036');9describe("Lottery", async () => {10 let lottery: Contract;11 const [ owner, guilherme, alicia ] = await ethers.getSigners();12 beforeEach(async () => {13 const Lottery = await ethers.getContractFactory("Lottery");14 lottery = await Lottery.connect(owner).deploy();15 });16 describe("Ownable", async () => {17 it("Should get the current owner", async () => {18 expect(await lottery.owner()).to.eq(owner.address);19 });20 it("Should trasnfer the ownership", async () => {21 expect(await lottery.owner()).to.eq(owner.address);22 await lottery.transferOwnership(guilherme.address);23 expect(await lottery.owner()).to.eq(guilherme.address);24 });25 });26 describe("Game creattion", async () => {27 it("Should create a game", async () => {28 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);29 });30 it("Should validate that only owner can create a game", async () => {31 await expect(lottery.connect(guilherme).createGame()).to.be.revertedWith('');32 });33 it("Should validate that there is an open game", async () => {34 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);35 await expect(lottery.createGame()).to.be.revertedWith('There is an open game');36 });37 });38 describe("Enter game", async () => {39 it("Should enter in a game", async () => {40 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);41 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))42 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);43 });44 it("Should validate that we a entering in a valid game number", async () => {45 await expect(lottery.enterGame(1)).to.be.revertedWith('Wrong game number');46 });47 it("Should validate that the game wasn't played yet", async () => {48 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);49 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))50 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance);51 await lottery.pickWiner(1);52 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))53 .to.be.revertedWith('Game already drawned');54 });55 });56 describe("Get all games", async () => {57 it("Should return an empty array", async () => {58 expect(await lottery.getAllGames()).to.deep.eq([]);59 });60 it("Should return the list of games", async () => {61 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);62 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))63 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance);64 await lottery.pickWiner(1);65 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(2, games[1]);66 const gamesReturned = await lottery.getAllGames();67 expect(gamesReturned.length).to.eq(2);68 })69 });70 describe("Get game by id", async () => {71 it("Should get a game by ID", async () => {72 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);73 const game = await lottery.getGameById(1);74 expect(game).to.haveOwnProperty('id');75 expect(game).to.haveOwnProperty('drawned');76 expect(game).to.haveOwnProperty('pickedNumber');77 expect(game).to.haveOwnProperty('drawDate');78 expect(game).to.haveOwnProperty('payedPrize');79 expect(game.id.toString()).to.eq('1');80 expect(game.drawned).to.eq(false);81 expect(game.pickedNumber.toString()).to.eq('0');82 expect(game.drawDate.toString()).to.eq('0');83 expect(game.payedPrize.toString()).to.eq('0');84 });85 it("Should validate that the game exists", async () => {86 await expect(lottery.getGameById(1)).to.be.revertedWith("Game doesn't exist");87 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);88 await expect(lottery.getGameById(2)).to.be.revertedWith("Game doesn't exist");89 });90 });91 describe("Get players by game", async () => {92 it("Should get the players", async () => {93 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);94 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))95 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);96 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))97 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance.mul(2));98 const players = await lottery.getPlayersByGame(1);99 expect(players.length).to.eq(2);100 expect(players[0]).to.eq(guilherme.address);101 expect(players[1]).to.eq(alicia.address);102 });103 it("Should validate that the game exists", async () => {104 await expect(lottery.getGameById(1)).to.be.revertedWith("Game doesn't exist");105 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);106 await expect(lottery.getGameById(2)).to.be.revertedWith("Game doesn't exist");107 });108 });109 describe("Get prizes by game", async () => {110 it("Should get the prize by game", async () => {111 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);112 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))113 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);114 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))115 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance.mul(2));116 const players = await lottery.getPlayersByGame(1);117 expect(await lottery.getPrizeByGame(1)).to.eq(entrance.mul(players.length));118 });119 it("Should validate that the game exists", async () => {120 await expect(lottery.getGameById(1)).to.be.revertedWith("Game doesn't exist");121 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);122 await expect(lottery.getGameById(2)).to.be.revertedWith("Game doesn't exist");123 });124 });125 describe("Get Winer", async () => {126 it("Should get the winer of a game", async () => {127 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);128 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))129 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);130 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))131 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance.mul(2));132 const transaction = await lottery.pickWiner(1);133 const receipt = await transaction.wait(1);134 const winer = receipt.events[0].args.player;135 expect(await lottery.getWiner(1)).to.eq(winer);136 });137 it("Should validate that the game exists", async () => {138 await expect(lottery.getGameById(1)).to.be.revertedWith("Game doesn't exist");139 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);140 await expect(lottery.getGameById(2)).to.be.revertedWith("Game doesn't exist");141 });142 });143 describe("Pick winer", async () => {144 it("Should picker the correct winner", async () => {145 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);146 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))147 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);148 await expect(lottery.connect(alicia).enterGame(1, { value: entrance }))149 .to.emit(lottery, 'EnterGameEvt').withArgs(alicia.address, 1, entrance.mul(2));150 const guilhermeBalanceBefore = await guilherme.getBalance();151 const aliciaBalanceBefore = await alicia.getBalance();152 const transaction = await lottery.pickWiner(1);153 const receipt = await transaction.wait(1);154 const winer = receipt.events[0].args.player;155 const prize = receipt.events[0].args.prize;156 const guilhermeBalanceAfter = await guilherme.getBalance();157 const aliciaBalanceAfter = await alicia.getBalance();158 if (winer == guilherme.address) {159 expect(guilhermeBalanceAfter).to.eq(guilhermeBalanceBefore.add(prize));160 expect(aliciaBalanceAfter).to.eq(aliciaBalanceBefore);161 } else {162 expect(aliciaBalanceAfter).to.eq(aliciaBalanceBefore.add(prize));163 expect(guilhermeBalanceAfter).to.eq(guilhermeBalanceBefore);164 }165 });166 it("Should validate that only owner can pick a winer", async () => {167 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);168 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))169 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);170 await expect(lottery.connect(alicia).pickWiner(1)).to.be.revertedWith('');171 });172 it("Shoul validate that the game number is valid", async () => {173 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);174 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))175 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);176 await expect(lottery.pickWiner(2)).to.be.revertedWith('Wrong game number');177 });178 it("Should validate that the game wasn't drawned before", async () => {179 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);180 await expect(lottery.connect(guilherme).enterGame(1, { value: entrance }))181 .to.emit(lottery, 'EnterGameEvt').withArgs(guilherme.address, 1, entrance);182 await expect(lottery.pickWiner(1)).to.emit(lottery, 'GameWinerEvt').withArgs(guilherme.address, 0, 1, entrance);183 await expect(lottery.pickWiner(1)).to.be.revertedWith('Game already drawned');184 });185 it("Should validate that there is at least one player", async () => {186 await expect(lottery.createGame()).to.emit(lottery, 'GameCreatedEvt').withArgs(1, games[0]);187 await expect(lottery.pickWiner(1)).to.be.revertedWith('There is no player to be drawned');188 });189 });...
Using AI Code Generation
1import { storiesOf } from '@storybook/react';2import { action } from '@storybook/addon-actions';3import { linkTo } from '@storybook/addon-links';4import { WithArgs } from 'storybook-root';5WithArgs(storiesOf('Button', module), {6 onClick: action('clicked'),7});8import { storiesOf } from '@storybook/react';9import { action } from '@storybook/addon-actions';10import { linkTo } from '@storybook/addon-links';11import { WithArgs } from 'storybook-root';12WithArgs(storiesOf('Button', module), {13 onClick: action('clicked'),14});15import { storiesOf } from '@storybook/react';16import { action } from '@storybook/addon-actions';17import { linkTo } from '@storybook/addon-links';18import { WithArgs } from 'storybook-root';19WithArgs(storiesOf('Button', module), {20 onClick: action('clicked'),21});22import { storiesOf } from '@storybook/react';23import { action } from '@storybook/addon-actions';24import { linkTo } from '@storybook/addon-links';25import { WithArgs } from 'storybook-root';26WithArgs(storiesOf('Button', module), {27 onClick: action('clicked'),28});29import { storiesOf } from '@storybook/react';30import { action } from '@storybook/addon-actions';31import { linkTo } from '@storybook/addon-links';32import { WithArgs } from 'storybook-root';33WithArgs(storiesOf('Button', module), {34 onClick: action('clicked'),35});36import { storiesOf } from '@storybook/react';37import { action } from '@storybook/addon-actions';38import { linkTo } from '@storybook/addon-links';39import { WithArgs } from 'storybook-root';40WithArgs(storiesOf('Button', module), {41 onClick: action('clicked'),42});43import { storiesOf } from '@storybook/react';44import { action
Using AI Code Generation
1import { WithArgs } from 'storybook-root-decorator';2import { storiesOf } from '@storybook/react';3import { action } from '@storybook/addon-actions';4import { Button } from './Button';5storiesOf('Button', module)6 .addDecorator(WithArgs)7 .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)8 .add('with some emoji', () => (9 <Button onClick={action('clicked')}>10 .add('with some args', ({ backgroundColor, color }) => (11 <Button style={{ backgroundColor, color }} onClick={action('clicked')}>12 ), { args: { backgroundColor: 'green', color: 'white' } })13 .add('with some more args', ({ backgroundColor, color }) => (14 <Button style={{ backgroundColor, color }} onClick={action('clicked')}>15 ), { args: { backgroundColor: 'red', color: 'black' } });16import React from 'react';17import PropTypes from 'prop-types';18export const Button = ({ backgroundColor, color, onClick, children }) => (19 <button type="button" onClick={onClick} style={{ backgroundColor, color }}>20 {children}21);22Button.propTypes = {23};24Button.defaultProps = {25};26import React from 'react';27import { storiesOf } from '@storybook/react';28import { action } from '@storybook/addon-actions';29import { Button } from './Button';30storiesOf('Button', module)31 .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)32 .add('with some emoji', () => (33 <Button onClick={action('clicked')}>34 .add('with some args', ({ backgroundColor, color }) => (35 <Button style={{
Using AI Code Generation
1import React from 'react';2import { storiesOf } from '@storybook/react';3import { WithArgs } from 'storybook-root';4storiesOf('React', module)5 .add('with args', () => <WithArgs />);6import React from 'react';7export default function WithArgs({ arg1, arg2 }) {8 return (9 <p>arg1: {arg1}</p>10 <p>arg2: {arg2}</p>11 );12}13WithArgs.args = {14};15import React from 'react';16import { WithArgs } from './WithArgs';17export default {18 argTypes: {19 arg1: { control: 'text' },20 arg2: { control: 'text' },21 },22};23import React from 'react';24import { WithArgs } from './WithArgs';25export default {26 argTypes: {27 arg1: { control: 'text' },28 arg2: { control: 'text' },29 },30};31import React from 'react';32import { WithArgs } from './WithArgs';33export default {34 argTypes: {35 arg1: { control: 'text' },36 arg2: { control: 'text' },37 },38};39import { ArgsTable, Story } from '@storybook/addon-docs/blocks';40import { WithArgs } from './WithArgs';41<ArgsTable of={WithArgs} />42<Story name="with args" args={{ arg1: 'arg1', arg2: 'arg2' }}>43 {({ arg1, arg2 }) => <WithArgs arg1={arg1} arg2={arg2} />}44import React from 'react';45import { WithArgs } from './WithArgs';46export default {
Using AI Code Generation
1import { WithArgs } from 'storybook-root';2import { MyComponent } from './MyComponent';3export default {4};5export const myComponentStory = () => <MyComponent />;6myComponentStory.story = {7};8import { WithArgs } from 'storybook-root';9import MyComponent from './MyComponent';10export default {11};12export const myComponentStory = () => <MyComponent />;13myComponentStory.story = {14};15import React from 'react';16import { addDecorator } from '@storybook/react';17import { withKnobs } from '@storybook/addon-knobs';18export const WithArgs = (storyFn, context) => {19 addDecorator(withKnobs);20 return storyFn();21};22And then import it in your stories23import { WithArgs } from 'storybook-root';24import MyComponent from './MyComponent';25export default {26};27export const myComponentStory = () => <MyComponent />;28myComponentStory.story = {29};
Using AI Code Generation
1import { WithArgs } from 'storybook-root';2import { Button } from 'storybook-root';3import { ButtonProps } from 'storybook-root';4import { ButtonSize } from 'storybook-root';5import { ButtonType } from 'storybook-root';6export default {7};8export const Primary = () => {9 const args: ButtonProps = {10 };11 return <WithArgs component={Button} args={args} />;12};13export const Secondary = () => {14 const args: ButtonProps = {15 };16 return <WithArgs component={Button} args={args} />;17};18export const Success = () => {19 const args: ButtonProps = {20 };21 return <WithArgs component={Button} args={args} />;22};23export const Danger = () => {24 const args: ButtonProps = {25 };26 return <WithArgs component={Button} args={args} />;27};28export const Warning = () => {29 const args: ButtonProps = {30 };31 return <WithArgs component={Button} args={args} />;32};33export const Info = () => {34 const args: ButtonProps = {35 };36 return <WithArgs component={Button} args={args} />;37};38export const Light = () => {39 const args: ButtonProps = {40 };41 return <WithArgs component={Button} args={args} />;42};43export const Dark = () => {44 const args: ButtonProps = {45 };46 return <WithArgs component={Button} args={args} />;47};48export const Link = () => {49 const args: ButtonProps = {
Using AI Code Generation
1import { WithArgs } from 'storybook-root-saga'2import { call, put } from 'redux-saga/effects'3import { doSomething } from './sagas'4export function* doSomethingWithArgs() {5 yield put({ type: 'DO_SOMETHING' })6 yield call(WithArgs, doSomething, 'some args')7 yield put({ type: 'DO_SOMETHING' })8}9export function* doSomething(args) {10 yield put({ type: 'DO_SOMETHING', args })11}12import { doSomethingWithArgs } from './test'13import { storiesOf } from '@storybook/react'14import { withSaga } from 'storybook-root-saga'15storiesOf('Test', module)16 .addDecorator(withSaga(doSomethingWithArgs))17 .add('test', () => <div>test</div>)18import { configure } from '@storybook/react'19import '../src/index.scss'20const req = require.context('../src', true, /.stories.js$/)21function loadStories() {22 req.keys().forEach(filename => req(filename))23}24configure(loadStories, module)
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!