How to authenticate Supertest requests with Passport?

后端 未结 8 1424
囚心锁ツ
囚心锁ツ 2020-11-28 21:22

I\'m using Passport.js for authentication (local strategy) and testing with Mocha and Supertest.

How can I create a session and make authenticated requests with Supe

8条回答
  •  眼角桃花
    2020-11-28 22:13

    Here is a neat approach which has the added benefit of being reusable.

    const chai = require("chai")
    const chaiHttp = require("chai-http")
    const request = require("supertest")
    
    const app = require("../api/app.js")
    
    const should = chai.should()
    chai.use(chaiHttp)
    
    
    describe("a mocha test for an expressjs mongoose setup", () => {
      // A reusable function to wrap your tests requiring auth.
      const signUpThenLogIn = (credentials, testCallBack) => {
        // Signs up...
        chai
          .request(app)
          .post("/auth/wizard/signup")
          .send({
            name: "Wizard",
            ...credentials,
          })
          .set("Content-Type", "application/json")
          .set("Accept", "application/json")
          .end((err, res) => {
            // ...then Logs in...
            chai
              .request(app)
              .post("/auth/wizard/login")
              .send(credentials)
              .set("Content-Type", "application/json")
              .set("Accept", "application/json")
              .end((err, res) => {
                should.not.exist(err)
                res.should.have.status(200)
                res.body.token.should.include("Bearer ")
                // ...then passes the token back into the test 
                // callBack function.
                testCallBack(res.body.token)
              })
          })
      }
    
      it.only("flipping works", done => {
        // "Wrap" our test in the signUpThenLogIn function.
        signUpLogIn(
          // The credential parameter.
          {
            username: "wizard",
            password: "youSHALLpass",
          },
          // The test wrapped in a callback function which expects 
          /// the token passed back from when signUpLogIn is done.
          token => {
            // Now we can use this token to run a test... 
            /// e.g. create an apprentice.
            chai
              .request(app)
              .post("/apprentice")
              .send({ name: "Apprentice 20, innit" })
               // Using the token to auth! 
              .set("Authorization", token)
              .end((err, res) => {
                should.not.exist(err)
                res.should.have.status(201)
                // Yep. apprentice created using the token.
                res.body.name.should.be.equal("Apprentice 20, innit")
                done()
              })
          }
        )
      })
    })
    

    BONUS MATERIAL

    To make it even more reusable, put the function into a file called "myMochaSuite.js" which you can replace "describe" with when testing your api server. Be a wizard and put all your before/after stuff in this "suite". e.g.:

    // tests/myMochaSuite.js  
    module.exports = (testDescription, testsCallBack) => {
      describe(testDescription, () => {
        const signUpThenLogIn = (credentials, testCallBack) => {
          // The signUpThenLogIn function from above
        }
    
        before(async () => {
          //before stuff like setting up the app and mongoose server.
        })
        beforeEach(async () => {
          //beforeEach stuff clearing out the db
        })
        after(async () => {
          //after stuff like shutting down the app and mongoose server.
        })
        
        // IMPORTANT: We pass signUpLogIn back through "testsCallBack" function.
        testsCallBack(signUpThenLogIn)
      })
    }
    
    // tests/my.api.test.js
    // chai, supertest, etc, imports +
    const myMochaSuite = require("./myMochaSuite")
    
    // NB: signUpThenLogIn coming back into the tests.
    myMochaSuite("my test description", signUpThenLogIn => {
       it("just works baby", done => {
         signUpThenLogIn(
           {username: "wizard", password: "youSHALLpass"},
           token => {
             chai
               .request(app)
               .get("/apprentices/20")
               // Using the incoming token passed when signUpThenLogIn callsback.
               .set("Authorization", token)
               .end((err, res) => {
                 res.body.name.equals("Apprentice 20, innit")
                 done()
               })
           }
         )
       })
    })
    

    Now you have a even more reusable suite "wrapper" for all your tests, leaving them uncluttered.

提交回复
热议问题