test_cli.py (5207B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import io 6 import os 7 import subprocess 8 import sys 9 from shutil import which 10 11 import mozunit 12 import pytest 13 14 from mozlint import cli 15 16 here = os.path.abspath(os.path.dirname(__file__)) 17 18 19 @pytest.fixture 20 def parser(): 21 return cli.MozlintParser() 22 23 24 @pytest.fixture 25 def run(parser, files): 26 def inner(args=None): 27 args = args or [] 28 if not any("--stdin-filename" in a for a in args): 29 args.extend(files) 30 lintargs = vars(parser.parse_args(args)) 31 lintargs["root"] = here 32 lintargs["config_paths"] = [os.path.join(here, "linters")] 33 return cli.run(**lintargs) 34 35 return inner 36 37 38 def test_cli_with_ascii_encoding(run, monkeypatch, capfd): 39 cmd = [sys.executable, "runcli.py", "-l=string", "-f=stylish", "files/foobar.js"] 40 env = os.environ.copy() 41 env["PYTHONPATH"] = os.pathsep.join(sys.path) 42 env["PYTHONIOENCODING"] = "ascii" 43 proc = subprocess.Popen( 44 cmd, 45 stdout=subprocess.PIPE, 46 stderr=subprocess.STDOUT, 47 cwd=here, 48 env=env, 49 universal_newlines=True, 50 ) 51 out = proc.communicate()[0] 52 assert "Traceback" not in out 53 54 55 def test_cli_run_with_fix(run, capfd): 56 ret = run(["-f", "json", "--fix", "--linter", "external"]) 57 out, err = capfd.readouterr() 58 assert ret == 0 59 assert out.endswith("{}\n") 60 61 62 @pytest.mark.skipif(not which("echo"), reason="No `echo` executable found.") 63 def test_cli_run_with_edit(run, parser, capfd): 64 os.environ["EDITOR"] = "echo" 65 66 ret = run(["-f", "compact", "--edit", "--linter", "external"]) 67 out, err = capfd.readouterr() 68 out = out.splitlines() 69 assert ret == 1 70 assert out[0].endswith("foobar.js") # from the `echo` editor 71 assert "foobar.js: line 1, col 1, Error" in out[1] 72 assert "foobar.js: line 2, col 1, Error" in out[2] 73 assert "2 problems" in out[-1] 74 assert len(out) == 5 75 76 del os.environ["EDITOR"] 77 with pytest.raises(SystemExit): 78 parser.parse_args(["--edit"]) 79 80 81 def test_cli_run_with_setup(run, capfd): 82 # implicitly call setup 83 ret = run(["-l", "setup", "-l", "setupfailed", "-l", "setupraised"]) 84 out, err = capfd.readouterr() 85 assert "setup passed" in out 86 assert "setup failed" in out 87 assert "setup raised" in out 88 assert ret == 1 89 90 # explicitly call setup 91 ret = run(["-l", "setup", "-l", "setupfailed", "-l", "setupraised", "--setup"]) 92 out, err = capfd.readouterr() 93 assert "setup passed" in out 94 assert "setup failed" in out 95 assert "setup raised" in out 96 assert ret == 1 97 98 99 def test_cli_run_with_all_skipped(run, capfd): 100 # implicitly call setup 101 ret = run(["-l", "setupskipped"]) 102 out, err = capfd.readouterr() 103 assert "setup skipped" in out 104 assert "ERROR" in err 105 assert ret == 1 106 107 108 def test_cli_for_exclude_list(run, monkeypatch, capfd): 109 ret = run(["-l", "excludes", "--check-exclude-list"]) 110 out, err = capfd.readouterr() 111 112 assert "**/foobar.js" in out 113 assert ( 114 "The following list of paths are now green and can be removed from the exclude list:" 115 in out 116 ) 117 118 ret = run(["-l", "excludes_empty", "--check-exclude-list"]) 119 out, err = capfd.readouterr() 120 121 assert "No path in the exclude list is green." in out 122 assert ret == 1 123 124 125 def test_cli_run_with_wrong_linters(run, capfd): 126 run(["-l", "external", "-l", "foobar"]) 127 out, err = capfd.readouterr() 128 129 # Check if it identifies foobar as invalid linter 130 assert "A failure occurred in the foobar linter." in out 131 132 # Check for exception message 133 assert "Invalid linters given, run again using valid linters or no linters" in out 134 135 136 def test_cli_run_with_stdin_filename(run, filedir, capfd, monkeypatch, tmp_path): 137 for arg in ("bar.txt", "--workdir", "--outgoing", "--rev=abc"): 138 with pytest.raises(SystemExit): 139 run(["--stdin-filename=foo.txt", arg]) 140 141 capfd.readouterr() 142 monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"foobar\n"))) 143 run(["-l", "string", f"--stdin-filename={filedir}/foobar.py"]) 144 out, err = capfd.readouterr() 145 assert out == "✖ 0 problems (0 errors, 0 warnings, 0 fixed)\n" 146 147 monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"foobar\n"))) 148 run(["-l", "string", f"--stdin-filename={filedir}/foobar.py", "--dump-stdin-file"]) 149 out, err = capfd.readouterr() 150 assert out == "foobar\n" 151 152 monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"foobar\n"))) 153 run(["-l", "string", f"--stdin-filename={filedir}/foobar.py", "--fix"]) 154 out, err = capfd.readouterr() 155 assert out == "foobar\n" 156 157 monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"foobar\n"))) 158 tmpfile = tmp_path / "temp" 159 run([ 160 "-l", 161 "string", 162 f"--stdin-filename={filedir}/foobar.py", 163 "--dump-stdin-file", 164 str(tmpfile), 165 ]) 166 out, err = capfd.readouterr() 167 assert out == "" 168 assert tmpfile.read_text() == "foobar\n" 169 170 171 if __name__ == "__main__": 172 mozunit.main()