Compare commits
	
		
			3 Commits
		
	
	
		
			v4.4.2
			...
			41da641ab9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 41da641ab9 | |||
| 6ba628f80e | |||
| 1f10268aa0 | 
| @@ -13,7 +13,7 @@ class MissingFlagAndEnvironmentVariableError(EnvironmentError, ArgumentError): | |||||||
|  |  | ||||||
| class MissingScwryptsExecutableError(EnvironmentError): | class MissingScwryptsExecutableError(EnvironmentError): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__(f'scwrypts must be installed and available on your PATH') |         super().__init__('scwrypts must be installed and available on your PATH') | ||||||
|  |  | ||||||
|  |  | ||||||
| class BadScwryptsLookupError(ValueError): | class BadScwryptsLookupError(ValueError): | ||||||
|   | |||||||
| @@ -5,44 +5,54 @@ from subprocess import run | |||||||
| from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError | from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError | ||||||
|  |  | ||||||
|  |  | ||||||
| def scwrypts(*args, patterns=None, name=None, group=None, _type=None, log_level=None): | def scwrypts(patterns=None, args=None, executable_args=None, name=None, group=None, _type=None): | ||||||
|     ''' |     ''' | ||||||
|     top-level scwrypts invoker from python |     top-level scwrypts invoker from python | ||||||
|  |  | ||||||
|     - patterns allows for pattern-based scwrypt lookup |         patterns          str / list   pattern-based scwrypt lookup | ||||||
|     - name/group/type allos for precise-match lookup |         args              str / list   arguments forwarded to the invoked scwrypt | ||||||
|  |         executable_args   str / list   arguments for the 'scwrypts' executable | ||||||
|  |           (str above assumes space-delimited values) | ||||||
|  |  | ||||||
|     *args should be a list of strings and is forwarded to the |         name    str   exact scwrypt lookup name (requires group and _type) | ||||||
|     invoked scwrypt |         group   str   exact scwrypt lookup group | ||||||
|  |         _type   str   exact scwrypt lookup type | ||||||
|  |  | ||||||
|  |         SCWRYPTS_EXECUTABLE   configuration variable which defines the full path to scwrypts executable | ||||||
|  |  | ||||||
|     see 'scwrypts --help' for more information |     see 'scwrypts --help' for more information | ||||||
|     ''' |     ''' | ||||||
|     executable = which('scwrypts') |  | ||||||
|     if executable is None: |  | ||||||
|         raise MissingScwryptsExecutableError() |  | ||||||
|  |  | ||||||
|     if patterns is None and name is None: |     if patterns is None and name is None: | ||||||
|         raise BadScwryptsLookupError() |         raise BadScwryptsLookupError() | ||||||
|  |  | ||||||
|     pre_args = [] |     if name is not None and (group is None or _type is None): | ||||||
|  |         raise MissingScwryptsGroupOrTypeError(group, _type) | ||||||
|  |  | ||||||
|     if name is None: |     executable = which(getenv('SCWRYPTS_EXECUTABLE', 'scwrypts')) | ||||||
|         pre_args += patterns |  | ||||||
|     else: |  | ||||||
|         pre_args += ['--name', name, '--group', group, '--type', _type] |  | ||||||
|         if group is None or _type is None: |  | ||||||
|             raise MissingScwryptsGroupOrTypeError(group, _type) |  | ||||||
|  |  | ||||||
|     if log_level is not None: |     if executable is None: | ||||||
|         pre_args += ['--log-level', log_level] |         raise MissingScwryptsExecutableError() | ||||||
|  |  | ||||||
|  |     lookup = _parse(patterns) if name is None else f'--name {name} --group {group} --type {_type}' | ||||||
|  |  | ||||||
|     depth = getenv('SUBSCWRYPT', '') |     depth = getenv('SUBSCWRYPT', '') | ||||||
|     if depth != '': |     if depth != '': | ||||||
|         depth = int(depth) + 1 |         depth = int(depth) + 1 | ||||||
|  |  | ||||||
|     return run( |     return run( | ||||||
|         f'SUBSCWRYPT={depth} {executable} {" ".join(pre_args)} -- {" ".join(args)}', |         f'SUBSCWRYPT={depth} {executable} {_parse(executable_args)} {lookup} -- {_parse(args)}', | ||||||
|         shell=True, |         shell=True, | ||||||
|         executable='/bin/zsh', |         executable='/bin/zsh', | ||||||
|         check=False, |         check=False, | ||||||
|  |         capture_output=True, | ||||||
|  |         text=True, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  | def _parse(string_or_list_args): | ||||||
|  |     if string_or_list_args is None: | ||||||
|  |         return '' | ||||||
|  |  | ||||||
|  |     if isinstance(string_or_list_args, list): | ||||||
|  |         return ' '.join(string_or_list_args) | ||||||
|  |  | ||||||
|  |     return str(string_or_list_args) | ||||||
|   | |||||||
							
								
								
									
										184
									
								
								py/lib/scwrypts/scwrypts/test_scwrypts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								py/lib/scwrypts/scwrypts/test_scwrypts.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | |||||||
|  | from random import choice | ||||||
|  | from re import search | ||||||
|  | from string import ascii_letters, digits | ||||||
|  | from types import SimpleNamespace | ||||||
|  | from unittest.mock import patch | ||||||
|  |  | ||||||
|  | from pytest import fixture, raises | ||||||
|  |  | ||||||
|  | from scwrypts.test import get_generator | ||||||
|  |  | ||||||
|  | from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError | ||||||
|  | from .scwrypts import scwrypts | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | def test_scwrypts(sample, _scwrypts): | ||||||
|  |     assert validate_scwrypts_output(sample, _scwrypts) | ||||||
|  |  | ||||||
|  | def test_scwrypts_finds_system_executable(sample, _scwrypts, mock_which): | ||||||
|  |     mock_which.assert_called_once_with(sample.env['SCWRYPTS_EXECUTABLE']) | ||||||
|  |  | ||||||
|  | def test_scwrypts_uses_configured_executable_path(_scwrypts, mock_getenv): | ||||||
|  |     mock_getenv.assert_any_call('SCWRYPTS_EXECUTABLE', 'scwrypts') | ||||||
|  |  | ||||||
|  | def test_scwrypts_uses_correct_depth(_scwrypts, mock_getenv): | ||||||
|  |     mock_getenv.assert_any_call('SUBSCWRYPT', '') | ||||||
|  |  | ||||||
|  | def test_scwrypts_runs_subprocess(_scwrypts, mock_run): | ||||||
|  |     mock_run.assert_called_once() | ||||||
|  |  | ||||||
|  | ########################################## | ||||||
|  |  | ||||||
|  | def test_scwrypts_omit_optionals(sample, _scwrypts_omit_optionals): | ||||||
|  |     assert validate_scwrypts_output(sample, _scwrypts_omit_optionals) | ||||||
|  |  | ||||||
|  | def test_scwrypts_omit_optionals_finds_system_executable(sample, _scwrypts_omit_optionals, mock_which): | ||||||
|  |     mock_which.assert_called_once_with('scwrypts') | ||||||
|  |  | ||||||
|  | def test_scwrypts_omit_optionals_uses_configured_executable_path(_scwrypts_omit_optionals, mock_getenv): | ||||||
|  |     mock_getenv.assert_any_call('SCWRYPTS_EXECUTABLE', 'scwrypts') | ||||||
|  |  | ||||||
|  | def test_scwrypts_omit_optionals_uses_correct_depth(_scwrypts_omit_optionals, mock_getenv): | ||||||
|  |     mock_getenv.assert_any_call('SUBSCWRYPT', '') | ||||||
|  |  | ||||||
|  | def test_scwrypts_omit_optionals_runs_subprocess(_scwrypts_omit_optionals, mock_run): | ||||||
|  |     mock_run.assert_called_once() | ||||||
|  |  | ||||||
|  | ########################################## | ||||||
|  |  | ||||||
|  | def test_invalid_lookup_missing_patterns_and_name(sample): | ||||||
|  |     sample.patterns = None | ||||||
|  |     sample.name = None | ||||||
|  |     with raises(BadScwryptsLookupError): | ||||||
|  |         scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | def test_invalid_name_lookup_missing_group(sample): | ||||||
|  |     sample.group = None | ||||||
|  |     with raises(MissingScwryptsGroupOrTypeError): | ||||||
|  |         scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | def test_invalid_name_lookup_missing_type(sample): | ||||||
|  |     sample._type = None  # pylint: disable=protected-access | ||||||
|  |     with raises(MissingScwryptsGroupOrTypeError): | ||||||
|  |         scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | def test_invalid_scwrypts_installation(sample, mock_which): | ||||||
|  |     mock_which.return_value = None | ||||||
|  |     with raises(MissingScwryptsExecutableError): | ||||||
|  |         scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | generate = get_generator({ | ||||||
|  |     'str_length_minimum':   8, | ||||||
|  |     'str_length_maximum': 128, | ||||||
|  |     'character_set': ascii_letters + digits + '/-_' | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  | def _generate_str_or_list_arg(): | ||||||
|  |     random_arg = generate(list, {'data_types': {str}}) | ||||||
|  |     return random_arg if choice([str, list]) == list else ' '.join(random_arg) | ||||||
|  |  | ||||||
|  | @fixture(name='sample') | ||||||
|  | def fixture_sample(): | ||||||
|  |     sample = SimpleNamespace( | ||||||
|  |             patterns        = _generate_str_or_list_arg(), | ||||||
|  |             args            = _generate_str_or_list_arg(), | ||||||
|  |             executable_args = _generate_str_or_list_arg(), | ||||||
|  |  | ||||||
|  |             name  = generate(str), | ||||||
|  |             group = generate(str), | ||||||
|  |             _type = generate(str), | ||||||
|  |  | ||||||
|  |             executable = generate(str), | ||||||
|  |  | ||||||
|  |             env = { | ||||||
|  |                 'SCWRYPTS_EXECUTABLE': generate(str), | ||||||
|  |                 'SUBSCWRYPT': str(generate(int, {'minimum': 1, 'maximum': 99})), | ||||||
|  |                 }, | ||||||
|  |  | ||||||
|  |             returncode = generate(int), | ||||||
|  |             stdout = generate(str), | ||||||
|  |             stderr = generate(str), | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |     return sample | ||||||
|  |  | ||||||
|  | def get_scwrypts_args(sample): | ||||||
|  |     return { | ||||||
|  |             key: getattr(sample, key) | ||||||
|  |             for key in [ | ||||||
|  |                 'patterns', | ||||||
|  |                 'args', | ||||||
|  |                 'executable_args', | ||||||
|  |                 'name', | ||||||
|  |                 'group', | ||||||
|  |                 '_type', | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | @fixture(name='mock_which', autouse=True) | ||||||
|  | def fixture_mock_which(sample): | ||||||
|  |     with patch('scwrypts.scwrypts.scwrypts.which') as mock: | ||||||
|  |         mock.return_value = sample.executable | ||||||
|  |         yield mock | ||||||
|  |  | ||||||
|  | @fixture(name='mock_getenv', autouse=True) | ||||||
|  | def fixture_mock_getenv(sample): | ||||||
|  |     with patch('scwrypts.scwrypts.scwrypts.getenv') as mock: | ||||||
|  |         mock.side_effect = sample.env.get | ||||||
|  |         yield mock | ||||||
|  |  | ||||||
|  | @fixture(name='mock_run', autouse=True) | ||||||
|  | def fixture_mock_run(sample): | ||||||
|  |     with patch('scwrypts.scwrypts.scwrypts.run') as mock: | ||||||
|  |         mock.side_effect = lambda *args, **_kwargs: SimpleNamespace( | ||||||
|  |                 args = args, | ||||||
|  |                 returncode = sample.returncode, | ||||||
|  |                 stdout = sample.stdout, | ||||||
|  |                 stderr = sample.stderr, | ||||||
|  |                 ) | ||||||
|  |         yield mock | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | @fixture(name='_scwrypts') | ||||||
|  | def fixture_scwrypts(sample): | ||||||
|  |     return scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | @fixture(name='_scwrypts_omit_optionals') | ||||||
|  | def fixture_scwrypts_omit_optionals(sample): | ||||||
|  |     sample.args = None | ||||||
|  |     sample.executable_args = None | ||||||
|  |  | ||||||
|  |     del sample.env['SCWRYPTS_EXECUTABLE'] | ||||||
|  |     del sample.env['SUBSCWRYPT'] | ||||||
|  |  | ||||||
|  |     return scwrypts(**get_scwrypts_args(sample)) | ||||||
|  |  | ||||||
|  | def validate_scwrypts_output(sample, output): | ||||||
|  |     # | ||||||
|  |     # I would love to use 'assert _scwrypts == SimpleNamespace(...expected...)' | ||||||
|  |     # but the output.args is difficult to recreate without copying all the | ||||||
|  |     # processing logic over from the scwrypts function | ||||||
|  |     # | ||||||
|  |     # opting for a bit of a strange equality test here, checking the args | ||||||
|  |     # as closely as possible without copying parsing logic | ||||||
|  |     # | ||||||
|  |     run_args_reduced_to_a_single_string = len(output.args) == 1 | ||||||
|  |     run_args_follow_expected_form = search( | ||||||
|  |             fr'^SUBSCWRYPT=.* {sample.executable} .*-- .*$', | ||||||
|  |             output.args[0], | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |     return all([ | ||||||
|  |         run_args_reduced_to_a_single_string, | ||||||
|  |         run_args_follow_expected_form, | ||||||
|  |         output.returncode == sample.returncode, | ||||||
|  |         output.stdout     == sample.stdout, | ||||||
|  |         output.stderr     == sample.stderr, | ||||||
|  |         ]) | ||||||
| @@ -5,6 +5,6 @@ __all__ = [ | |||||||
|         'generate', |         'generate', | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
| from .generate import generate | from .generate import generate, get_generator | ||||||
|  |  | ||||||
| from .character_set import * | from .character_set import * | ||||||
|   | |||||||
| @@ -45,6 +45,21 @@ DEFAULT_OPTIONS = { | |||||||
|         'requests_response_status_code': status_codes.codes[200], |         'requests_response_status_code': status_codes.codes[200], | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | def get_generator(default_options=None): | ||||||
|  |     if default_options is None: | ||||||
|  |         default_options = {} | ||||||
|  |  | ||||||
|  |     def generator_function(data_type=None, options_overrides=None): | ||||||
|  |         if options_overrides is None: | ||||||
|  |             options_overrides = {} | ||||||
|  |  | ||||||
|  |         return generate( | ||||||
|  |                 data_type = data_type, | ||||||
|  |                 options = default_options | options_overrides, | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |     return generator_function | ||||||
|  |  | ||||||
| def generate(data_type=None, options=None): | def generate(data_type=None, options=None): | ||||||
|     ''' |     ''' | ||||||
|     generate random data with the call of a function |     generate random data with the call of a function | ||||||
|   | |||||||
| @@ -1,100 +0,0 @@ | |||||||
| { |  | ||||||
| 	"name": "scwrypts", |  | ||||||
| 	"main": "dist/index.js", |  | ||||||
| 	"type": "module", |  | ||||||
| 	"files": [ |  | ||||||
| 		"dist" |  | ||||||
| 	], |  | ||||||
| 	"description": "scwrypts integration for typescript", |  | ||||||
| 	"scripts": { |  | ||||||
| 		"build": "rm -rf ./dist && tsc", |  | ||||||
| 		"test": "jest", |  | ||||||
| 		"lint": "eslint . && prettier --check src/", |  | ||||||
| 		"format": "prettier --write src/" |  | ||||||
| 	}, |  | ||||||
| 	"author": "Wryn (yage) Wagner", |  | ||||||
| 	"license": "GPL-3.0", |  | ||||||
| 	"devDependencies": { |  | ||||||
| 		"@jest/globals": "^29.7.0", |  | ||||||
| 		"@types/jest": "^29.5.12", |  | ||||||
| 		"@types/node": "^20.11.19", |  | ||||||
| 		"@types/uuid": "^9.0.8", |  | ||||||
| 		"@typescript-eslint/eslint-plugin": "^7.0.2", |  | ||||||
| 		"@typescript-eslint/parser": "^7.0.2", |  | ||||||
| 		"eslint": "^8.56.0", |  | ||||||
| 		"jest": "^29.7.0", |  | ||||||
| 		"prettier": "^3.2.5", |  | ||||||
| 		"ts-jest": "^29.1.2", |  | ||||||
| 		"ts-node": "^10.9.2", |  | ||||||
| 		"typescript": "^5.3.3", |  | ||||||
| 		"uuid": "^9.0.1" |  | ||||||
| 	}, |  | ||||||
| 	"eslintConfig": { |  | ||||||
| 		"ignorePatterns": [ |  | ||||||
| 			"dist", |  | ||||||
| 			"node_modules" |  | ||||||
| 		], |  | ||||||
| 		"env": { |  | ||||||
| 			"node": true, |  | ||||||
| 			"es2021": true |  | ||||||
| 		}, |  | ||||||
| 		"extends": [ |  | ||||||
| 			"eslint:recommended", |  | ||||||
| 			"plugin:@typescript-eslint/recommended" |  | ||||||
| 		], |  | ||||||
| 		"overrides": [ |  | ||||||
| 			{ |  | ||||||
| 				"env": { |  | ||||||
| 					"node": true |  | ||||||
| 				}, |  | ||||||
| 				"files": [ |  | ||||||
| 					".eslintrc.{js,cjs}" |  | ||||||
| 				], |  | ||||||
| 				"parserOptions": { |  | ||||||
| 					"sourceType": "script" |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		], |  | ||||||
| 		"parser": "@typescript-eslint/parser", |  | ||||||
| 		"parserOptions": { |  | ||||||
| 			"ecmaVersion": "latest", |  | ||||||
| 			"sourceType": "module" |  | ||||||
| 		}, |  | ||||||
| 		"plugins": [ |  | ||||||
| 			"@typescript-eslint" |  | ||||||
| 		], |  | ||||||
| 		"rules": { |  | ||||||
| 			"linebreak-style": [ |  | ||||||
| 				"error", |  | ||||||
| 				"unix" |  | ||||||
| 			], |  | ||||||
| 			"quotes": [ |  | ||||||
| 				"error", |  | ||||||
| 				"single" |  | ||||||
| 			], |  | ||||||
| 			"semi": [ |  | ||||||
| 				"error", |  | ||||||
| 				"always" |  | ||||||
| 			], |  | ||||||
| 			"comma-dangle": [ |  | ||||||
| 				"error", |  | ||||||
| 				"always-multiline" |  | ||||||
| 			] |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"prettier": { |  | ||||||
| 		"printWidth": 120, |  | ||||||
| 		"singleQuote": true, |  | ||||||
| 		"trailingComma": "all" |  | ||||||
| 	}, |  | ||||||
| 	"jest": { |  | ||||||
| 		"preset": "ts-jest", |  | ||||||
| 		"clearMocks": true, |  | ||||||
| 		"moduleNameMapper": { |  | ||||||
| 			"^(\\.{1,2}/.*)\\.js$": "$1" |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"dependencies": { |  | ||||||
| 		"execa": "^8.0.1" |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										86
									
								
								zx/lib/package.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								zx/lib/package.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | --- | ||||||
|  | name: scwrypts | ||||||
|  | author: Wryn (yage) Wagner | ||||||
|  | description: scwrypts integration for typescript | ||||||
|  | license: GPL-3.0 | ||||||
|  | type: module | ||||||
|  | main: dist/index.js | ||||||
|  |  | ||||||
|  | files: | ||||||
|  |   - dist | ||||||
|  |  | ||||||
|  | scripts: | ||||||
|  |   build: rm -rf ./dist && tsc | ||||||
|  |   test: jest | ||||||
|  |   lint: eslint . && prettier --check src/ | ||||||
|  |   format: prettier --write src/ | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | dependencies: | ||||||
|  |   execa: ^8.0.1 | ||||||
|  |  | ||||||
|  | devDependencies: | ||||||
|  |   '@jest/globals': ^29.7.0 | ||||||
|  |   '@types/jest': ^29.5.12 | ||||||
|  |   '@types/node': ^20.11.19 | ||||||
|  |   '@types/uuid': ^9.0.8 | ||||||
|  |   '@typescript-eslint/eslint-plugin': ^7.0.2 | ||||||
|  |   '@typescript-eslint/parser': ^7.0.2 | ||||||
|  |   eslint: ^8.56.0 | ||||||
|  |   jest: ^29.7.0 | ||||||
|  |   prettier: ^3.2.5 | ||||||
|  |   ts-jest: ^29.1.2 | ||||||
|  |   ts-node: ^10.9.2 | ||||||
|  |   typescript: ^5.3.3 | ||||||
|  |   uuid: ^9.0.1 | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | eslintConfig: | ||||||
|  |   ignorePatterns: | ||||||
|  |     - dist | ||||||
|  |     - node_modules | ||||||
|  |   env: | ||||||
|  |     node: true | ||||||
|  |     es2021: true | ||||||
|  |   extends: | ||||||
|  |     - eslint:recommended | ||||||
|  |     - plugin:@typescript-eslint/recommended | ||||||
|  |   overrides: | ||||||
|  |     - env: | ||||||
|  |         node: true | ||||||
|  |       files: | ||||||
|  |         - .eslintrc.{js,cjs} | ||||||
|  |       parserOptions: | ||||||
|  |         sourceType: script | ||||||
|  |   parser: '@typescript-eslint/parser' | ||||||
|  |   parserOptions: | ||||||
|  |     ecmaVersion: latest | ||||||
|  |     sourceType: module | ||||||
|  |   plugins: | ||||||
|  |     - '@typescript-eslint' | ||||||
|  |   rules: | ||||||
|  |     linebreak-style: | ||||||
|  |       - error | ||||||
|  |       - unix | ||||||
|  |     quotes: | ||||||
|  |       - error | ||||||
|  |       - single | ||||||
|  |     semi: | ||||||
|  |       - error | ||||||
|  |       - always | ||||||
|  |     comma-dangle: | ||||||
|  |       - error | ||||||
|  |       - always-multiline | ||||||
|  |  | ||||||
|  | prettier: | ||||||
|  |   printWidth: 120 | ||||||
|  |   singleQuote: true | ||||||
|  |   trailingComma: all | ||||||
|  |  | ||||||
|  | jest: | ||||||
|  |   preset: ts-jest | ||||||
|  |   clearMocks: true | ||||||
|  |   moduleNameMapper: | ||||||
|  |     ^(\.{1,2}/.*)\.js$: $1 | ||||||
		Reference in New Issue
	
	Block a user