These are chat archives for ramda/ramda

21st
Mar 2018
Vesa Karvonen
@polytypic
Mar 21 2018 07:42

@Kielan Like @kurtmilam said you can't make a recursive function in JS completely point-free. However, nothing prevents one from making general purpose recursive transformation functions. The Partial Lenses documentation mentions a simple Rambda based bottom-up transform function as an example:

const descend = (w2w, w) => R.is(Object, w) ? R.map(w2w, w) : w
const substUp = (h2h, w) => descend(h2h, descend(w => substUp(h2h, w), w))
const transform = (w2w, w) => w2w(substUp(w2w, w))

Something like the above transform function might be a useful addition to Ramda.

Using that you could write a removeNulls function point-free:

const removeNulls = transform(
  R.when(R.is(Object),
    R.pipe(
      R.omit(['id']),
      R.reject(R.isNil)
    )
  )
)

Here is the whole thing.

I should also mention that Partial Lenses does support whole data structure spanning operations so that particular example in the Partial Lenses documentation is somewhat out of date. Here is a playground that does a similar filtering operation using Partial Lenses.
Janne Lönn
@janneh
Mar 21 2018 07:51

I'm having a bit of trouble with Ramda and Typescript types.... Setting is something like:

interface Item {
  name: string
  uuid: string
}

const list = [{ 
  name: "foo",
  uuid: "123"
}, {
  name: "bar",
  uuid: "321"
}]

const name = R.pipe(
  R.find<Item>(propEq("uuid", "might-not-exist")),
  R.prop("name")
)(list)

For a not found item that will return undefined in the end , but Typescript does not think prop should be allowed to receive undefined

Type 'undefined' is not assignable to type 'Record<"name", string>'.

Anyone with some insights in to how this should be done?

With that the find part is correctly typed to returning Item | undefined but then that will not play well when passed to prop
Vesa Karvonen
@polytypic
Mar 21 2018 09:03
@6ewis I don't think that Ramda directly provides that functionality. Here is a quick example that implements a recursive query function that one could use with prop. BTW, Partial Lenses provides a query combinator that handles cases like this and more.
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 10:08
hi everyone. I'm trying to implement tests for my Futures and I don't know if I'm doing it right or not. Can anyone recommend how would I go about it please?
// my api call
const getUsers = Future((rej, res) =>
  xhr
    .get('/api/users')
    .then(res)
    .catch(rej));

// test, which DOESN'T work
const rejectFn = jest.fn();
const resolveFn = jest.fn();

describe('getUsers', () => {
  it('should fetch user if api call resolves', () => {
    const data = { test: 'Hello world' };
    xhr.get = jest.fn(() => Promise.resolve(data));
    getUsers.fork(rejectFn, resolveFn);
    expect(resolveFn).toBeCalledWith(data);
  });
});

// test which works
describe('getUsers', () => {
  it('should fetch user if api call resolves', () => {
    const data = { test: 'Hello world' };
    xhr.get = jest.fn(() => Promise.resolve(data));
    return new Promise((res, rej) => getUsers.fork(rej, res))
      .then(resolveFn)
      .catch(rejectFn)
      .then(data => expect(resolveFn).toBeCalledWith(data));
  });
});
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 12:28
but that doesn't change much, does it?
it just changes this bit
xhr.get = jest.fn(() => Promise.resolve(data));
Stefano Vozza
@svozza
Mar 21 2018 12:59
you can make assertions on the fake data received from the api to make sure it's been handled correctly. you can also test the reject path of your function
not sure what else you'd want to test
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 13:21
but what I was saying is, is this a correct way of testing it? (returning a Promise from the test and doing .then.catch.then combo)
Stefano Vozza
@svozza
Mar 21 2018 13:27
i'd use the done callback instead
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 13:27
working reject path
// test which works
describe('getUsers', () => {
  it('should fetch user if api call resolves', () => {
    const data = { test: 'Hello world' };
    xhr.get = jest.fn(() => Promise.reject(data));
    return new Promise((res, rej) => getUsers.fork(rej, res))
      .then(resolveFn)
      .catch(rejectFn)
      .then(data => expect(rejectFn).toBeCalledWith(data));
  });
});
Stefano Vozza
@svozza
Mar 21 2018 13:27
it('should fetch user if api call resolves', done => {
    getUsers().fork(done, data => {
      //make assetions on data
      done();
    })
  });
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 13:27
that's what I was trying to achieve :D
looks much much better!
thank you
Stefano Vozza
@svozza
Mar 21 2018 13:28
no probs :)
if you use nock in your test set up then you can control what ends up being passed to fork
or you can monkeypatch xhr like you were doing, it works out the same in the end
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 13:32
yeah that part is fine for these tests, I was just getting a bit frustrated that I had to use this redundant Promise as a wrapper
and I was sort of exploiting Promise api's odd functionality that it runs thens even after catch :D
Stefano Vozza
@svozza
Mar 21 2018 13:34
yeah, that was a layer of indirection that looked confusing
geganizharadzeatamido
@geganizharadzeatamido
Mar 21 2018 13:37
finally, I can test monads! :D it's a bit frustrating that the articles about monads out there don't seem to include the ways to test them properly
it's quite obvious at first glance, but then these types of minor issues arise and ..
Karthik Iyengar
@karthikiyengar
Mar 21 2018 15:13
Quick one - what function do I use to set a value at a given path (even if it doesn’t exist)
Something like assocPath (should work on deep objects)
Cancel that, assocPath is exactly what I needed