<commit_before>import { build } from '../../builder';
import { uniq, compose, map, flatten, curry, prop, head, last, toObject, values } from '../../fp';
import { denormalizer, extractAccessors } from '.';

const toIdMap = toObject(prop('id'));

const peter = { id: 'peter' };
const gernot = { id: 'gernot' };
const robin = { id: 'robin' };

const users = toIdMap([peter, gernot, robin]);

const c1 = { id: 'a' };
const c2 = { id: 'b' };

const comments = toIdMap([c1, c2]);

const m1 = {
  id: 'x',
  author: peter.id,
  recipient: gernot.id,
  visibleTo: [robin.id],
  nestedData: {
    comments: [c1.id, c2.id]
  }
};
const m2 = {
  id: 'y',
  author: gernot.id,
  recipient: peter.id,
  visibleTo: [],
  nestedData: {
    comments: []
  }
};

const messages = toIdMap([m1, m2]);

const getById = curry((m, id) => Promise.resolve(m[id]));
const getAll = (m) => () => Promise.resolve(values(m));

const getUser = getById(users);
getUser.operation = 'READ';
getUser.byId = true;
const getUsers = getAll(users);
getUser.operation = 'READ';

const getMessage = getById(messages);
getMessage.operation = 'READ';
getMessage.byId = true;
const getMessages = getAll(messages);
getMessages.operation = 'READ';

const getComment = getById(comments);
getComment.operation = 'READ';
getComment.byId = true;
const getComments = getAll(comments);
getComments.operation = 'READ';


const config = () => ({
  user: {
    api: { getUser, getUsers },
    plugins: {
      denormalizer: {
        getOne: 'getUser',
        getAll: 'getUsers',
        threshold: 5
      }
    }
  },
  message: {
    api: { getMessage, getMessages },
    plugins: {
      denormalizer: {
        schema: {
          author: 'user',
          recipient: 'user',
          visibleTo: ['user'],
          nestedData: {
            comments: ['comment']
          }
        }
      }
    }
  },
  comment: {
    api: { getComment, getComments },
    plugins: {
      denormalizer: {
        getOne: 'getComment',
        getAll: 'getComments'
      }
    }
  }
});

const expectResolved = curry((k, val, obj) => {
  expect(obj[k]).to.deep.equal(val);
  return obj;
});

describe('denormalizer', () => {
  describe('with a fn, that returns one object', () => {
    it('resolves references to simple id fields', (done) => {
      const api = build(config(), [denormalizer()]);
      api.message.getMessage(m1.id)
        .then(expectResolved('author', users[m1.author]))
        .then(expectResolved('recipient', users[m1.recipient]))
        .then(() => done());
    });

    it('resolves references to lists of ids', (done) => {
      const api = build(config(), [denormalizer()]);
      api.message.getMessage(m1.id)
        .then(expectResolved('visibleTo', [users[m1.visibleTo[0]]]))
        .then(() => done());
    });<commit_msg>Add spec to verify nested data resolution<commit_after>import { build } from '../../builder';
import { uniq, compose, map, flatten, curry, prop, head, last, toObject, values } from '../../fp';
import { denormalizer, extractAccessors } from '.';

const toIdMap = toObject(prop('id'));

const peter = { id: 'peter' };
const gernot = { id: 'gernot' };
const robin = { id: 'robin' };

const users = toIdMap([peter, gernot, robin]);

const c1 = { id: 'a' };
const c2 = { id: 'b' };

const comments = toIdMap([c1, c2]);

const m1 = {
  id: 'x',
  author: peter.id,
  recipient: gernot.id,
  visibleTo: [robin.id],
  nestedData: {
    comments: [c1.id, c2.id]
  }
};
const m2 = {
  id: 'y',
  author: gernot.id,
  recipient: peter.id,
  visibleTo: [],
  nestedData: {
    comments: []
  }
};

const messages = toIdMap([m1, m2]);

const getById = curry((m, id) => Promise.resolve(m[id]));
const getAll = (m) => () => Promise.resolve(values(m));

const getUser = getById(users);
getUser.operation = 'READ';
getUser.byId = true;
const getUsers = getAll(users);
getUser.operation = 'READ';

const getMessage = getById(messages);
getMessage.operation = 'READ';
getMessage.byId = true;
const getMessages = getAll(messages);
getMessages.operation = 'READ';

const getComment = getById(comments);
getComment.operation = 'READ';
getComment.byId = true;
const getComments = getAll(comments);
getComments.operation = 'READ';


const config = () => ({
  user: {
    api: { getUser, getUsers },
    plugins: {
      denormalizer: {
        getOne: 'getUser',
        getAll: 'getUsers',
        threshold: 5
      }
    }
  },
  message: {
    api: { getMessage, getMessages },
    plugins: {
      denormalizer: {
        schema: {
          author: 'user',
          recipient: 'user',
          visibleTo: ['user'],
          nestedData: {
            comments: ['comment']
          }
        }
      }
    }
  },
  comment: {
    api: { getComment, getComments },
    plugins: {
      denormalizer: {
        getOne: 'getComment',
        getAll: 'getComments'
      }
    }
  }
});

const expectResolved = curry((k, val, obj) => {
  expect(obj[k]).to.deep.equal(val);
  return obj;
});

describe('denormalizer', () => {
  describe('with a fn, that returns one object', () => {
    it('resolves references to simple id fields', (done) => {
      const api = build(config(), [denormalizer()]);
      api.message.getMessage(m1.id)
        .then(expectResolved('author', users[m1.author]))
        .then(expectResolved('recipient', users[m1.recipient]))
        .then(() => done());
    });

    it('resolves references to lists of ids', (done) => {
      const api = build(config(), [denormalizer()]);
      api.message.getMessage(m1.id)
        .then(expectResolved('visibleTo', [users[m1.visibleTo[0]]]))
        .then(() => done());
    });

    it('resolves references for nested data', (done) => {
      const api = build(config(), [denormalizer()]);
      api.message.getMessage(m1.id)
      .then((m) => expectResolved('comments', [c1, c2], m.nestedData))
        .then(() => done());
    })
{'fraction_non_alphanumeric': 0.1792821908487838, 'fraction_numerical': 0.006293587344786528, 'mean_word_length': 2.93048128342246, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6068558', 'n_tokens_mistral': 2005, 'n_tokens_neox': 1988, 'n_words': 458}