Registering project-wide test traits

I have a test trait for stubbing out how I retrieve JWTs:

'use strict';

const Config = use('Config');
const authenticationClient = use('Auth0/AuthenticationClient');

module.exports = function (suite) {
  suite.before(async () => {
    const ctx = new suite.Context();
    const { admin, user } = ctx; // Depends on another trait that provides this data in context.

    // Login to Auth0 to obtain access token using Resource Owner Password Grant
    try {
      const [adminToken, userToken] = [
        await authenticationClient.passwordGrant({
          username: admin.email,
          password: admin.password,
          audience: Config.get('auth0.jwt.audience'),
          client_secret: Config.get('auth0.clientSecret'),
          scope: Config.get('auth0.clientCredentialsScope')
        }),
        await authenticationClient.passwordGrant({
          username: user.email,
          password: user.password,
          audience: Config.get('auth0.jwt.audience'),
          client_secret: Config.get('auth0.clientSecret'),
          scope: Config.get('auth0.clientCredentialsScope')
        })
      ];

      // Save the tokens so that tests can use them for making requests.
      suite.Context.getter('adminToken', () => adminToken);
      suite.Context.getter('userToken', () => userToken);
    } catch (e) {
      console.error(e); // Use console.error since Logger eats up proper stack trace
      throw e;
    }
  });
};

The documentation is clear on creating a test trait for a single test suite. The documentation skimps out for declaring project-wide test traits for reuse. If I want to reuse the above trait in multiple test suites, what is the current best practice besides copy-pasting to every test suite file?

  1. Do I separate it out as a separate file? If so, where should it live? (e.g. projectRoot/tests/traits/jwt.js)
  2. I’m guessing IoC container binding is required for multiple tests to use the trait. Where should I declare this binding in my project?
  3. What is the best practice for the name of the IoC binding? (e.g. App/Traits/Jwt vs Test/Traits/Jwt)

Also strugling with this… If I solve it will post solution here…

EDIT: Well, because Test folder is not accessible via trait(‘Test/…’) I think the cleanest solution is to add test trait to App/Traits/Test/NameOfTrait.js

It works for me… In any test where I use my custom test traits I just add trait(‘App/Traits/Test/NameOfTrait’)

@hlozancic I figured out a way to get Test/Traits to autoload without having it in App/ (I wanted to separate out the test code from application code). There’s a little hidden feature in the framework which will autoload directories. You’ll have to edit the package.json and add the following entry:

{
  …
   "autoload": {
    "App": "./app",
    "Test/Traits": "./test/traits"
  },
  …
}

For a framework that prides itself on anti-bikeshedding, there’s a very little documentation on best practices though. :confused:

1 Like

Thank for providing solution for this! Will definetely use different approach now :slight_smile:

Docs are open source and there is a recipes section, so feel free to create a PR

1 Like