From c8f0071c4f5336dfe0efc5d3c218ab49f2401264 Mon Sep 17 00:00:00 2001
From: Elena Vilchik
Date: Wed, 18 Dec 2019 17:10:10 +0100
Subject: Rely on NodeJS API of Stylelint to execute CSS rules (#221)
---
.../css-bundle/tests/fixtures/file-bom.css | 2 +
.../css-bundle/tests/fixtures/file.css | 1 +
.../css-bundle/tests/fixtures/file.html | 12 ++
.../css-bundle/tests/fixtures/file.php | 13 ++
.../css-bundle/tests/fixtures/stylelintconfig.json | 5 +
.../css-bundle/tests/server-mock-stylelint.test.ts | 51 +++++++
sonar-css-plugin/css-bundle/tests/server.test.ts | 153 +++++++++++++++++++++
sonar-css-plugin/css-bundle/tests/utils.ts | 36 +++++
8 files changed, 273 insertions(+)
create mode 100644 sonar-css-plugin/css-bundle/tests/fixtures/file-bom.css
create mode 100644 sonar-css-plugin/css-bundle/tests/fixtures/file.css
create mode 100644 sonar-css-plugin/css-bundle/tests/fixtures/file.html
create mode 100644 sonar-css-plugin/css-bundle/tests/fixtures/file.php
create mode 100644 sonar-css-plugin/css-bundle/tests/fixtures/stylelintconfig.json
create mode 100644 sonar-css-plugin/css-bundle/tests/server-mock-stylelint.test.ts
create mode 100644 sonar-css-plugin/css-bundle/tests/server.test.ts
create mode 100644 sonar-css-plugin/css-bundle/tests/utils.ts
(limited to 'sonar-css-plugin/css-bundle/tests')
diff --git a/sonar-css-plugin/css-bundle/tests/fixtures/file-bom.css b/sonar-css-plugin/css-bundle/tests/fixtures/file-bom.css
new file mode 100644
index 0000000..0ecd9c3
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/fixtures/file-bom.css
@@ -0,0 +1,2 @@
+p {
+}
diff --git a/sonar-css-plugin/css-bundle/tests/fixtures/file.css b/sonar-css-plugin/css-bundle/tests/fixtures/file.css
new file mode 100644
index 0000000..802e4f0
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/fixtures/file.css
@@ -0,0 +1 @@
+p { }
diff --git a/sonar-css-plugin/css-bundle/tests/fixtures/file.html b/sonar-css-plugin/css-bundle/tests/fixtures/file.html
new file mode 100644
index 0000000..02e014f
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/fixtures/file.html
@@ -0,0 +1,12 @@
+
+
+
+ Page Title
+
+
+
+
+
diff --git a/sonar-css-plugin/css-bundle/tests/fixtures/file.php b/sonar-css-plugin/css-bundle/tests/fixtures/file.php
new file mode 100644
index 0000000..54d36ee
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/fixtures/file.php
@@ -0,0 +1,13 @@
+
+
+
+ Index
+
+
+
+ = "Hello World!" ?>
+
+
diff --git a/sonar-css-plugin/css-bundle/tests/fixtures/stylelintconfig.json b/sonar-css-plugin/css-bundle/tests/fixtures/stylelintconfig.json
new file mode 100644
index 0000000..44d0932
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/fixtures/stylelintconfig.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "block-no-empty": true
+ }
+}
\ No newline at end of file
diff --git a/sonar-css-plugin/css-bundle/tests/server-mock-stylelint.test.ts b/sonar-css-plugin/css-bundle/tests/server-mock-stylelint.test.ts
new file mode 100644
index 0000000..f7df176
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/server-mock-stylelint.test.ts
@@ -0,0 +1,51 @@
+import { start, setLogHandlersForTests } from "../src/server";
+import { Server } from "http";
+import * as path from "path";
+import { promisify } from "util";
+import * as stylelint from "stylelint";
+import { postToServer } from "./utils";
+
+const filePath = path.join(__dirname, "fixtures", "file.css");
+
+const request = JSON.stringify({
+ filePath,
+ configFile: path.join(__dirname, "fixtures", "stylelintconfig.json")
+});
+
+jest.mock("stylelint");
+
+describe("server", () => {
+ let server: Server;
+ let close: () => Promise;
+ const logSpy = jest.fn();
+ const errorSpy = jest.fn();
+
+ beforeAll(async () => {
+ setLogHandlersForTests(logSpy, errorSpy);
+ server = await start();
+ close = promisify(server.close.bind(server));
+ });
+
+ afterAll(async () => {
+ jest.restoreAllMocks();
+ await close();
+ });
+
+ it("should not return issues for not original file", async () => {
+ (stylelint.lint as any).mockResolvedValue({
+ results: [{ source: "foo.bar" }]
+ });
+ const response = await postToServer(request, "/analyze", server);
+ expect(JSON.parse(response)).toEqual([]);
+ expect(logSpy).toHaveBeenCalledWith(
+ `DEBUG For file [${filePath}] received issues with [foo.bar] as a source. They will not be reported.`
+ );
+ });
+
+ it("should not return issues when failed promise returned", async () => {
+ (stylelint.lint as any).mockRejectedValue("some reason");
+ const response = await postToServer(request, "/analyze", server);
+ expect(JSON.parse(response)).toEqual([]);
+ expect(errorSpy).toHaveBeenCalledWith("some reason");
+ });
+});
diff --git a/sonar-css-plugin/css-bundle/tests/server.test.ts b/sonar-css-plugin/css-bundle/tests/server.test.ts
new file mode 100644
index 0000000..8465810
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/server.test.ts
@@ -0,0 +1,153 @@
+import { start, setLogHandlersForTests } from "../src/server";
+import * as http from "http";
+import { Server } from "http";
+import { promisify } from "util";
+import { AddressInfo } from "net";
+import { postToServer } from "./utils";
+import * as path from "path";
+
+const configFile = path.join(__dirname, "fixtures", "stylelintconfig.json");
+
+describe("server", () => {
+ let server: Server;
+ let close: () => Promise;
+ const logSpy = jest.fn();
+ const errorSpy = jest.fn();
+
+ beforeAll(async () => {
+ setLogHandlersForTests(logSpy, errorSpy);
+ server = await start();
+ close = promisify(server.close.bind(server));
+ });
+
+ afterAll(async () => {
+ jest.restoreAllMocks();
+ await close();
+ });
+
+ it("should log with debug server start", async () => {
+ expect(server.listening).toEqual(true);
+ expect(logSpy).toBeCalledTimes(2);
+ expect(logSpy).toBeCalledWith(
+ "DEBUG starting stylelint-bridge server at port",
+ 0
+ );
+ expect(logSpy).toBeCalledWith(
+ "DEBUG stylelint-bridge server is running at port",
+ (server.address()).port
+ );
+ expect(errorSpy).toBeCalledTimes(0);
+ });
+
+ it("should respond to analysis request", async () => {
+ const request = JSON.stringify({
+ filePath: path.join(__dirname, "fixtures", "file.css"),
+ configFile
+ });
+ const response = await post(request, "/analyze");
+ expect(JSON.parse(response)).toEqual([
+ {
+ line: 1,
+ rule: "block-no-empty",
+ text: "Unexpected empty block (block-no-empty)"
+ }
+ ]);
+ });
+
+ it("should respond to analysis request for php", async () => {
+ const requestPhp = JSON.stringify({
+ filePath: path.join(__dirname, "fixtures", "file.php"),
+ configFile
+ });
+ const responsePhp = await post(requestPhp, "/analyze");
+ expect(JSON.parse(responsePhp)).toEqual([
+ {
+ line: 7,
+ rule: "block-no-empty",
+ text: "Unexpected empty block (block-no-empty)"
+ }
+ ]);
+ });
+
+ it("should respond to analysis request for html", async () => {
+ const requestHtml = JSON.stringify({
+ filePath: path.join(__dirname, "fixtures", "file.html"),
+ configFile
+ });
+ const responseHtml = await post(requestHtml, "/analyze");
+ expect(JSON.parse(responseHtml)).toEqual([
+ {
+ line: 6,
+ rule: "block-no-empty",
+ text: "Unexpected empty block (block-no-empty)"
+ }
+ ]);
+ });
+
+ it("should cut BOM", async () => {
+ const response = await post(
+ JSON.stringify({
+ filePath: path.join(__dirname, "fixtures", "file-bom.css"),
+ configFile
+ }),
+ "/analyze"
+ );
+ expect(JSON.parse(response)).toEqual([
+ {
+ line: 1,
+ rule: "block-no-empty",
+ text: "Unexpected empty block (block-no-empty)"
+ }
+ ]);
+ });
+
+ it("should respond OK! when started", done => {
+ const req = http.request(
+ {
+ host: "localhost",
+ port: (server.address()).port,
+ path: "/status",
+ method: "GET"
+ },
+ res => {
+ let data = "";
+ res.on("data", chunk => {
+ data += chunk;
+ });
+ res.on("end", () => {
+ expect(data).toEqual("OK!");
+ done();
+ });
+ }
+ );
+ req.end();
+ });
+
+ it("should return empty list of issues when request not json", async () => {
+ const response = await post("invalid json", "/analyze");
+ expect(JSON.parse(response)).toEqual([]);
+ expect(errorSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: expect.stringContaining(
+ "Unexpected token i in JSON at position 0"
+ )
+ })
+ );
+ });
+
+ it("should return empty list of issues when invalid request", async () => {
+ const response = await post("{}", "/analyze");
+ expect(JSON.parse(response)).toEqual([]);
+ expect(errorSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: expect.stringContaining(
+ "Unexpected token i in JSON at position 0"
+ )
+ })
+ );
+ });
+
+ function post(data: string, endpoint: string): Promise {
+ return postToServer(data, endpoint, server);
+ }
+});
diff --git a/sonar-css-plugin/css-bundle/tests/utils.ts b/sonar-css-plugin/css-bundle/tests/utils.ts
new file mode 100644
index 0000000..0be132b
--- /dev/null
+++ b/sonar-css-plugin/css-bundle/tests/utils.ts
@@ -0,0 +1,36 @@
+import * as http from "http";
+import { Server } from "http";
+import { AddressInfo } from "net";
+
+export function postToServer(
+ data: string,
+ endpoint: string,
+ server: Server
+): Promise {
+ const options = {
+ host: "localhost",
+ port: (server.address()).port,
+ path: endpoint,
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ }
+ };
+
+ return new Promise((resolve, reject) => {
+ let response = "";
+
+ const req = http.request(options, res => {
+ res.on("data", chunk => {
+ response += chunk;
+ });
+
+ res.on("end", () => resolve(response));
+ });
+
+ req.on("error", reject);
+
+ req.write(data);
+ req.end();
+ });
+}
--
cgit v1.2.3