рдмрдЧ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ
рдирдХрд▓реА sinon.restore()
(рди рд╣реА resetHistory
, resetBehavior
, рдФрд░ рди рд╣реА reset
) рдХреЛ рд╕рд╛рдлрд╝ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ред рдлрд┐рд░ рдореИрдВрдиреЗ рдПрдХ рдирдпрд╛ рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдмрдирд╛рдиреЗ рдФрд░ рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдХреЛ рд╕рд╛рдлрд╝ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ред рдХреЛрдИ рдкрд╛рдБрд╕рд╛ рдирд╣реАрдВред рдХреНрдпрд╛ рдпрд╣ рдЬрд╛рдирдмреВрдЭрдХрд░ рд╣реИ?
рдкреНрд░рдЬрдирди рдХрд░рдирд╛
it("Demonstrates how to restore a fake", () => {
let sandbox = sinon.createSandbox();
let thing = sandbox.fake();
thing("Hi");
expect(thing.calledOnce).to.be.true;
expect(thing.lastArg).to.equal("Hi");
sandbox.restore();
sandbox.resetHistory();
sandbox.resetBehavior();
sandbox.reset();
expect(thing.calledOnce).to.be.false; // Fails. thing.calledOnce === true
expect(thing.lastArg).to.be.undefined; // Fails if above commented out. thing.lastArg === "Hi"
});
рдЕрдкреЗрдХреНрд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░
рдореБрдЭреЗ рдЙрдореНрдореАрдж рдереА рдХрд┐ thing.lastArg
рдпрд╛ рддреЛ undefined
рдпрд╛ null
ред рдпрд╣ рдореБрдЭреЗ "Hi"
рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ
рдПрди/рдП
рдкреНрд░рд╕рдВрдЧ (рдХреГрдкрдпрд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВ):
рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рдВрджрд░реНрдн
рдмрд╕ рд╕рд┐рдиреЙрди рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдмреИрдХрдПрдВрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реВрдВред
рд╡реИрд╕реЗ рднреА, рдпрд╣ рдПрдХ рдмрдЧ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдЪ рдХрд╣реВрдВ рддреЛ, рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реВрдВред рдореБрдЭреЗ рдпрд╛рдж рд╣реИ рдХрд┐ рдирдХрд▓реА рдкрд░ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рдпрд╣ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдХреБрдЫ рдЕрд░реНрдереЛрдВ рдореЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдорд╛рдирд╛ рдЬрд╛рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ рд░рд╛рдЬреНрдп рд╣реИ (рдпрд╛рдиреА рд╡реЗ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ), рдХрд┐ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдпрддрд╛ рдХреЗрд╡рд▓ рдареВрдВрдарджрд╛рд░ рд╡реНрдпрд╡рд╣рд╛рд░ рддрдХ рд╣реА рд╕реАрдорд┐рдд рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИред
@mrodrick рдЗрд╕рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╡реНрдпрдХреНрддрд┐ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ...
рдпрджрд┐ рдпрд╣ рд╕рд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдХрдо рд╕реЗ рдХрдо рдбреЙрдХреНрд╕ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
@fatso83 рдмрд╣реБрдд рд╕рд░рд╛рд╣рдирд╛ рдХреА! .restore
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдирдХрд▓реА рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
рдЗрд╕ рдмрдЧ рд╕реЗ рдмрд╕ рдереЛрдбрд╝рд╛ рд╕рд╛ рд╣реА рдерд╛, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдареАрдХ рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред
рдЕрдЧрд░ рдЕрдЧрд▓реЗ рдХреБрдЫ рджрд┐рдиреЛрдВ рдореЗрдВ рдХреЛрдИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреАрдЖрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдореБрдЭреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордп рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ
рдореИрдВрдиреЗ рдЕрдм рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдФрд░ рдбреЙрдХреНрд╕ рдереЛрдбрд╝реЗ рднреНрд░рд╛рдордХ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдкрд░реАрдХреНрд╖рдг рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ (рд▓рдЧрднрдЧ) рдХреНрдпрд╛ рдХрд╣рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдЗрдП рдкрд╣рд▓реЗ рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ - рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд░реНрде рд╣реИ рд╕рднреА рд╕реНрдЯрдм рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЙрдирдХреА рдореВрд▓ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рд╕реНрдЯрдмреНрд╕ рд╣рдЯрд╛ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реЗ рдореВрд▓ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
рд░реАрд╕реЗрдЯ - рд░реАрд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдмрдирд╛рдП рдЧрдП рдкреНрд░рддреНрдпреЗрдХ рдирдХрд▓реА рдХреА рд╕реНрдерд┐рддрд┐ рд╕рд╛рдл рд╣реЛ рдЧрдИ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рдЕрднреА рднреА рд╡рд╕реНрддреБрдУрдВ рдкрд░ рдореМрдЬреВрдж рд╣реИрдВред
рдЙрдкрд░реЛрдХреНрдд рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣
рдЗрд╕рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ :-)
рдореИрдВрдиреЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИ рдФрд░ reset
рдФрд░ restore
рдХреЙрд▓ рдЙрд╕реА рддрд░рд╣ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдЙрдиреНрд╣реЗрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓рдЧрднрдЧ ... reset
calledOnce
рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╛рдл рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди lastArgument
рдХреЛ рд╕рд╛рдл рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдФрд░ рдЬрд╛рдВрдЪрдирд╛ рдХрд┐ рдХреНрдпрд╛ рдореИрдВрдиреЗ рдХреБрдЫ рд╡рд┐рд╡рд░рдг рдЦреЛ рджрд┐рдпрд╛ рд╣реИред
рдЗрд╕реЗ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рдХрд░рдирд╛, рд▓реЗрдХрд┐рди fake.lastArg
рдмрдЧ рдкрд░ рдПрдХ рдирдпрд╛ рдЕрдВрдХ рдЦреЛрд▓рдирд╛ред
рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП: https://runkit.com/fatso83/sinon-issue-2065
рдореИрдВ рдкреБрд╖реНрдЯрд┐ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдмрдЧ рдореЗрд░реЗ рд╕рд╛рде рднреА рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рджреГрд╢реНрдп рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрд░рдХрд░рд╛рд░ рд░рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд╝рдВрдХреНрд╢рди рдкрд┐рдЫрд▓реЗ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рд╕реНрдЯрдм рдкрд░рд┐рдгрд╛рдо рд░рдЦрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ sandbox.restore()
рд╡рд╣ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдХрд░рдиреЗ рдХрд╛ рдЗрд░рд╛рджрд╛ рд╣реИред
рдпрд╣ рдореЗрд░реЗ рд╕рд╛рде рд╕рдВрд╕реНрдХрд░рдг 7.5.0
@ oscarr-reyes рдХреНрдпрд╛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ https://github.com/sinonjs/sinon/commit/54df7f7000a9db2dd05319daa49518f3cd5a5dd7 рдЗрд╕реЗ рдЖрдкрдХреЗ рд▓рд┐рдП рдареАрдХ рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдиреЗ рдЗрд╕реЗ рдЕрднреА рддрдХ рдПрдХ рдирдИ рд░рд┐рд▓реАрдЬрд╝ рдореЗрдВ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рд╣реИред
@ oscarr-reyes рдХреНрдпрд╛ рдЖрдк рдПрдХ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ? рд╣рдордиреЗ рдЕрднреА рддрдХ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдмрдЧ рдХреЛ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдКрдкрд░ рджрд┐рдП рдЧрдП рдзрд╛рдЧреЗ рдФрд░ рдореЗрд░реА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдмрдЧ рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ рдПрдХ рдзреНрд╡рдЬ рдХреЛ рд╕рд╛рдл рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдмрд╛рдХреА рд╕рдм рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдЬрдм рддрдХ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреБрдЫ рдкреНрд░рдорд╛рдг рдирд╣реАрдВ рджреЗрдЦрддреЗ рд╣реИрдВ, рддрдм рддрдХ рдХреЛрдИ рдмрдЧ рдирд╣реАрдВ рд╣реИ (lastArg рдзреНрд╡рдЬ рдХреЗ рдЕрд▓рд╛рд╡рд╛)ред
рдореБрдЭреЗ рдПрдХ рд╣реА рдореБрджреНрджреЗ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИред
рдореИрдВ рдЕрдкрдиреЗ "ValidateCaptcha" рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рд╕реИрдВрдбрдмреЙрдХреНрд╕рд┐рдВрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЬрдм рдореИрдВ рдЗрд╕реЗ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдпрд╣ рд╕реНрдЯрдм рдЬрд╛рд░реА рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддрд╛ рд╣реИред
/src/middlewares/captcha.js
const request = require("got");
const validateCaptcha = async (req, res, next) => {
// if (process.env.NODE_ENV !== "production") return next();
const captcha = req.body["g-recaptcha-response"] || req.body.g_recaptcha_response;
// g-recaptcha-response is the key that browser will generate upon form submit.
// if its blank or null means user has not selected the captcha, so return the error.
if (captcha === undefined || captcha === "" || captcha === null)
return res
.status(400)
.json({ message: "Please, verify that you are not a robot" });
// Put your secret key here.
const secretKey = process.env.GOOGLE_CAPTCHA_API_SECRET_KEY;
// req.connection.remoteAddress will provide IP address of connected user.
const verificationUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captcha}`;
try {
// Hitting GET request to the URL, Google will respond with success or error scenario.
const { body } = await request.post(verificationUrl, { responseType: "json" });
// Success will be true or false depending upon captcha validation.
if (body.success !== undefined && !body.success)
return res
.status(400)
.json({ message: "Captcha validation error" });
} catch (error) {
return res
.status(503)
.json({ message: "Couldn't validate captcha" });
}
next();
};
module.exports = {
validateCaptcha,
};
/test/api/user.spec.js
require("../setup.spec");
const supertest = require("supertest");
const captcha = require("../../src/middlewares/captcha");
const sinon = require("sinon");
let app;
let agent;
let sandbox;
const login = (anAgent, userCredentials) =>
anAgent
.post("/api/users/signIn")
.send(userCredentials);
const logout = (anAgent) =>
anAgent
.post("/api/users/signOut");
describe("User endpoints", function () {
this.beforeAll(async () => {
sandbox = sinon.createSandbox();
sandbox
.stub(captcha, "validateCaptcha")
.callsFake(async (req, res, next) => {
console.log("Validate Captcha FAKE");
return next();
});
// sandbox.restore();
});
this.beforeEach(async () => {
app = require("../../src/app");
agent = supertest.agent(app);
const sequelize = require("../../src/models");
await sequelize.sync({ force: true });
const Customer = require("../../src/models/customer");
const User = require("../../src/models/user");
await Customer.create(
{
firstName: "Test",
lastName: "Customer",
user: {
email: "[email protected]",
password: "boo",
},
},
{
include: [User],
}
);
});
this.afterEach(async () => {
sandbox.restore();
});
it("should create a new user", function (done) {
agent
.post("/api/users/signUp")
.send({
firstName: "firstName",
lastName: "lastName",
email: "[email protected]",
password: "aPassword",
})
.expect(201)
.end((err, res) => {
err ? done(err) : done();
});
});
it("should sign in", function (done) {
login(agent, { email: "[email protected]", password: "boo" })
.expect(200)
.end((err, res) => {
const { message, user } = res.body;
message.should.be.equal("valid");
user.should.have.property("email").equal("[email protected]");
user.should.have.property("customer").have.property("firstName").equal("Test");
user.should.have.property("customer").have.property("lastName").equal("Customer");
agent
.get("/api/users/me")
.expect(200)
.end((err, res) => {
const user = res.body;
user.should.have.property("email").equal("[email protected]");
user.should.have.property("customer").have.property("firstName").equal("Test");
user.should.have.property("customer").have.property("lastName").equal("Customer");
err ? done(err) : done();
});
});
});
it("should sign out", async function () {
await login(agent, { email: "[email protected]", password: "boo" });
await logout(agent)
.expect(302)
.expect("Location", "/");
return agent
.get("/api/users/me")
.expect(401);
});
it("should return unauthorized", function (done) {
agent
.get("/api/users/me")
.expect(401)
.end((err, res) => {
err ? done(err) : done();
});
});
});
рдореИрдВ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:
1) рдкрд╣рд▓реЗ рдЯреЗрд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдореЙрдХ рдХрд░реЗрдВ
2) рдЗрд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд▓рд┐рдП рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ
рдкрд╣рд▓реЗ рд╕рднреА рдХреЗ рдЕрдВрджрд░ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рд╣реИ "sandbox.restore ();" рдХрд┐ рдореИрдВрдиреЗ рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ рдФрд░ рд╡рд╣рд╛рдБ рдпрд╣ рдХрд╛рдо рдХрд┐рдпрд╛... рд▓реЗрдХрд┐рди рдпрд╣ рдмреЗрдХрд╛рд░ рд╣реИ
рдореИрдВ рднреА рдЕрдкрдиреЗ app.js . рдХреЗ рд▓рд┐рдП рд╣рд░ рдмрд╛рд░ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ
рдкрд╛рдВрдЪ рдорд┐рдирдЯ рдкрд╣рд▓реЗ рдореИрдВрдиреЗ рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рд╣реИ:
require("../setup.spec");
const decache = require("decache");
const supertest = require("supertest");
const sequelize = require("../../src/models");
const sinon = require("sinon");
const sandbox = sinon.createSandbox();
let agent;
const login = (anAgent, userCredentials) =>
anAgent
.post("/api/users/signIn")
.send(userCredentials);
const logout = (anAgent) =>
anAgent
.post("/api/users/signOut");
describe("User endpoints", function () {
this.beforeAll(async () => {
});
this.beforeEach(async () => {
decache("../../src/app");
decache("../../src/middlewares/captcha");
const captcha = require("../../src/middlewares/captcha");
sandbox
.stub(captcha, "validateCaptcha")
.callsFake(async (req, res, next) => {
console.log("Validate Captcha FAKE");
return next();
});
const app = require("../../src/app");
agent = supertest.agent(app);
await sequelize.sync({ force: true });
const Customer = require("../../src/models/customer");
const User = require("../../src/models/user");
await Customer.create(
{
firstName: "Test",
lastName: "Customer",
user: {
email: "[email protected]",
password: "boo",
},
},
{
include: [User],
}
);
});
this.afterEach(async () => {
sandbox.restore();
});
it("should create a new user", function (done) {
agent
.post("/api/users/signUp")
.send({
firstName: "firstName",
lastName: "lastName",
email: "[email protected]",
password: "aPassword",
})
.expect(201)
.end((err, res) => {
err ? done(err) : done();
});
});
it("should sign in", function (done) {
login(agent, { email: "[email protected]", password: "boo" })
.expect(200)
.end((err, res) => {
const { message, user } = res.body;
message.should.be.equal("valid");
user.should.have.property("email").equal("[email protected]");
user.should.have.property("customer").have.property("firstName").equal("Test");
user.should.have.property("customer").have.property("lastName").equal("Customer");
agent
.get("/api/users/me")
.expect(200)
.end((err, res) => {
const user = res.body;
user.should.have.property("email").equal("[email protected]");
user.should.have.property("customer").have.property("firstName").equal("Test");
user.should.have.property("customer").have.property("lastName").equal("Customer");
err ? done(err) : done();
});
});
});
it("should sign out", async function () {
await login(agent, { email: "[email protected]", password: "boo" });
await logout(agent)
.expect(302)
.expect("Location", "/");
return agent
.get("/api/users/me")
.expect(401);
});
it("should return unauthorized", function (done) {
agent
.get("/api/users/me")
.expect(401)
.end((err, res) => {
err ? done(err) : done();
});
});
});
рдореИрдВ рднреА рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВред рдпрд╣ рдмрдВрдж рдХреНрдпреЛрдВ рд╣реИ?
рдпрд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛ рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕реНрдЯрдм рдХреЛ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рдкреНрд░рддрд┐ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рд╣реЛред рдЕрдлреИрдХ рдпреЗ рджреЛрдиреЛрдВ _рдЪрд╛рд╣рд┐рдП_ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд╡реИрдз рддрд░реАрдХреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛() рдЕрд▓рдЧ рд╣реИред рдПрдХ рдореЗрдВ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рджреВрд╕рд░реЗ рдореЗрдВ рдЗрд╕рдХреЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдкрд░рд┐рдгрд╛рдо рд╣реЛрддреЗ рд╣реИрдВред
const sinon = require('sinon')
// restore does not work as expected
let db = {
query: () => {
return 'my query 1'
}
}
const dbStub = sinon.stub().resolves('somejson')
db.query = dbStub
db.query() // somejson
sinon.restore()
db.query() // resolves nothing
// restore works as expected
db = {
query: () => {
return 'my query 1'
}
}
sinon.stub(db, 'query').resolves('somejson')
db.query() // somejson
sinon.restore()
db.query() //my query 1
@scottpatrickwright рдЬрдм рдЖрдк рд╕реАрдзреЗ db.query
рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ sinon
рдХреЛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдпрд╛ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рд╕реЗ рдкрд╣рд▓реЗ рдореВрд▓реНрдп рдХреНрдпрд╛ рдерд╛ред
@scottpatrickwright рдпрд╣ рдмрдВрдж рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдИ рдмрдЧ рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдзрд╛рдЧреЗ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╕рд┐рд░реНрдл рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддреНрд░реБрдЯрд┐ рдереА, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣реИ: рдпрд╣ рд╡рд░реНрдгрд┐рдд рдФрд░ рдЗрдЪреНрдЫрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ :-)
рд╕рд┐рдиреЙрди рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдЙрди рдЪреАрдЬреЛрдВ рдХреЛ рд╕рд╛рдл рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд╣ рдЬрд╛рдирддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╕рд┐рдиреЙрди рдХреЛ рдЙрди рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЬреНрдЮрд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рдирдХреЗ рд╕рд╛рде рд╡рд╣ рдмрд╛рддрдЪреАрдд рдХрд░рддрд╛ рд╣реИред рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдареВрдВрда рдХреЛ рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╕рд┐рдиреЙрди рдХреЛ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдЕрд╕рд╛рдЗрди рдХреА рдЧрдИ рдХрд┐рд╕реА рднреА рд╡рд╕реНрддреБ рд╕реЗ рдЕрд╡рдЧрдд рдирд╣реАрдВ рдХрд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд╣ рджреВрд╕рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдЗрд╕реЗ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП sinon.replace(obj, fieldname, fake)
рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд┐рд░реНрдл рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ
рдХрд╛рдлреА рдЙрдЪрд┐рдд - рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рд╢реБрдХреНрд░, 19 рдлрд░рд╡рд░реА, 2021 рдХреЛ рд╕реБрдмрд╣ 7:02 рдмрдЬреЗ рдХрд╛рд░реНрд▓-рдПрд░рд┐рдХ рдХреЛрдкреНрд╕реЗрдВрдЧ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com
рд▓рд┐рдЦрд╛ рдерд╛:
@scottpatrickwright https://github.com/scottpatrickwright рдпрд╣ рдмрдВрдж рд╣реИ
рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдИ рдмрдЧ рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдзрд╛рдЧреЗ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдмрд╕ рдЧрдпрд╛ рдерд╛
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддреНрд░реБрдЯрд┐, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣реИ: рдпрд╣ рд╡рд░реНрдгрд┐рдд рдФрд░ рдЗрдЪреНрдЫрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ :-)рд╕рд┐рдиреЙрди рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдЙрди рдЪреАрдЬреЛрдВ рдХреЛ рд╕рд╛рдл рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд╣ рдЬрд╛рдирддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╕рд┐рдиреЛрди рд╣реИ
рдЙрди рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЬреНрдЮрд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЬрд┐рдирдХреЗ рд╕рд╛рде рдпрд╣ рдмрд╛рддрдЪреАрдд рдХрд░рддрд╛ рд╣реИ рдареВрдВрда рдЖрдк
рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╕рд┐рдиреЙрди рдХреЛ рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрд╡рдЧрдд рдирд╣реАрдВ рдХрд░рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ
рдЬрд┐рди рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЖрдк рдЗрд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд░рддреЗ рд╣реИрдВред рд╡рд╣ рджреВрд╕рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП sinon.replace(obj, fieldname, fake) рднреА рдХрд░реЗрдВред рдпрд╣ рд╕рд┐рд░реНрдл
рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 , рдпрд╛
рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдХрд╛рдлреА рдЙрдЪрд┐рдд - рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рд╢реБрдХреНрд░, 19 рдлрд░рд╡рд░реА, 2021 рдХреЛ рд╕реБрдмрд╣ 7:02 рдмрдЬреЗ рдХрд╛рд░реНрд▓-рдПрд░рд┐рдХ рдХреЛрдкреНрд╕реЗрдВрдЧ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com
рд▓рд┐рдЦрд╛ рдерд╛: