Skip to content

Commit

Permalink
chore: wip add types for wrap
Browse files Browse the repository at this point in the history
  • Loading branch information
arturosdg committed Nov 8, 2024
1 parent 5601d81 commit 9f4ec7c
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 19 deletions.
19 changes: 13 additions & 6 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,26 @@ 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 } },
}
}

const getConfig = (): Config => ({ ...config })
const typedConfig = <T extends Extensions>(newConfig: Partial<Config<T>>) => {
configure(newConfig)
return { wrap: (Component: any) => configWrap<T>(Component) }
}

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

export { configure, getConfig, Config, mount }
export { configure, typedConfig, 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
12 changes: 9 additions & 3 deletions tests/lib/extend.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { render, screen, fireEvent } from '@testing-library/react'
import { vi, it, expect } from 'vitest'
import { wrap, configure } from '../../src/index'
import { configure, typedConfig } from '../../src/index'

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

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

0 comments on commit 9f4ec7c

Please sign in to comment.