Skip to content

Instantly share code, notes, and snippets.

@WMcKibbin
Last active April 14, 2020 22:26
Show Gist options
  • Save WMcKibbin/6f8adfefbff6d2cf60d0d61ab9f6092f to your computer and use it in GitHub Desktop.
Save WMcKibbin/6f8adfefbff6d2cf60d0d61ab9f6092f to your computer and use it in GitHub Desktop.

Revisions

  1. WMcKibbin revised this gist Apr 14, 2020. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions test.js
    Original file line number Diff line number Diff line change
    @@ -87,6 +87,19 @@ export default class UserDao extends Dao {
    if (!foundUser) return null
    return new UserDao(foundUser)
    }
    /**
    * Update user contained in this UserDao
    * @param {String} type - The type of update for the UserDao
    * @param {String} key - The key in the UserDao to update
    * @param {String|Object|Array|Boolean|Date|Number} update - The update for the UserDao
    * @return {Promise<UserDao>} - The updated UserDao
    */
    async updateUser(key, update, type) {
    if (!await Dao._init()) new Error('Database cannot be initialized')
    const updateSuccess = type ? await this._user.updateOne({[type]:{[key]: update}},{new: true}) : await this._user.updateOne({[key]: update},{new: true});
    if (updateSuccess.ok === 1) return this._user.toObject()
    return null
    }
    }
    ///////////////////////////////////////////////////////////////
    //Testing
  2. WMcKibbin revised this gist Apr 14, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion test.js
    Original file line number Diff line number Diff line change
    @@ -107,7 +107,7 @@ describe("AuthController Class", function () {
    }
    })
    //This apparently does not work.
    sinon.stub(UserDao.prototype.contructor, async () => {
    sinon.stub(UserDao.prototype.constructor, async () => {
    return { updateUser: async () => { return true } } //
    })
    //This is an application context class that provides dependency injection for the application
  3. WMcKibbin created this gist Apr 14, 2020.
    130 changes: 130 additions & 0 deletions test.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    ///////////////////////////////////////////////////////////////
    //Dependency Injection
    ///////////////////////////////////////////////////////////////
    /**
    * Provides Inversion of Control interface wrapping Bottlejs
    */
    class ApplicationContext {

    /**
    * Create a new ApplicationContext with a given name
    * @param {String} name - The name of the application context
    */
    constructor(name = 'main') {
    if (!name) throw new Error('ApplicationContext name must be defined');
    if (!typeof (name) === 'string') throw new Error('ApplicationContext name must be a string.');
    try {
    this._bottle = new Bottle(name);
    } catch (error) {
    console.error(error)
    throw new Error(`Unable to create new Application Context with name ${name}`);
    }
    this._name = name
    }

    /**
    * Register a new service into the Application Context. Will throw error if name|service is undefined
    * @param {String} name - The name of the service that is being registered into the ApplciationContext
    * @param {any} service - The service object to register to the given name.
    */
    register(name, service) {
    if (!name) throw new Error('No name given to register service.');
    if (!typeof (name) === 'string') throw new Error('Service name must be a string.');
    if (!service) throw new Error('No service object given.');
    this._bottle.service(name, service);
    }

    /**
    * Get the registered service with a given name. Throws error if name undefined or service not registered.
    * @param {String} name - The name of the service to retrieve.
    * @returns {any} - The Service object
    */
    get(name) {
    if (!name) throw new Error('Serice name must be defined')
    if (!typeof (name) === 'string') throw new Error('Service name must be a string.');
    const service = this._bottle.container[name];
    if (!service) throw new Error(`Service ${name} not found. Please ensure all required services are registered into the Application Context`);
    return service;
    }

    /**
    * Clear the Application context of all services
    */
    clear() {
    Bottle.clear(this._name)
    }
    }

    //Export Singleton Application Context to be used across the application.
    const appContext = new ApplicationContext()
    Object.freeze(appContext)
    export default appContext;

    ///////////////////////////////////////////////////////////////
    //User Database
    ///////////////////////////////////////////////////////////////
    /**
    * Data Access object for user profiles
    */
    export default class UserDao extends Dao {

    /**
    * Returns a new UserDao object
    * @param {Object} user - the populated user object
    */
    constructor(user) {
    super()
    this._user = new User(user);
    }
    /**
    * Returns a new UserDao for the user with the username specified
    * @param {String} usernameDb - The unique username for the user to fetch
    * @return {Promise<UserDao>} - The user with the given username
    */
    static async fromUserName(usernameDb) {
    if (!await Dao._init()) new Error('Database cannot be initialized');
    let foundUser = await User.findOne({ 'usernameDb': usernameDb }).exec();
    if (!foundUser) return null
    return new UserDao(foundUser)
    }
    }
    ///////////////////////////////////////////////////////////////
    //Testing
    ///////////////////////////////////////////////////////////////

    /* Test Suite for Authentication Controller*/
    describe("AuthController Class", function () {
    //Tests for login functionality
    describe("#login", function () {
    before(async function () {
    context.clear()
    //Need to mock the user retrieval from the DB, done via UserDao Class
    sinon.stub(UserDao.fromUserName, async () => {
    return {
    username: 'userperson',
    profile: {},
    password: 'bcrypt_hash_goes_here'
    }
    })
    //This apparently does not work.
    sinon.stub(UserDao.prototype.contructor, async () => {
    return { updateUser: async () => { return true } } //
    })
    //This is an application context class that provides dependency injection for the application
    // Modules grab their dependencies with context.get('service_name')
    context.register('UserDao', UserDao)
    })
    it("login: Should throw a 400 for a password less than 8 characters", async function () {
    const auth = new AuthController(process.env.SERVER_SECRET);
    const shortPassword = '@1234gH'
    try {
    const JWT = await auth.login(testUser, shortPassword)
    throw new Error('AuthController Should have thrown an 400 HttpError.')
    } catch (error) {
    if (!error instanceof HttpError) throw error;
    expect(error.code).to.equal(400)
    return true
    }
    });
    })
    })