IBM / slack-wrench

Tools to build and test Slack apps
Apache License 2.0
48 stars 26 forks source link

Plans to update jest-mock-web-client for current versions of Slack and Jest? #118

Closed Mr0grog closed 2 years ago

Mr0grog commented 2 years ago

Hi there, I was wondering whether there are any plans to update jest-mock-web-client for current versions of Jest and Slack.

I was recently tasked with updating an internal Slack tool that uses jest-mock-web-client (it’s really nice, thank you!), but am caught trying to figure out how to resolve some of these compatibility issues with modern versions of Jest and Slack. Since there haven’t been any updates in over a year, I was hoping to find out whether you have future plans for this, or if not and I should be evaluating tradeoffs between using this tool and updated features or vulnerability fixes in Jest and Slack.

Thanks!

barlock commented 2 years ago

Thanks for your continued interest in this project. 😅 It's absolutely fallen off my radar in the last few months, but that wasn't my intention. I took a quick pass to try and upgrade the project but it's proving to be a bit more of a web of upgrades than I can contain in a morning.

I should be able to get to it over the holidays, but if you're willing PRs are absolutely welcome.

Mr0grog commented 2 years ago

This doesn’t address the Jest issue, but would something like the following be a good way to address broader compatibility with multiple major Slack versions?

/**
 * Creates a new type where functions in the original types are Jest mocks and
 * other values are kept as is, and which works recusively (so if a property
 * is an object with functions, it becomes and object with mocks).
 */
type ObjectWithMocks<Type> = {
  [Property in keyof Type]: Type[Property] extends Function
    ? jest.Mock<any>
    : (Type[Property] extends Object
      ? ObjectWithMocks<Type[Property]>
      : Type[Property]);
}

const primitiveTypes = new Set(["string", "boolean", "number", "undefined"]);

function deepCopyWithMocks<T>(original: T): ObjectWithMocks<T> {
  const copy: any = {};
  for (const key in original) {
    const value = original[key];
    if (typeof value === "function") {
      copy[key] = jest.fn();
    } else if (primitiveTypes.has(typeof value) || value == null) {
      copy[key] = value;
    } else {
      copy[key] = deepCopyWithMocks(value);
    }
  }
  return copy;
}

type MockedWebClient =  ObjectWithMocks<WebClient>;

const exampleClientInstance = new WebClient();
function MockWebClient(): MockedWebClient {
  return deepCopyWithMocks<WebClient>(exampleClientInstance);
}

(This would also eliminate the need to clear the mocks before each test, I think.)

Mr0grog commented 2 years ago

I gave this a go in #123.

barlock commented 2 years ago

Fixed in #123