TS_TEST_EXTENSION=
TS_TEST_EXTRA_SRCS_MASK=

TS_TEST_CONFIG_PATH=
TS_TEST_NM=

_TS_TEST_DEPENDS_ON_BUILD=

# We have to rename node_modules.tar to workspace_node_modules.tar,
# so TS_TEST_JEST module has it's own unique output.
# TS_TEST_JEST_FOR module has to output all files required for test run.
TS_TEST_JEST_CMD=$TOUCH_UNIT \
    && $NOTS_TOOL $NOTS_TOOL_BASE_ARGS create-node-modules --moddir $TS_TEST_FOR_PATH \
    $_NODE_MODULES_INOUTS ${hide:PEERS} \
    && ${cwd:BINDIR} $MOVE_FILE $TS_TEST_NM ${output:"workspace_node_modules.tar"} \
    ${kv;hide:"p TS_JST"} ${kv;hide:"pc magenta"}

### @usage: TS_TEST_JEST_FOR(Path)
###
### Defines testing module with jest test runner.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/TS_TEST_JEST_FOR
###
### @example
###
###     TS_TEST_JEST_FOR(path/to/module)
###         TS_TEST_SRCS(../src)
###         TS_TEST_CONFIG(../jest.config.js)
###     END()
###
module TS_TEST_JEST_FOR: _TS_TEST_BASE {
    .CMD=TS_TEST_JEST_CMD

    # for multimodule peers we should choose NODE_MODULES
    SET(PEERDIR_TAGS TS)

    # compatibility with old TS_TEST_SRCS
    SET(TS_TEST_EXTENSION test.(ts|tsx|js|jsx))
    SET(TS_TEST_EXTRA_SRCS_MASK /**/__mocks__/*)

    # nots.py will decide if we need to depend on the testing target module output
    _DEPENDS_ON_MOD()
    _PEERDIR_TS_RESOURCE(nodejs jest)
    _TS_TEST_FOR_CONFIGURE(jest jest.config.js workspace_node_modules.tar)

    _TS_ADD_NODE_MODULES_FOR_BUILDER()
}

TS_TEST_HERMIONE_CMD=$TOUCH_UNIT \
    && ${cwd:BINDIR} $MOVE_FILE ${input:TS_TEST_NM} ${output:"workspace_node_modules.tar"} \
    ${kv;hide:"p TSHRM"} ${kv;hide:"pc magenta"}

### @usage: TS_TEST_HERMIONE_FOR(Path)
###
### Defines testing module with hermione test runner.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/TS_TEST_HERMIONE_FOR
###
### @example
###
###     TS_TEST_HERMIONE_FOR(path/to/module)
###         TS_TEST_SRCS(../src)
###         TS_TEST_CONFIG(../hermione.conf.js)
###     END()
###
module TS_TEST_HERMIONE_FOR: _TS_TEST_BASE {
    .CMD=TS_TEST_HERMIONE_CMD

    # for multimodule peers we should choose TS
    SET(PEERDIR_TAGS TS)

    # compatibility with old TS_TEST_SRCS
    SET(TS_TEST_EXTENSION hermione.(ts|js))

    TS_TEST_DEPENDS_ON_BUILD()
    _DEPENDS_ON_MOD()
    _PEERDIR_TS_RESOURCE(nodejs typescript hermione)
    _TS_TEST_FOR_CONFIGURE(hermione .hermione.conf.js workspace_node_modules.tar)
}

TS_TEST_PLAYWRIGHT_CMD=$TOUCH_UNIT \
    && $NOTS_TOOL $NOTS_TOOL_BASE_ARGS create-node-modules --moddir $TS_TEST_FOR_PATH \
    $_NODE_MODULES_INOUTS ${hide:PEERS} \
    && ${cwd:BINDIR} $MOVE_FILE $TS_TEST_NM ${output:"workspace_node_modules.tar"} \
    ${kv;hide:"p TSPW"} ${kv;hide:"pc magenta"}

### @usage: TS_TEST_PLAYWRIGHT_FOR(Path)
###
### Defines testing module with playwright test runner.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/TS_TEST_PLAYWRIGHT_FOR
###
### @example
###
###     TS_TEST_PLAYWRIGHT_FOR(path/to/module)
###         TS_TEST_SRCS(../src)
###         TS_TEST_CONFIG(../playwright.config.js)
###     END()
###
module TS_TEST_PLAYWRIGHT_FOR: _TS_TEST_BASE {
    .CMD=TS_TEST_PLAYWRIGHT_CMD

    # for multimodule peers we should choose TS
    SET(PEERDIR_TAGS TS)

    # compatibility with old TS_TEST_SRCS
    SET(TS_TEST_EXTENSION (playwright|spec).(ts|js))

    _DEPENDS_ON_MOD()
    _TS_ADD_NODE_MODULES_FOR_BUILDER()

    _PEERDIR_TS_RESOURCE(nodejs playwright)
    _TS_TEST_FOR_CONFIGURE(playwright playwright.config.ts workspace_node_modules.tar)
}

TS_TEST_PLAYWRIGHT_LARGE_CMD=$TOUCH_UNIT \
    && ${cwd:BINDIR} $MOVE_FILE ${input:TS_TEST_NM} ${output:"workspace_node_modules.tar"} \
    ${kv;hide:"p TSPW"} ${kv;hide:"pc magenta"}

### @usage: TS_TEST_PLAYWRIGHT_LARGE_FOR(Path)
###
### Defines testing module with playwright test runner.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/TS_TEST_PLAYWRIGHT_FOR
###
### @example
###
###     TS_TEST_PLAYWRIGHT_LARGE_FOR(path/to/module)
###         TS_TEST_SRCS(../src)
###         TS_TEST_CONFIG(../playwright.config.js)
###     END()
###
module TS_TEST_PLAYWRIGHT_LARGE_FOR: _TS_TEST_BASE {
    .CMD=TS_TEST_PLAYWRIGHT_LARGE_CMD

    # for multimodule peers we should choose TS
    SET(PEERDIR_TAGS TS)

    # compatibility with old TS_TEST_SRCS
    SET(TS_TEST_EXTENSION (playwright|spec).(ts|js))

    TS_TEST_DEPENDS_ON_BUILD()
    _DEPENDS_ON_MOD()
    _PEERDIR_TS_RESOURCE(nodejs playwright)
    _TS_TEST_FOR_CONFIGURE(playwright_large playwright.config.ts workspace_node_modules.tar)
}

### # internal
module _TS_TEST_BASE: _BARE_UNIT {
    # ignore SRCS macro
    .ALIASES=SRCS=_NOOP_MACRO
    # use this parser to get module args in $MODULE_ARGS_RAW
    .ARGS_PARSER=Raw
    .NODE_TYPE=Bundle
    .PEERDIR_POLICY=as_build_from

    # .fake tells builder to not materialize it in results
    SET(MODULE_SUFFIX .ts_test.fake)
    # include processor works only for TS tag
    SET(MODULE_TAG TS)
    SET(MODULE_LANG TS)
    # we read erm-packages.json during configuration, so we have to include it to configuration cache key
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS ${ARCADIA_ROOT}/$ERM_PACKAGES_PATH)

    # parse module args
    _TS_TEST_FOR_ARGS($MODULE_ARGS_RAW)

    # Set PM values from TS_TEST_FOR_DIR
    _SET_PACKAGE_MANAGER()

    # we don't want to have TS outputs for tests
    DISABLE(TS_CONFIG_DEDUCE_OUT)
}

macro _TS_TEST_FOR_ARGS(FOR_MOD, RELATIVE?"${CURDIR}":"${ARCADIA_ROOT}") {
    # we read testing modules' package.json during configuration,
    # so we have to include it to configuration cache key
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS $RELATIVE/$FOR_MOD/package.json)
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS $RELATIVE/$FOR_MOD/pnpm-lock.yaml)
    _VALIDATE_TS_TEST_FOR_ARGS($FOR_MOD $RELATIVE)
    _SET_TS_TEST_FOR_VARS($FOR_MOD)
}

macro _SETUP_EXTRACT_NODE_MODULES_RECIPE(FOR_PATH) {
    USE_RECIPE(devtools/frontend_build_platform/nots/recipes/extract_node_modules/recipe $FOR_PATH workspace_node_modules.tar)
}

macro _SETUP_EXTRACT_OUTPUT_TARS_RECIPE(FOR_PATH) {
    USE_RECIPE(devtools/frontend_build_platform/nots/recipes/extract_output_tars/recipe $FOR_PATH)
}

macro _SETUP_INSTALL_NODE_MODULES_RECIPE() {
    USE_RECIPE(devtools/frontend_build_platform/nots/recipes/install_node_modules/recipe $NOTS_TOOL_BASE_ARGS --bundle no)
}


### @usage: TS_TEST_CONFIG(Path)
###
### Macro sets the path to configuration file of the test runner.
###
### - Path - path to the config file.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/macros#ts-test-config
macro TS_TEST_CONFIG(Path) {
    SET(TS_TEST_CONFIG_PATH $Path)
}


_TS_TEST_SRCS_VALUE=
_TS_TEST_EXTRA_SRCS_VALUE=
### @usage: TS_TEST_SRCS(DIRS...)
###
### Macro to define directories where the test source files should be located.
###
### - DIRS... - directories.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/macros#ts-test-srcs
macro TS_TEST_SRCS(DIRS...) {
    _GLOB(_TS_TEST_SRCS_VALUE ${suf=/**/*.$TS_TEST_EXTENSION:DIRS})
    SRCS($_TS_TEST_SRCS_VALUE)

    _GLOB(_TS_TEST_EXTRA_SRCS_VALUE ${suf=$TS_TEST_EXTRA_SRCS_MASK:DIRS})
    SRCS($_TS_TEST_EXTRA_SRCS_VALUE)
}


_TS_TEST_DATA_VALUE=
_TS_TEST_DATA_DIRS_RENAME_VALUE=
### @usage: TS_TEST_DATA([RENAME] GLOBS...)
###
### Macro to add tests data (i.e. snapshots) used in testing to a bindir from curdir.
### Creates symbolic links to directories of files found by the specified globs.
###
### Parameters:
### - RENAME - adds ability to rename paths for tests data from curdir to bindir.
###            For example if your tested module located on "module" path and tests data in "module/tests_data".
###            Then you can be able to rename "tests_data" folder to something else - `RENAME tests_data:example`.
###            As a result in your bindir will be created folder - "module/example" which is a symbolic link on "module/tests_data" in curdir.
###            It is possible to specify multiple renaming rules in the following format "dir1:dir2;dir3/foo:dir4/bar", where "dir1" and "dir3" folders in curdir.
### - GLOBS... - globs to tests data files, symbolic links will be created to their folders. For example - "tests_data/**/*".
macro TS_TEST_DATA(RENAME="", GLOBS...) {
    _GLOB(_TS_TEST_DATA_VALUE $GLOBS)
    SET(_TS_TEST_DATA_DIRS_RENAME_VALUE $RENAME)
}

### @usage: TS_TEST_DEPENDS_ON_BUILD()
###
### Macro enables build and results unpacking for the module test is targeting.
### It is not required for most of the tests, but it might be needeed in some special cases.
macro TS_TEST_DEPENDS_ON_BUILD() {
    ENABLE(_TS_TEST_DEPENDS_ON_BUILD)
}

# TS_TYPECHECK

_TS_TYPECHECK_VALUE=none
_TS_TYPECHECK_TSCONFIG=

macro NO_TS_TYPECHECK() {
    SET(_TS_TYPECHECK_VALUE none)
}

### @usage: TS_TYPECHECK(tsconfigFile)
###
### For check CSS, SASS, LESS for StyleLint. Must be inside of Module (TS_WEBPACK, TS_VITE, TS_NEXT, etc)
###
###    - tsconfigFile - by default tsconfig.json or value from TS_CONFIG macros.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/macros#ts-typecheck
###
### @example:
###
###     TS_VITE()
###         TS_TYPECHECK()
###     END()
macro TS_TYPECHECK(TS_CONFG="") {
    ENABLE(_TS_TYPECHECK_VALUE)
    SET(_TS_TYPECHECK_TSCONFIG $TS_CONFG)
}

# TS_STYLELINT
_TS_STYLELINT_VALUE=no
_TS_STYLELINT_CONFIG=
_TS_STYLELINT_FILES=

### @usage: TS_STYLELINT(configFile)
###
### For check CSS, SASS, LESS for StyleLint. Must be inside of Module (TS_WEBPACK, TS_VITE, TS_NEXT, etc)
###
###    - configFile - by default .stylelintrc.
###
### Documentation: https://docs.yandex-team.ru/frontend-in-arcadia/references/macros#ts-stylelint
###
### @example:
###
###     TS_VITE()
###         TS_STYLELINT(.stylelintrc)
###     END()
macro TS_STYLELINT(_CONFIG) {
    ENABLE(_TS_STYLELINT_VALUE)
    SET(_TS_STYLELINT_CONFIG $_CONFIG)

    _GLOB(_TS_STYLELINT_FILES **/*(.css|.scss|.less) EXCLUDE $TS_EXCLUDE_DIR_GLOB $TS_COMMON_OUTDIR_GLOB $TS_GLOB_EXCLUDE_ADDITIONAL)
}