Ember Mirage custom route

I can’t figure out why Mirage fails to mock a request and I’m getting the error when running an acceptance test:

#tests/acceptance/dashboard-test.js

import { module, test } from 'qunit';
import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { authenticateSession } from 'ember-simple-auth/test-support';
import setupMirageTest from 'ember-cli-mirage/test-support/setup-mirage';
import { setupWindowMock } from 'ember-window-mock';

module('Acceptance | Dashboard', function(hooks) {
  setupWindowMock(hooks);
  setupApplicationTest(hooks);
  setupMirageTest(hooks);

  test('Authenticated users can visit /dashboard', async function(assert) {
    let shop = this.server.create('shop');
    this.server.create('user', { shop });

    await authenticateSession({
      access_token: 'abcdDEF',
      token_type: 'Bearer'
    });

    await visit('/dashboard');

    assert.equal(currentURL(), '/dashboard', 'user is on dashboard page');
  });
});

The error happens when calling the following function in the application route:

#routes/application.js

_loadCurrentUser() {
    return this.get('currentUser').loadCurrentUser().catch(() => this.get('session').invalidate());
  },

Here is how loadCurrentUser function is defined in current-user service:

#services/current-user.js

export default Service.extend({
  session:        service(),
  store:          service(),
  flashMessages:  service(),
  intl:           service(),
  currentShop:    service(),
  shopService:    service(),

  async loadCurrentUser() {
    this.get('flashMessages').clearMessages();
    if (this.get('session.isAuthenticated')) {
      let user = await this.get('store').queryRecord('user', { me: true });
      
      if (user) {
        this.get('flashMessages').success(this.get('intl').t('flash.signed_in'));
        this.get('currentShop').setShop(user.get('shop'));
        this.set('user', user);
        this.get('shopService').loadShops();
        return user;
      } else {
        this._respondWithError();
      }

    } else {
      this.get('flashMessages').info(this.get('intl').t('flash.signed_off'));
      return RSVP.resolve();
    }
  },

  _respondWithError() {
    this.get('flashMessages').danger(this.get('intl').t('flash.authentication.error'));
    return RSVP.reject();
  }
});

If I’m not mistaken, the error happens on the line:

let user = await this.get('store').queryRecord('user', { me: true });

and then catched in application route catch block.

Here is how I defined the routes in Mirage config.js file:

#../mirage/config.js

export default function() {

  this.get('/users/me', (schema) => {
    return schema.users.first();
  });
  
  this.get('/shops');
}

The factories are also created for User and Shop:

#mirage/factories/user.js

import { Factory, faker, association } from 'ember-cli-mirage';

export default Factory.extend({
  firstName: faker.name.firstName(),
  lastName: faker.name.lastName(),
  username: faker.internet.userName(),
  shop: association()
});

#mirage/factories/shop.js

import { Factory, faker } from 'ember-cli-mirage';

export default Factory.extend({
  identifier: faker.random.number(),
  category: faker.commerce.department(),
  name: faker.company.companyName()
});

If I modify the catch block to display the caught error as follows:

# routes/application.js

_loadCurrentUser() {
    return this.get('currentUser').loadCurrentUser().catch((e) => console.log('+++++++++ catched: ' + e));
    //return this.get('currentUser').loadCurrentUser().catch(() => this.get('session').invalidate());
  },

it displays:

'\'+++++++++ catched: SyntaxError: Unexpected end of JSON input\'\n'

I also defined the serializers for Mirage environment using the same settings as in serializers/application.js:

#mirage/serializers/application.js

import { JSONAPISerializer } from 'ember-cli-mirage';
import { underscore } from '@ember/string';

export default JSONAPISerializer.extend({
  keyForAttribute: function(attr) {
    return underscore(attr);
  },

  keyForRelationship: function(rawKey) {
    return underscore(rawKey);
  }
});

#mirage/serializers/user.js

import ApplicationSerializer from './application';

export default ApplicationSerializer.extend({
  include: ['shop']
});

What am I missing? Thank you

Mirage CLI version: 0.4.15 ember: `3.8.2`` Thank you

I’m getting closer, - the problem is now in decoding a token passed from the Ember test to the backend controller.
So, from Ember dashboard-test I’m calling the backend user/me end-point to identify a user. And here is where the problem is: the backend needs to decode the token passed in the request header as:

Bearer abcdDEF....

It looks a little bit weird, - why even if I mock the end-point users/me with Mirage, the backend proceeds as usual? It’s supposed to be totally ignored, no?

The error I’m getting from the response:

Assertion Failed: normalizeResponse must return a valid JSON API document:\\n\\t* One or more of the following keys must be present: "data", "errors", "meta".\'\n

Any idea ? Is it possible to debug in some way this kind of tests ?

Are you sure the mirage route is being called? Looking at what’s there the queryRecord() call should hit an endpoint like this.get('/users');. The me part of queryRecord('...', {me: true}) would just be a queryParam right?

I got help on Discord channel, (special thanks to @jelhan) for pointing out to the missing return statement and providing the link to the opened issue.

Actually, what worked:

# mirage/config.js

export default function() {

  this.get('/users/me', (schema) => {
    return schema.users.first();
  });

  this.get('/shops');
}


# tests/acceptance/dashboard-tests.js

import { module, test } from 'qunit';
import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { authenticateSession } from 'ember-simple-auth/test-support';
import setupMirageTest from 'ember-cli-mirage/test-support/setup-mirage';
import { setupWindowMock } from 'ember-window-mock';

module('Acceptance | Dashboard', function(hooks) {
  setupWindowMock(hooks);
  setupApplicationTest(hooks);
  setupMirageTest(hooks);

  test('Authenticated users can visit /dashboard', async function(assert) {
    let shop = server.create('shop');
    server.create('user', { shop });

    await authenticateSession({
      access_token: 'azerty',
      token_type: 'Bearer'
    });

    await visit('/dashboard');
    assert.equal(currentURL(), '/dashboard', 'user is on dashboard page');
  });
});

I also created application and user serializers in mirage folder as described above.