Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2e back #75

Merged
merged 8 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,29 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 15.x
uses: actions/setup-node@v2
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: '15.x'
node-version: '20.x'
- run: npm i
- run: npm run lint
- run: npm run prettier:ci

build:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
typescript_version: [4.x, 5.2.2, latest]

steps:
- uses: actions/checkout@v2
- name: Use Node.js 15.x
uses: actions/setup-node@v2
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: '15.x'
node-version: '20.x'
- run: npm i
- run: npm i -D typescript@${{ matrix.typescript_version }}
- run: npm run build
- run: npm run test
6 changes: 3 additions & 3 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: '14.x'
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- run: npm install
- run: npm run build
Expand Down
3 changes: 3 additions & 0 deletions e2e/fixtures/default-config/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
4 changes: 4 additions & 0 deletions e2e/fixtures/default-config/ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-strict-ignore
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/default-config/strict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
18 changes: 18 additions & 0 deletions e2e/fixtures/default-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018"],
"baseUrl": "./",
"outDir": "./dist",
"strict": false,
"pretty": true,
"esModuleInterop": true,
"noImplicitAny": true,
"plugins": [
{
"name": "typescript-strict-plugin"
}
]
}
}
4 changes: 4 additions & 0 deletions e2e/fixtures/non-root-config/nested/ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-strict-ignore
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/non-root-config/nested/strict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
18 changes: 18 additions & 0 deletions e2e/fixtures/non-root-config/nested/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018"],
"baseUrl": "./",
"outDir": "./dist",
"strict": false,
"pretty": true,
"esModuleInterop": true,
"noImplicitAny": true,
"plugins": [
{
"name": "typescript-strict-plugin"
}
]
}
}
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/.vscode/settings.json
KostkaBrukowa marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/excluded/excluded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/excluded/excluded2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-strict
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/included/included.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/included/included2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
18 changes: 18 additions & 0 deletions e2e/fixtures/path-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018"],
"baseUrl": "./",
"outDir": "./dist",
"strict": false,
"esModuleInterop": true,
"noImplicitAny": true,
"plugins": [
{
"name": "typescript-strict-plugin",
"paths": ["./included"]
}
]
}
}
29 changes: 29 additions & 0 deletions e2e/fixtures/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import path from 'path';

export const fixtureWithDefaultConfig = {
projectPath: path.resolve(__dirname, 'default-config'),
filePaths: {
strict: 'strict.ts',
ignored: 'ignored.ts',
},
};

export const fixtureWithPathConfig = {
projectPath: path.resolve(__dirname, 'path-config'),
filePaths: {
included: 'included/included.ts',
included2: 'included/included2.ts',
excluded: 'excluded/excluded.ts',
excluded2: 'excluded/excluded2.ts',
excludedWithStrictComment: 'excluded/excludedWithStrictComment.ts',
},
};

export const fixtureWithNonRootConfig = {
projectPath: path.resolve(__dirname, 'non-root-config'),
filePaths: {
strict: 'strict.ts',
ignored: 'ignored.ts',
},
args: ['--project', './nested/tsconfig.json'],
};
17 changes: 17 additions & 0 deletions e2e/plugin/multipleFile.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getMultipleDiagnostics } from './utils/getMultipleDiagnostics';
import { fixtureWithDefaultConfig } from '../fixtures/paths';

describe('multiple file diagnostics', () => {
it('should show errors only on file with strict comment', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;
const fileList = [filePaths.strict, filePaths.ignored];

// when
const diagnostics = await getMultipleDiagnostics(projectPath, fileList);

// then
expect(diagnostics[0]).toHaveLength(1);
expect(diagnostics[1]).toHaveLength(0);
});
});
65 changes: 65 additions & 0 deletions e2e/plugin/singleFile.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { getDiagnostics } from './utils/getDiagnostics';
import {
fixtureWithDefaultConfig,
fixtureWithNonRootConfig,
fixtureWithPathConfig,
} from '../fixtures/paths';

describe('single file diagnostics', () => {
it('should enable strict mode by default in project without config', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.strict);

// then
expect(diagnostics).toHaveLength(1);
});

it('should not enable strict mode in ignored file', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.ignored);

// then
expect(diagnostics).toHaveLength(0);
});

it('should not enable strict mode when file is not on path', async () => {
// given
const { projectPath, filePaths } = fixtureWithPathConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.excluded);

// then
expect(diagnostics).toHaveLength(0);
});

it('should enable strict mode when file is not on path and contains strict comment', async () => {
// given
const { projectPath, filePaths } = fixtureWithPathConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.excludedWithStrictComment);

// then
expect(diagnostics).toHaveLength(1);
});

it('should enable strict mode with a relative path config', async () => {
// given
const { projectPath, filePaths } = fixtureWithPathConfig;

// when
const diagnosticsIncluded = await getDiagnostics(projectPath, filePaths.included);
const diagnosticsExcluded = await getDiagnostics(projectPath, filePaths.excluded);

// then
expect(diagnosticsIncluded).toHaveLength(1);
expect(diagnosticsExcluded).toHaveLength(0);
});
});
82 changes: 82 additions & 0 deletions e2e/plugin/utils/TSServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// /* implementation taken from https://github.com/Quramy/ts-graphql-plugin/blob/master/e2e/fixtures/lang-server.js */
import { ChildProcess, fork } from 'child_process';
import { EventEmitter } from 'events';
import path from 'path';

export interface ServerResponse {
command: string;
event: string;
type: string;
body: any;
}

export interface ServerRequest {
command?: string;
event?: string;
type?: string;
arguments: any;
}

export class TSServer {
public responses: ServerResponse[];

private _responseEventEmitter: NodeJS.EventEmitter;
private _responseCommandEmitter: NodeJS.EventEmitter;
private _exitPromise: Promise<string>;
private _isClosed: boolean;
private _server: ChildProcess;
private _seq: number;

constructor(projectPath: string) {
this._responseEventEmitter = new EventEmitter();
this._responseCommandEmitter = new EventEmitter();
const tsserverPath = require.resolve('typescript/lib/tsserver');

const server = fork(tsserverPath, {
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
cwd: projectPath,
// env: { TSS_LOG: '-logToFile true -file ./ts.log -level verbose' }, // creates tsserver log from tests
});
this._exitPromise = new Promise((resolve, reject) => {
server.on('exit', (code: string) => resolve(code));
server.on('error', (reason: string) => reject(reason));
});
server.stdout?.setEncoding('utf-8');
server.stdout?.on('data', (data: string) => {
const [, , res] = data.split('\n');
const obj = JSON.parse(res) as ServerResponse;
if (obj.type === 'event') {
this._responseEventEmitter.emit(obj.event, obj);
} else if (obj.type === 'response') {
this._responseCommandEmitter.emit(obj.command, obj);
}
this.responses.push(obj);
});
this._isClosed = false;
this._server = server;
this._seq = 0;
this.responses = [];
}

send(command: ServerRequest) {
const seq = ++this._seq;
const req = JSON.stringify(Object.assign({ seq: seq, type: 'request' }, command)) + '\n';
this._server.stdin?.write(req);
}

close() {
if (!this._isClosed) {
this._isClosed = true;
this._server.stdin?.end();
}
return this._exitPromise;
}

waitEvent(eventName: string) {
return new Promise((res) => this._responseEventEmitter.once(eventName, () => res(undefined)));
}

waitResponse(eventName: string) {
return new Promise((res) => this._responseCommandEmitter.once(eventName, () => res(undefined)));
}
}
35 changes: 35 additions & 0 deletions e2e/plugin/utils/getDiagnostics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-ignore
import { TSServer, ServerResponse } from './TSServer';
import path, { resolve } from 'path';
import { readFileSync } from 'fs';

function findResponse(responses: ServerResponse[], eventName: string) {
return responses.find((response) => response.event === eventName);
}

export async function getDiagnostics(projectPath: string, filePath: string) {
const server = new TSServer(projectPath);

const file = resolve(projectPath, filePath);

const fileContent = readFileSync(file, 'utf-8');

server.send({
command: 'updateOpen',
arguments: {
openFiles: [{ file: file, fileContent, scriptKindName: 'TS', projectRootPath: projectPath }],
},
});

await server.waitEvent('projectLoadingFinish');

server.send({ command: 'geterr', arguments: { files: [file], delay: 10 } });

await server.waitEvent('semanticDiag');

await server.close();

const semanticDiagEvent = findResponse(server.responses, 'semanticDiag');

return semanticDiagEvent?.body.diagnostics;
}
Loading