🏡 index : quine-global/webdriverio.git

import path from 'node:path'

import { getManualMocks } from './utils.js'
import { DEFAULT_MOCK_DIRECTORY, DEFAULT_AUTOMOCK } from '../constants.js'
import type { MockRequestEvent } from './types.js'

const FIXTURE_PREFIX = '/@fixture/'

export class MockHandler {
    #automock: boolean
    #automockDir: string
    #manualMocksList: Promise<[string, string][]>
    #mocks = new Map<string, MockRequestEvent>()
    #unmocked: string[] = []

    manualMocks: string[] = []

    constructor (options: WebdriverIO.BrowserRunnerOptions, config: WebdriverIO.Config) {
        this.#automock = typeof options.automock === 'boolean' ? options.automock : DEFAULT_AUTOMOCK
        this.#automockDir = path.resolve(config.rootDir!, options.automockDir || DEFAULT_MOCK_DIRECTORY)
        this.#manualMocksList = getManualMocks(this.#automockDir)
    }

    get mocks () {
        return this.#mocks
    }

    unmock (moduleName: string) {
        this.#unmocked.push(moduleName)
    }

    async resolveId (id: string) {
        const manualMocksList = await this.#manualMocksList
        const mockPath = manualMocksList.find((m) => (
            // e.g. someModule
            id === m[1].replace(path.sep, '/') ||
            // e.g. @some/module
            id.slice(1) === m[1].replace(path.sep, '/')
        ))

        /**
         * return manual mock if `automock` is enabled or a manual mock was set via `mock('module')`
         */
        if ((this.manualMocks.includes(id) || this.#automock) && mockPath && !this.#unmocked.includes(id)) {
            return mockPath[0]
        }

        /**
         * return fixture
         */
        if (id.startsWith(FIXTURE_PREFIX)) {
            return path.resolve(this.#automockDir, id.slice(FIXTURE_PREFIX.length))
        }
    }

    /**
     * reset manual mocks between tests
     */
    resetMocks () {
        this.manualMocks = []
        this.#unmocked = []
    }
}