Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: wip add types for wrap #68

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { render } from 'react-dom'

import type { Component, Config, RenderResult } from './models'
import type { Component, Config, Extensions, RenderResult } from './models'
import { configWrap } from './wrap'

const mount = (Component: Component): RenderResult => {
const rootNode = document.body.appendChild(document.createElement('div'))
Expand All @@ -10,20 +11,22 @@ const mount = (Component: Component): RenderResult => {
return rootNode
}

let config: Config = {
let config = {
defaultHost: '',
extend: {},
mount,
changeRoute: (path: string) => window.history.replaceState(null, '', path),
}
} satisfies Config<Extensions>

function configure(newConfig: Partial<Config>) {
function configure<T extends Extensions>(newConfig: Partial<Config<T>>) {
config = {
...config,
...newConfig,
...{ extend: { ...newConfig.extend } },
}
return { wrap: (Component: any) => configWrap<T>(Component) }
}

const getConfig = (): Config => ({ ...config })
const getConfig = (): Config<Extensions> => ({ ...config })

export { configure, getConfig, Config, mount }
22 changes: 15 additions & 7 deletions src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ export interface WrapResponse extends Partial<Response> {
export type NetworkResponses = WrapResponse | WrapResponse[]

export interface Wrap {
withNetwork: (responses?: NetworkResponses) => Wrap
atPath: (path: string, historyState?: object) => Wrap
withProps: (props: object) => Wrap
debugRequests: () => Wrap
withNetwork: (responses?: NetworkResponses) => Omit<this, 'withNetwork'>
atPath: (path: string, historyState?: object) => Omit<this, 'atPath'>
withProps: (props: object) => Omit<this, 'withProps'>
debugRequests: () => Omit<this, 'debugRequests'>
mount: () => RenderResult
}

Expand All @@ -65,7 +65,15 @@ export interface WrapExtensionAPI {
addResponses: (responses: Array<WrapResponse>) => unknown
}

type Extension = <T>(extensionAPI: WrapExtensionAPI, args: T) => void
type DropFirst<T extends unknown[]> = T extends [any, ...infer U] ? U : never

type Extension = (extensionAPI: WrapExtensionAPI, ...args: any[]) => void
type WrappedExtension<T extends Extension> = DropFirst<Parameters<T>>

export type WrappedExtensions<T extends Extensions> = Record<
keyof T,
(...args: WrappedExtension<T[keyof T]>) => Wrap & WrappedExtensions<T>
>

type Extensions = {
[key: string]: Extension
Expand All @@ -76,10 +84,10 @@ type Component = React.ReactElement<any, any>
export type RenderResult = TLRenderResult | HTMLDivElement
export type Mount = (component: Component) => RenderResult

export interface Config {
export interface Config<T> {
defaultHost: string
mount: Mount
extend: Extensions
extend: T
changeRoute: (path: string) => void
history?: BrowserHistory
portal?: string
Expand Down
20 changes: 17 additions & 3 deletions src/wrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import * as React from 'react'
import { mockNetwork } from './mockNetwork'
import { getConfig } from './config'
import { updateOptions, getOptions } from './options'
import type {
import {
Response,
Wrap,
WrapExtensionAPI,
Extension,
Extensions,
WrappedExtensions,
} from './models'
import { vi } from 'vitest'
import type { MockedFunction } from 'vitest'
Expand All @@ -22,7 +23,7 @@ afterEach(() => {
mockedFetch.mockRestore()
})

const wrap = (component: unknown): Wrap => {
const wrap = (component: unknown) => {
updateOptions({
Component: component,
responses: [],
Expand All @@ -35,7 +36,20 @@ const wrap = (component: unknown): Wrap => {
return wrapWith()
}

const wrapWith = (): Wrap => {
export const configWrap = <T extends Extensions>(component: unknown) => {
updateOptions({
Component: component,
responses: [],
props: {},
path: '',
hasPath: false,
debug: process.env.npm_config_debugRequests === 'true',
})

return wrapWith() as Wrap & WrappedExtensions<T>
}

const wrapWith = () => {
const extensions = extendWith()

return {
Expand Down
14 changes: 10 additions & 4 deletions tests/lib/extend.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { render, screen, fireEvent } from '@testing-library/react'
import { vi, it, expect } from 'vitest'
import { wrap, configure } from '../../src/index'
import { configure } from '../../src/index'

import { MyComponentWithLogin } from '../components.mock'

it('should extend wrapito', async () => {
const otherCustomExtension = vi.fn()
const customArgs = { foo: 'bar' }
configure({
const { wrap } = configure({
mount: render,
extend: {
withLogin: ({ addResponses }, username: string) =>
withLogin: ({ addResponses }, username: string, test: boolean) =>
addResponses([
{
path: '/path/to/login/',
Expand All @@ -19,15 +19,21 @@
responseBody: username,
},
]),
withOtherCustomExtension: () => otherCustomExtension(customArgs),
withOtherCustomExtension: ({}) => otherCustomExtension(customArgs),
},
})
wrap(MyComponentWithLogin)
.withNetwork()
.debugRequests()
.withOtherCustomExtension()
.withLogin('Fran Perea')
.mount()
wrap(MyComponentWithLogin)
.withLogin('Fran Perea')
.withOtherCustomExtension()
.mount()

expect(await screen.findByText('Logged in as Fran Perea')).toBeInTheDocument()

Check failure on line 36 in tests/lib/extend.test.ts

View workflow job for this annotation

GitHub Actions / check-tests

tests/lib/extend.test.ts > should extend wrapito

TestingLibraryElementError: Found multiple elements with the text: Logged in as Fran Perea Here are the matching elements: Ignored nodes: comments, script, style <span> Logged in as Fran Perea </span> Ignored nodes: comments, script, style <span> Logged in as Fran Perea </span> (If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)). Ignored nodes: comments, script, style <body> <div> <div> <span> Logged in as Fran Perea </span> <button> Logout </button> </div> </div> <div> <div> <span> Logged in as Fran Perea </span> <button> Logout </button> </div> </div> </body> Ignored nodes: comments, script, style <body> <div> <div> <span> Logged in as Fran Perea </span> <button> Logout </button> </div> </div> <div> <div> <span> Logged in as Fran Perea </span> <button> Logout </button> </div> </div> </body> ❯ waitForWrapper node_modules/@testing-library/dom/dist/wait-for.js:166:27 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:86:33 ❯ tests/lib/extend.test.ts:36:23
expect(otherCustomExtension).toHaveBeenCalledWith(customArgs)
})

Expand All @@ -46,7 +52,7 @@
]),
},
})
wrap(MyComponentWithLogin)

Check failure on line 55 in tests/lib/extend.test.ts

View workflow job for this annotation

GitHub Actions / check-tests

tests/lib/extend.test.ts > should be compatible with withNetwork

ReferenceError: wrap is not defined ❯ tests/lib/extend.test.ts:55:3
.withLogin('Fran Perea')
.withNetwork([
{
Expand Down Expand Up @@ -79,7 +85,7 @@
]),
},
})
wrap(MyComponentWithLogin)

Check failure on line 88 in tests/lib/extend.test.ts

View workflow job for this annotation

GitHub Actions / check-tests

tests/lib/extend.test.ts > should be composable

ReferenceError: wrap is not defined ❯ tests/lib/extend.test.ts:88:3
.withNetwork([
{
path: '/path/to/logout/',
Expand Down
Loading