1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
from __future__ import annotations
import json
import os
import shutil
import sys
from unittest import mock
import pytest
import pre_commit.constants as C
from pre_commit import envcontext
from pre_commit import parse_shebang
from pre_commit.languages import node
from pre_commit.prefix import Prefix
from pre_commit.store import _make_local_repo
from pre_commit.util import cmd_output
from testing.language_helpers import run_language
from testing.util import xfailif_windows
ACTUAL_GET_DEFAULT_VERSION = node.get_default_version.__wrapped__
@pytest.fixture
def is_linux():
with mock.patch.object(sys, 'platform', 'linux'):
yield
@pytest.fixture
def is_win32():
with mock.patch.object(sys, 'platform', 'win32'):
yield
@pytest.fixture
def find_exe_mck():
with mock.patch.object(parse_shebang, 'find_executable') as mck:
yield mck
@pytest.mark.usefixtures('is_linux')
def test_sets_system_when_node_and_npm_are_available(find_exe_mck):
find_exe_mck.return_value = '/path/to/exe'
assert ACTUAL_GET_DEFAULT_VERSION() == 'system'
@pytest.mark.usefixtures('is_linux')
def test_uses_default_when_node_and_npm_are_not_available(find_exe_mck):
find_exe_mck.return_value = None
assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT
@pytest.mark.usefixtures('is_win32')
def test_sets_default_on_windows(find_exe_mck):
find_exe_mck.return_value = '/path/to/exe'
assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT
@xfailif_windows # pragma: win32 no cover
def test_healthy_system_node(tmpdir):
tmpdir.join('package.json').write('{"name": "t", "version": "1.0.0"}')
prefix = Prefix(str(tmpdir))
node.install_environment(prefix, 'system', ())
assert node.health_check(prefix, 'system') is None
@xfailif_windows # pragma: win32 no cover
def test_unhealthy_if_system_node_goes_missing(tmpdir):
bin_dir = tmpdir.join('bin').ensure_dir()
node_bin = bin_dir.join('node')
node_bin.mksymlinkto(shutil.which('node'))
prefix_dir = tmpdir.join('prefix').ensure_dir()
prefix_dir.join('package.json').write('{"name": "t", "version": "1.0.0"}')
path = ('PATH', (str(bin_dir), os.pathsep, envcontext.Var('PATH')))
with envcontext.envcontext((path,)):
prefix = Prefix(str(prefix_dir))
node.install_environment(prefix, 'system', ())
assert node.health_check(prefix, 'system') is None
node_bin.remove()
ret = node.health_check(prefix, 'system')
assert ret == '`node --version` returned 127'
@xfailif_windows # pragma: win32 no cover
def test_installs_without_links_outside_env(tmpdir):
tmpdir.join('bin/main.js').ensure().write(
'#!/usr/bin/env node\n'
'_ = require("lodash"); console.log("success!")\n',
)
tmpdir.join('package.json').write(
json.dumps({
'name': 'foo',
'version': '0.0.1',
'bin': {'foo': './bin/main.js'},
'dependencies': {'lodash': '*'},
}),
)
prefix = Prefix(str(tmpdir))
node.install_environment(prefix, 'system', ())
assert node.health_check(prefix, 'system') is None
# this directory shouldn't exist, make sure we succeed without it existing
cmd_output('rm', '-rf', str(tmpdir.join('node_modules')))
with node.in_env(prefix, 'system'):
assert cmd_output('foo')[1] == 'success!\n'
def _make_hello_world(tmp_path):
package_json = '''\
{"name": "t", "version": "0.0.1", "bin": {"node-hello": "./bin/main.js"}}
'''
tmp_path.joinpath('package.json').write_text(package_json)
bin_dir = tmp_path.joinpath('bin')
bin_dir.mkdir()
bin_dir.joinpath('main.js').write_text(
'#!/usr/bin/env node\n'
'console.log("Hello World");\n',
)
def test_node_hook_system(tmp_path):
_make_hello_world(tmp_path)
ret = run_language(tmp_path, node, 'node-hello')
assert ret == (0, b'Hello World\n')
def test_node_with_user_config_set(tmp_path):
cfg = tmp_path.joinpath('cfg')
cfg.write_text('cache=/dne\n')
with envcontext.envcontext((('NPM_CONFIG_USERCONFIG', str(cfg)),)):
test_node_hook_system(tmp_path)
@pytest.mark.parametrize('version', (C.DEFAULT, '18.14.0'))
def test_node_hook_versions(tmp_path, version):
_make_hello_world(tmp_path)
ret = run_language(tmp_path, node, 'node-hello', version=version)
assert ret == (0, b'Hello World\n')
def test_node_additional_deps(tmp_path):
_make_local_repo(str(tmp_path))
ret, out = run_language(tmp_path, node, 'npm ls -g', deps=('lodash',))
assert b' lodash@' in out
|