Skip to content

Commit

Permalink
v1.3.0 (#472)
Browse files Browse the repository at this point in the history
* feat: Allow disposing server, add first LSP test (#326)

* feat: Allow disposing server, add first LSP test

* test: close connection before finishing

* refactor: use stylelint namespace for custom event

* feat: Add restart server command (#339)

Closes #332

* test: add code actions on save end-to-end test (#341)

* test: add code actions on save end-to-end test

* test:test auto-fix on save after problem actions

Quick hack to hopefully stabilize tests on CI for now

* feat: Warn for old Stylelint regardless of lang ID (#340)

Does not warn if Stylelint was resolved globally, only locally.

* test: await functions that may return promises

* fix: de-nest globs used for watching config files (#356)

* fix: de-nest globs used for watching config files

* test: update extension tests

* docs: update changelog

* fix: ts error (#471)

* feat: Report ranges for diagnostics (#358)

* feat: Report ranges for diagnostics

* update snap

* update changelog

* update stylelint

* Fixes server/modules/formatter tests (#450)

Fix copied from original PR

https://github.com/stylelint/vscode-stylelint/pull/426/files#diff-f2680deb1906c0920d4e4b4f73879a32a741ed4288aabb2a218a2eef48f38211

* update snapshot

* update snapshot

* fix

* fix: test cases

---------

Co-authored-by: yosuke ota <[email protected]>
Co-authored-by: Chema Balsas <[email protected]>

---------

Co-authored-by: Adaline Valentina Simonian <[email protected]>
Co-authored-by: Chema Balsas <[email protected]>
  • Loading branch information
3 people authored Nov 2, 2023
1 parent abcb3a6 commit 1222726
Show file tree
Hide file tree
Showing 57 changed files with 2,628 additions and 1,178 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## [Unreleased]

## [1.2.4](https://github.com/stylelint/vscode-stylelint/compare/v1.2.3...v1.3.0) (2023-02-14)
### Added

- Language server can now be restarted with the "Restart Stylelint Server" command ([#339](https://github.com/stylelint/vscode-stylelint/pull/339)).
- The warning shown for unsupported versions of Stylelint will now be shown in any workspace with a locally installed copy of Stylelint, regardless of the file type of the open file ([#340](https://github.com/stylelint/vscode-stylelint/pull/340)).
- Language server can now be disposed with `server.dispose()` and is disposed when receiving the shutdown LSP notification ([#326](https://github.com/stylelint/vscode-stylelint/pull/326)).
- Add support for range warnings ([#358](https://github.com/stylelint/vscode-stylelint/pull/358)).

### Changed

- A custom notification used for testing in VS Code sent by the language server now uses the `stylelint` namespace instead of `textDocument` ([3b845a2](https://github.com/stylelint/vscode-stylelint/commit/3b845a2)).

### Fixed

- Files are now re-linted when a Stylelint configuration file is changed in the workspace ([#356](https://github.com/stylelint/vscode-stylelint/pull/356)).

## [1.2.4](https://github.com/stylelint/vscode-stylelint/compare/v1.2.3...v1.2.4) (2023-02-14)

### Added

Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,12 @@
"title": "Fix all auto-fixable Problems",
"category": "Stylelint",
"command": "stylelint.executeAutofix"
}
},
{
"title": "Restart Stylelint Server",
"category": "Stylelint",
"command": "stylelint.restart"
}
],
"jsonValidation": [
{
Expand Down
5 changes: 4 additions & 1 deletion src/extension/__tests__/__snapshots__/extension.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ Array [
},
],
"synchronize": Object {
"fileEvents": undefined,
"fileEvents": Array [
undefined,
undefined,
],
},
},
]
Expand Down
142 changes: 110 additions & 32 deletions src/extension/__tests__/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,11 @@ mockVSCode.workspace = mockWorkspace as unknown as typeof vscode.workspace;
mockVSCode.commands = mockCommands as unknown as typeof vscode.commands;
mockVSCode.window = mockWindow as unknown as typeof vscode.window;

const start = jest.fn();
const stop = jest.fn();
const onNotification = jest.fn();
const catchOnReady = jest.fn();
const catchSendRequest = jest.fn();
const afterOnReady = jest.fn().mockReturnValue({ catch: catchOnReady });
const afterSendRequest = jest.fn().mockReturnValue({ catch: catchSendRequest });
const onReady = jest.fn().mockReturnValue({ then: afterOnReady });
const sendRequest = jest.fn().mockReturnValue({ then: afterSendRequest });
const onReady = jest.fn();
const sendRequest = jest.fn();
const settingMonitorStart = jest.fn();

const mockExtensionContext = {
Expand All @@ -80,14 +78,20 @@ const stripPaths = <T extends unknown[]>(params: T): T => {

describe('Extension entry point', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();

mockVSCode.window.activeTextEditor = undefined;

start.mockImplementation(async () => undefined);
onReady.mockImplementation(async () => undefined);
sendRequest.mockImplementation(async () => undefined);

mockLanguageClient.mockReturnValue({
onNotification,
onReady,
sendRequest,
start,
stop,
} as unknown as LanguageClient);

mockSettingMonitor.mockReturnValue({
Expand All @@ -113,10 +117,15 @@ describe('Extension entry point', () => {
it('should watch for changes to Stylelint configuration files', () => {
activate(mockExtensionContext);

expect(mockWorkspace.createFileSystemWatcher).toHaveBeenCalled();
expect(mockWorkspace.createFileSystemWatcher).toHaveBeenCalledTimes(2);
expect(mockWorkspace.createFileSystemWatcher.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"**/{.stylelintrc{,.js,.json,.yaml,.yml},stylelint.config.js,.stylelintignore}",
"**/.stylelintrc{,.js,.json,.yaml,.yml}",
]
`);
expect(mockWorkspace.createFileSystemWatcher.mock.calls[1]).toMatchInlineSnapshot(`
Array [
"**/{stylelint.config.js,.stylelintignore}",
]
`);
});
Expand All @@ -142,42 +151,39 @@ describe('Extension entry point', () => {
expect(subscriptions).toContain(disposable);
});

it('with an active text editor, should send auto-fix commands to the language server', () => {
it('with an active text editor, should send auto-fix commands to the language server', async () => {
window.activeTextEditor = mockTextEditor;

activate(mockExtensionContext);

mockCommands.registerCommand.mock.calls[0][1](undefined);
await mockCommands.registerCommand.mock.calls[0][1](undefined);

expect(sendRequest).toHaveBeenCalledTimes(1);
expect(sendRequest.mock.calls[0]).toMatchSnapshot();
expect(afterSendRequest).toHaveBeenCalledTimes(1);
expect(afterSendRequest.mock.calls[0][0]).toBeUndefined();
expect(mockWindow.showErrorMessage).not.toHaveBeenCalled();
});

it('without an active text editor, should not send auto-fix commands to the language server', () => {
it('without an active text editor, should not send auto-fix commands to the language server', async () => {
window.activeTextEditor = undefined;

activate(mockExtensionContext);

mockCommands.registerCommand.mock.calls[0][1](undefined);
await mockCommands.registerCommand.mock.calls[0][1](undefined);

expect(sendRequest).not.toHaveBeenCalled();
expect(afterSendRequest).not.toHaveBeenCalled();
expect(mockWindow.showErrorMessage).not.toHaveBeenCalled();
});

it('should show an error message if sending the command request fails', () => {
it('should show an error message if sending the command request fails', async () => {
window.activeTextEditor = mockTextEditor;

activate(mockExtensionContext);

mockCommands.registerCommand.mock.calls[0][1](undefined);
afterSendRequest.mock.calls[0][1](undefined, new Error());
sendRequest.mockRejectedValueOnce(new Error('mock error'));

await mockCommands.registerCommand.mock.calls[0][1](undefined);

expect(sendRequest).toHaveBeenCalledTimes(1);
expect(afterSendRequest).toHaveBeenCalledTimes(1);
expect(mockWindow.showErrorMessage).toHaveBeenCalledTimes(1);
expect(mockWindow.showErrorMessage.mock.calls[0]).toMatchInlineSnapshot(`
Array [
Expand All @@ -186,6 +192,34 @@ describe('Extension entry point', () => {
`);
});

it('should register a restart server command', () => {
const disposable = { dispose: () => undefined };

mockCommands.registerCommand.mockReturnValue(disposable);

activate(mockExtensionContext);

const { subscriptions } = mockExtensionContext;

expect(mockCommands.registerCommand).toHaveBeenCalled();
expect(mockCommands.registerCommand.mock.calls[1]).toMatchInlineSnapshot(`
Array [
"stylelint.restart",
[Function],
]
`);
expect(subscriptions).toContain(disposable);
});

it('should restart the language server', async () => {
activate(mockExtensionContext);

await mockCommands.registerCommand.mock.calls[1][1]();

expect(stop).toHaveBeenCalled();
expect(start).toHaveBeenCalled();
});

it('should monitor settings', () => {
const disposable = { dispose: () => undefined };

Expand All @@ -204,10 +238,10 @@ describe('Extension entry point', () => {
expect(subscriptions).toContain(disposable);
});

it('should listen for the DidRegisterCodeActionRequestHandler notification', () => {
it('should listen for the DidRegisterCodeActionRequestHandler notification', async () => {
activate(mockExtensionContext);

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

expect(onReady).toHaveBeenCalled();
expect(onNotification).toHaveBeenCalled();
Expand All @@ -218,16 +252,17 @@ describe('Extension entry point', () => {
it('should set codeActionReady to true when the DidRegisterCodeActionRequestHandler notification is received', async () => {
const api = activate(mockExtensionContext);

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

onNotification.mock.calls[0][1]();

expect(api.codeActionReady).toBe(true);
});

it('should listen for the DidRegisterDocumentFormattingEditProvider notification', () => {
it('should listen for the DidRegisterDocumentFormattingEditProvider notification', async () => {
activate(mockExtensionContext);

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

expect(onReady).toHaveBeenCalled();
expect(onNotification).toHaveBeenCalled();
Expand All @@ -253,16 +288,17 @@ describe('Extension entry point', () => {
},
};

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

onNotification.mock.calls[1][1](params);

await expect(promise).resolves.toStrictEqual(params);
});

it('should listen for the DidResetConfiguration notification', () => {
it('should listen for the DidResetConfiguration notification', async () => {
activate(mockExtensionContext);

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

expect(onReady).toHaveBeenCalled();
expect(onNotification).toHaveBeenCalled();
Expand All @@ -277,17 +313,59 @@ describe('Extension entry point', () => {
api.on(ApiEvent.DidResetConfiguration, resolve);
});

afterOnReady.mock.calls[0][0]();
await new Promise((resolve) => setImmediate(resolve));

onNotification.mock.calls[2][1]();

await expect(promise).resolves.toBeUndefined();
});

it('should show an error message if the DidRegisterDocumentFormattingEditProvider notification fails', async () => {
it('should show an error message if registering notifications fails', async () => {
onNotification.mockImplementation((): void => {
throw new Error('Problem!');
});

activate(mockExtensionContext);

await new Promise((resolve) => setImmediate(resolve));

onNotification.mockImplementation((): void => {
throw 'String problem!';
});

activate(mockExtensionContext);

await new Promise((resolve) => setImmediate(resolve));

expect(mockWindow.showErrorMessage).toHaveBeenCalledTimes(2);
expect(mockWindow.showErrorMessage.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"Stylelint: Problem!",
]
`);
expect(mockWindow.showErrorMessage.mock.calls[1]).toMatchInlineSnapshot(`
Array [
"Stylelint: String problem!",
]
`);
});

it('should show an error message if restarting the language server fails', async () => {
activate(mockExtensionContext);

await catchOnReady.mock.calls[0][0](new Error('Problem!'));
await catchOnReady.mock.calls[0][0]('String problem!');
await new Promise((resolve) => setImmediate(resolve));

onReady.mockImplementation((): void => {
throw new Error('Problem!');
});

await mockCommands.registerCommand.mock.calls[1][1]();

onReady.mockImplementation((): void => {
throw 'String problem!';
});

await mockCommands.registerCommand.mock.calls[1][1]();

expect(mockWindow.showErrorMessage).toHaveBeenCalledTimes(2);
expect(mockWindow.showErrorMessage.mock.calls[0]).toMatchInlineSnapshot(`
Expand Down
Loading

0 comments on commit 1222726

Please sign in to comment.