avajs / flow-typed

Flow type definitions for AVA

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Help us set up this project

novemberborn opened this issue · comments

We're looking to host the Flow type definition for AVA here:

Let us know if you're interested in helping to maintain the type definitions.

Why not just submit it to https://github.com/flow-typed/flow-typed so the Flow community can be responsible for it?

My experience with https://github.com/DefinitelyTyped/DefinitelyTyped is that the definitions tend to be rather poor, and contributing is far too daunting given the size of that repository. At least here we can give feedback and flag up areas where the definition has fallen behind.

Some feedback: it would have been good that this was resolved before type definitions were removed and the experience for Flow users was broken.

Yes, it would have been, but unfortunately we did not receive any contributions. If the difference is that v2 is not released, or you can't use it, then overall it's still better to have released v2. Once we decided we could not maintain the type definitions as part of the main project there was no point in waiting for them to be extracted, and of course we're no longer maintaining them in the main project because we don't have the knowledge to do so… and therefore we don't have the requisite knowledge to extract them either. Catch-22 I'm afraid.

I've rewritten things a bit based on prior work and removed some quirks. This can go in as a library definition module in ~flow-typed/.

This isn't adopted for v2.x.x, but at least for me in my project I didn't encounter any breaking changes. Requires detailed tests to be written before they're eligible for publishing to flow-typed. Will open a WIP PR there at the next opportune moment unless someone gets to it first.

// Adopted from: https://github.com/avajs/ava/blob/3a4afc6cf35aeffb6b019c6b75fa9b8e071bb53d/index.js.flow
// See: https://github.com/avajs/ava/pull/2098

declare module 'ava' {
  declare interface PromiseLike<R> {
    then(onFulfill: null | void, onReject: null | void): Promise<R>;
    then<U>(
      onFulfill: null | void,
      onReject: (error: any) => Promise<U> | U
    ): Promise<R | U>;
    then<U>(
      onFulfill: (value: R) => Promise<U> | U,
      onReject: null | void | ((error: any) => Promise<U> | U)
    ): Promise<U>;
  }

  declare interface ObservableLike {
    subscribe(observer: (value: any) => void): void;
  }

  declare type Constructor = Class<{ constructor(...args: Array<any>): any }>;

  declare type ThrowsExpectation = {
    code?: string | number,
    instanceOf?: Constructor,
    is?: Error,
    message?: string | RegExp,
    name?: string,
  };

  declare type SnapshotOptions = {
    id?: string,
  };

  declare type Assertions = {
    assert: {
      (actual: any, message?: string): void,
      skip(actual: any, message?: string): void,
    },

    deepEqual: {
      (actual: any, expected: any, message?: string): void,
      skip(actual: any, expected: any, message?: string): void,
    },
    fail: {
      (message?: string): void,
      skip(message?: string): void,
    },
    false: {
      (actual: any, message?: string): void,
      skip(actual: any, message?: string): void,
    },
    falsy: {
      (actual: any, message?: string): void,
      skip(actual: any, message?: string): void,
    },
    is: {
      (actual: any, expected: any, message?: string): void,
      skip(actual: any, expected: any, message?: string): void,
    },
    not: {
      (actual: any, expected: any, message?: string): void,
      skip(actual: any, expected: any, message?: string): void,
    },
    notDeepEqual: {
      (actual: any, expected: any, message?: string): void,
      skip(actual: any, expected: any, message?: string): void,
    },
    notRegex: {
      (string: string, regex: RegExp, message?: string): void,
      skip(string: string, regex: RegExp, message?: string): void,
    },
    notThrows: {
      (fn: () => any, message?: string): void,
      skip(fn: () => any, message?: string): void,
    },
    notThrowsAsync: {
      (fn: () => PromiseLike<any>, message?: string): Promise<void>,
      (promise: PromiseLike<any>, message?: string): Promise<void>,
      skip(nonThrower: any, message?: string): void,
    },
    pass: {
      (message?: string): void,
      skip(message?: string): void
    },
    regex: {
      (string: string, regex: RegExp, message?: string): void,
      skip(string: string, regex: RegExp, message?: string): void,
    },
    snapshot: {
      (expected: any, message?: string): void,
      (expected: any, options: SnapshotOptions, message?: string): void,
      skip(expected: any, message?: string): void,
      skip(expected: any, options: SnapshotOptions, message?: string): void,
    },
    throws: {
      <ThrownError: Error>(
        fn: () => any,
        expectations?: null,
        message?: string
      ): ThrownError,
      <ThrownError: Error>(
        fn: () => any,
        constructor: Constructor,
        message?: string
      ): ThrownError,
      <ThrownError: Error>(
        fn: () => any,
        regex: RegExp,
        message?: string
      ): ThrownError,
      <ThrownError: Error>(
        fn: () => any,
        errorMessage: string,
        message?: string
      ): ThrownError,
      <ThrownError: Error>(
        fn: () => any,
        expectations: ThrowsExpectation,
        message?: string
      ): ThrownError,
      skip(fn: () => any, expectations?: any, message?: string): void,
    },
    throwsAsync: {
      <ThrownError: Error>(
        fn: () => PromiseLike<any>,
        expectations?: null,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        fn: () => PromiseLike<any>,
        constructor: Constructor,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        fn: () => PromiseLike<any>,
        regex: RegExp,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        fn: () => PromiseLike<any>,
        errorMessage: string,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        fn: () => PromiseLike<any>,
        expectations: ThrowsExpectation,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        promise: PromiseLike<any>,
        expectations?: null,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        promise: PromiseLike<any>,
        constructor: Constructor,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        promise: PromiseLike<any>,
        regex: RegExp,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        promise: PromiseLike<any>,
        errorMessage: string,
        message?: string
      ): Promise<ThrownError>,
      <ThrownError: Error>(
        promise: PromiseLike<any>,
        expectations: ThrowsExpectation,
        message?: string
      ): Promise<ThrownError>,
      skip(thrower: any, expectations?: any, message?: string): void,
    },
    true: {
      (actual: any, message?: string): void,
      skip(actual: any, message?: string): void,
    },
    truthy: {
      (actual: any, message?: string): void,
      skip(actual: any, message?: string): void,
    },
  };

  declare type ExecutionContext<Context> = Assertions & {
    context: Context,
    +title: string,

    log: {
      (...values: Array<any>): void,
      skip(...values: Array<any>): void,
    },
    plan: {
      (count: number): void,
      skip(count: number): void,
    },
    timeout(ms: number): void,
  };

  declare type CbExecutionContext<Context> = ExecutionContext<Context> & {
    end(error?: any): void,
  };

  declare type ImplementationResult = PromiseLike<void> | ObservableLike | void;
  declare type Implementation<Context> = (
    t: ExecutionContext<Context>
  ) => ImplementationResult;
  declare type CbImplementation<Context> = (
    t: CbExecutionContext<Context>
  ) => ImplementationResult;

  declare type Macro<Context> = {
    (t: ExecutionContext<Context>, ...args: Array<any>): ImplementationResult,
    title?: (providedTitle: string | void, ...args: Array<any>) => string,
  };

  declare type CbMacro<Context> = {
    (t: CbExecutionContext<Context>, ...args: Array<any>): ImplementationResult,
    title?: (providedTitle: string | void, ...args: Array<any>) => string,
  };

  declare export type TestInterface<Context: Object> = {
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,

    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    after: After<Context>,
    afterEach: After<Context>,
    before: Before<Context>,
    beforeEach: Before<Context>,
    cb: Cb<Context>,
    failing: FailingInterface<Context>,
    serial: SerialInterface<Context>,
    only: OnlyInterface<Context>,
    skip: Skip<Context>,
    todo: TodoDeclaration,
  };

  declare type After<Context> = {
    (implementation: Implementation<Context> | Macro<Context>): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    always: {
      (implementation: Implementation<Context> | Macro<Context>): void,
      (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
      (
        title: string,
        implementation: Implementation<Context> | Macro<Context>
      ): void,
      (
        title: string,
        macro: Macro<Context> | Macro<Context>[],
        ...args: Array<any>
      ): void,
      cb: HookCb<Context>,
      skip: HookSkip<Context>,
    },
    cb: HookCb<Context>,
    skip: HookSkip<Context>,
  };

  declare type Before<Context> = {
    (implementation: Implementation<Context> | Macro<Context>): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    cb: HookCb<Context>,
    skip: HookSkip<Context>,
  };

  declare type Cb<Context> = {
    (
      title: string,
      implementation: CbImplementation<Context> | CbMacro<Context>
    ): void,
    (
      title: string,
      macro: CbMacro<Context> | CbMacro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
    failing: {
      (
        title: string,
        implementation: CbImplementation<Context> | CbMacro<Context>
      ): void,
      (
        title: string,
        macro: CbMacro<Context> | CbMacro<Context>[],
        ...args: Array<any>
      ): void,
      (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
      only: CbOnlyInterface<Context>,
      skip: CbSkip<Context>,
    },
    only: CbOnlyInterface<Context>,
    skip: CbSkip<Context>,
  };

  declare type CbOnlyInterface<Context> = {
    (
      title: string,
      implementation: CbImplementation<Context> | CbMacro<Context>
    ): void,
    (
      title: string,
      macro: CbMacro<Context> | CbMacro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
  };

  declare type CbSkip<Context> = {
    (
      title: string,
      implementation: CbImplementation<Context> | CbMacro<Context>
    ): void,
    (
      title: string,
      macro: CbMacro<Context> | CbMacro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
  };

  declare type FailingInterface<Context> = {
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    only: OnlyInterface<Context>,
    skip: Skip<Context>,
  };

  declare type HookCb<Context> = {
    (implementation: CbImplementation<Context> | CbMacro<Context>): void,
    (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
    (
      title: string,
      implementation: CbImplementation<Context> | CbMacro<Context>
    ): void,
    (
      title: string,
      macro: CbMacro<Context> | CbMacro<Context>[],
      ...args: Array<any>
    ): void,
    skip: HookCbSkip<Context>,
  };

  declare type HookCbSkip<Context> = {
    (implementation: CbImplementation<Context> | CbMacro<Context>): void,
    (macro: CbMacro<Context> | CbMacro<Context>[], ...args: Array<any>): void,
    (
      title: string,
      implementation: CbImplementation<Context> | CbMacro<Context>
    ): void,
    (
      title: string,
      macro: CbMacro<Context> | CbMacro<Context>[],
      ...args: Array<any>
    ): void,
  };

  declare type HookSkip<Context> = {
    (implementation: Implementation<Context> | Macro<Context>): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
  };

  declare type OnlyInterface<Context> = {
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
  };

  declare type SerialInterface<Context> = {
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
    after: After<Context>,
    afterEach: After<Context>,
    before: Before<Context>,
    beforeEach: Before<Context>,
    cb: Cb<Context>,
    failing: FailingInterface<Context>,
    only: OnlyInterface<Context>,
    skip: Skip<Context>,
    todo: TodoDeclaration,
    meta: {
      file: string,
    },
  };

  declare type Skip<Context> = {
    (
      title: string,
      implementation: Implementation<Context> | Macro<Context>
    ): void,
    (
      title: string,
      macro: Macro<Context> | Macro<Context>[],
      ...args: Array<any>
    ): void,
    (macro: Macro<Context> | Macro<Context>[], ...args: Array<any>): void,
  };

  declare type TodoDeclaration = (title: string) => void;

  declare export default TestInterface<any>;
}

I've rewritten things a bit based on prior work and removed some quirks.

Great!

This isn't adopted for v2.x.x, but at least for me in my project I didn't encounter any breaking changes.

Just had a quick look and I don't think there's any breaking changes in the test & assertion interfaces, so that's all good.

This can go in as a library definition module in ~flow-typed/.

By this, do you mean contributing it to the Flow typing project?

☝️ I meant that someone can just paste and drop this in their projects if they need to restore type support right now.

I would like to contribute it to flow-typed when I have time to cover everything with type tests, unless there's an actual proposal how it can be accomplished from this repository?

I would like to contribute it to flow-typed when I have time to cover everything with type tests, unless there's an actual proposal how it can be accomplished from this repository?

I don't really know the pros and cons of "self-hosting" a type definition. I know with TypeScript's @types I'm always put off from contributing anything because of the sheer size of that repository, so I'm inclined to publishing these definitions ourselves. Not sure how easily that's set up in a project though.