DEV Community

Michal Bryxí
Michal Bryxí

Posted on

Add fulltext filter support to ember-cli-mirage

There is an open issue in ember-cli-mirage that tries to bring filter support for JSONAPI Serializer. Unfortunately my tests needed this functionality now. More specifically they needed a fulltext filtering support.

Here is a solution I came up with.

First make sure that factories for all endpoints produce something that we can filter on. I simply created attribute fulltext that returns a string of things that I want to filter on:

// mirage/factories/item.js

import faker from "faker";

export default Factory.extend({
  fulltext() {
    return `${this.name}`;
  },
  name() {
    return faker.commerce.productName();
  },
});
Enter fullscreen mode Exit fullscreen mode
// mirage/factories/customer.js

import { Factory } from "ember-cli-mirage";
import faker from "faker";

export default Factory.extend({
  fulltext() {
    return `${this.firstName} ${this.lastName}`;
  },
  firstName() {
    return faker.name.firstName();
  },
  lastName() {
    return faker.name.lastName();
  },
});
Enter fullscreen mode Exit fullscreen mode

Then teach mirage to filter on attribute filter when querying for collections:

// mirage/config.js

import Response from "ember-cli-mirage/response";

export default function() {
  this.namespace = "api/v1/";

  this.get("/customers", fulltextFilter);
  this.get("/items", fulltextFilter);
}

function fulltextFilter(schema, request) {
  // example: request.url = '/api/v1/items?filter%5Bfulltext%5D=Automobil'
  // So we make it so that `subject = 'items'`. This way we can use this function for any endpoint
  let subject = request.url.split(/[/?]/)[3];

  // If mirage got request for fulltext filter
  let fulltextParam = request.queryParams["filter[fulltext]"]
  if (fulltextParam) {
    // I'm making the search case in-sensitive
    let fulltextParamCI = fulltextParam.toLowerCase();
    // Filter out from all the records
    return schema[subject].all().filter(function(record) {
      // Leave only those which `fulltext` attribute contain our string
      return record.attrs.fulltext.toLowerCase().indexOf(fulltextParamCI) !== -1;
    });
  }

  // If no filter is applied, return all records for given `subject`
  return schema[subject].all();
}
Enter fullscreen mode Exit fullscreen mode

Notes

  • This is very primitive fulltext search, you might need to make it more fancy for your use-case.
  • On the backend I'm using jsonapi-resources@0.9.10 and I'm not exactly sure why it requires the query param as literal string of filter[fulltext] and not nested array. Your API might be different.

Top comments (0)