Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Hanson committed Apr 6, 2017
1 parent 9b6e8a4 commit 8696ac9
Show file tree
Hide file tree
Showing 53 changed files with 302 additions and 35 deletions.
1 change: 0 additions & 1 deletion .gitignore
@@ -1,4 +1,3 @@
.vscode
bin
node_modules
typescript-installs
13 changes: 13 additions & 0 deletions .vscode/launch.json
@@ -0,0 +1,13 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/test/test.js",
"outFiles": ["${workspaceRoot}/bin"]
}
]
}
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -20,7 +20,8 @@
"scripts": {
"watch": "tsc --watch",
"build": "tsc",
"lint": "tslint --project tsconfig.json --type-check --format stylish"
"lint": "tslint --project tsconfig.json --type-check --format stylish",
"test": "node test/test.js"
},
"dependencies": {
"fs-promise": "^2.0.0",
Expand Down
6 changes: 5 additions & 1 deletion src/index.ts
Expand Up @@ -129,7 +129,11 @@ async function test(dirPath: string, options: Options, version: TypeScriptVersio
export interface TestError { message: string; }
async function testWithVersion(dirPath: string, options: Options, version: TypeScriptVersion | "next"): Promise<TestError | undefined> {
async function testWithVersion(
dirPath: string,
options: Options,
version: TypeScriptVersion | "next",
): Promise<TestError | undefined> {
await install(version);
if (options.noLint) {
// Special for old DefinitelyTyped packages that aren't linted yet.
Expand Down
6 changes: 5 additions & 1 deletion src/lint.ts
Expand Up @@ -32,7 +32,11 @@ export async function lintWithVersion(
return result.failures.length ? { message: result.output } : undefined;
}

async function getLintConfig(configuration: Configuration, configPath: string, options: Options): Promise<IConfigurationFile> {
async function getLintConfig(
configuration: Configuration,
configPath: string,
options: Options,
): Promise<IConfigurationFile> {
if (!await exists(configPath)) {
if (options.dt) {
throw new Error('On DefinitelyTyped, must include `tslint.json` containing `{ "extends": "../tslint.json" }`');
Expand Down
6 changes: 3 additions & 3 deletions src/rules/noBadReferenceRule.ts
Expand Up @@ -14,7 +14,7 @@ export class Rule extends Lint.Rules.AbstractRule {
static FAILURE_STRING =
"Don't use <reference path> to reference another package. Use an import or <reference types> instead.";
static FAILURE_STRING_REFERENCE_IN_TEST =
"Don't use <reference path> in test files. Use <reference types> or include the file in 'tsconfig.json'";
"Don't use <reference path> in test files. Use <reference types> or include the file in 'tsconfig.json'.";

apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
Expand All @@ -26,10 +26,10 @@ function walk(ctx: Lint.WalkContext<void>): void {
for (const ref of sourceFile.referencedFiles) {
if (sourceFile.isDeclarationFile) {
if (ref.fileName.startsWith("..")) {
ctx.addFailureAt(ref.pos, ref.end, Rule.FAILURE_STRING);
ctx.addFailure(ref.pos, ref.end, Rule.FAILURE_STRING);
}
} else {
ctx.addFailureAt(ref.pos, ref.end, Rule.FAILURE_STRING_REFERENCE_IN_TEST);
ctx.addFailure(ref.pos, ref.end, Rule.FAILURE_STRING_REFERENCE_IN_TEST);
}
}
}
22 changes: 15 additions & 7 deletions src/rules/noDeadReferenceRule.ts
Expand Up @@ -20,18 +20,26 @@ export class Rule extends Lint.Rules.AbstractRule {
}

function walk(ctx: Lint.WalkContext<void>): void {
const { sourceFile } = ctx;
if (!sourceFile.statements.length) {
const { sourceFile: { statements, text } } = ctx;
if (!statements.length) {
return;
}

// 'm' flag makes it multiline, so `^` matches the beginning of any line.
// 'g' flag lets us set rgx.lastIndex
const rgx = /^\s*\/\/\/ <reference/mg;
const rgx = /^\s*(\/\/\/ <reference)/mg;

// Start search at the first statement. (`/// <reference>` before that is OK.)
rgx.lastIndex = sourceFile.statements[0].getStart();
const match = rgx.exec(sourceFile.text);
if (match !== null) {
ctx.addFailureAt(match.index, 0, Rule.FAILURE_STRING);
rgx.lastIndex = statements[0].getStart();

while (true) {
const match = rgx.exec(text);
if (match === null) {
break;
}

const length = match[1].length;
const start = match.index + match[0].length - length;
ctx.addFailureAt(start, length, Rule.FAILURE_STRING);
}
}
2 changes: 1 addition & 1 deletion src/rules/noPaddingRule.ts
Expand Up @@ -2,7 +2,7 @@ import * as Lint from "tslint";
import * as ts from "typescript";

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-padding",
description: "Forbids unnecessary 'export' or 'declare' modifiers in declaration files.",
optionsDescription: "Not configurable.",
Expand Down
8 changes: 5 additions & 3 deletions src/rules/noRedundantModifiersRule.ts
Expand Up @@ -2,7 +2,7 @@ import * as Lint from "tslint";
import * as ts from "typescript";

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-redundant-modifiers",
description: "Forbids unnecessary 'export' or 'declare' modifiers in declaration files.",
optionsDescription: "Not configurable.",
Expand Down Expand Up @@ -37,8 +37,10 @@ function walk(ctx: Lint.WalkContext<void>): void {
// Types do not need 'declare'.
switch (node.kind) {
case ts.SyntaxKind.InterfaceDeclaration:
case ts.SyntaxKind.TypeAliasDeclaration:
ctx.addFailureAtNode(node, "'declare' keyword is redundant here.");
case ts.SyntaxKind.TypeAliasDeclaration: {
const { name } = node as ts.TypeAliasDeclaration | ts.InterfaceDeclaration;
ctx.addFailureAtNode(name, "'declare' keyword is redundant here.");
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/rules/noRelativeImportInTestRule.ts
Expand Up @@ -2,7 +2,7 @@ import * as Lint from "tslint";
import * as ts from "typescript";

export class Rule extends Lint.Rules.TypedRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-relative-import-in-test",
description: "Forbids test (non-declaration) files to use relative imports.",
optionsDescription: "Not configurable.",
Expand Down
6 changes: 3 additions & 3 deletions src/rules/noUselessFilesRule.ts
Expand Up @@ -5,7 +5,7 @@ import * as ts from "typescript";
// Remove when that PR is in.

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-useless-files",
description: "Forbids files with no content.",
optionsDescription: "Not configurable.",
Expand All @@ -14,9 +14,9 @@ export class Rule extends Lint.Rules.AbstractRule {
typescriptOnly: false,
};

public static FAILURE_STRING = "File has no content.";
static FAILURE_STRING = "File has no content.";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
if (sourceFile.statements.length) {
return [];
}
Expand Down
6 changes: 3 additions & 3 deletions src/rules/noVarRule.ts
Expand Up @@ -4,7 +4,7 @@ import * as ts from "typescript";
// TODO: pull request to update tslint's `no-var-keyword`

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "no-var",
description: "Forbids 'var'.",
optionsDescription: "Not configurable.",
Expand All @@ -13,9 +13,9 @@ export class Rule extends Lint.Rules.AbstractRule {
typescriptOnly: false,
};

public static FAILURE_STRING = "Do not use 'var'.";
static FAILURE_STRING = "Do not use 'var'.";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/rules/preferDeclareFunctionRule.ts
Expand Up @@ -2,7 +2,7 @@ import * as Lint from "tslint";
import * as ts from "typescript";

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "prefer-declare-function",
description: "Forbids `export const x = () => void`.",
optionsDescription: "Not configurable.",
Expand All @@ -11,9 +11,9 @@ export class Rule extends Lint.Rules.AbstractRule {
typescriptOnly: true,
};

public static FAILURE_STRING = "Use a function declaration instead of a variable of function type.";
static FAILURE_STRING = "Use a function declaration instead of a variable of function type.";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/rules/trimFileRule.ts
Expand Up @@ -2,7 +2,7 @@ import * as Lint from "tslint";
import * as ts from "typescript";

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
static metadata: Lint.IRuleMetadata = {
ruleName: "trim-file",
description: "Forbids leading/trailing blank lines in a file. Allows file to end in '\n'.",
optionsDescription: "Not configurable.",
Expand All @@ -11,10 +11,11 @@ export class Rule extends Lint.Rules.AbstractRule {
typescriptOnly: false,
};

public static FAILURE_STRING_LEADING = "File should not begin with a blank line.";
public static FAILURE_STRING_TRAILING = "File should not end with a blank line. (Ending in '\\n' OK, ending in '\\n\\n' not OK.)";
static FAILURE_STRING_LEADING = "File should not begin with a blank line.";
static FAILURE_STRING_TRAILING =
"File should not end with a blank line. (Ending in '\\n' OK, ending in '\\n\\n' not OK.)";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
Expand All @@ -26,6 +27,6 @@ function walk(ctx: Lint.WalkContext<void>): void {
}

if (text.endsWith("\n\n") || text.endsWith("\r\n\r\n")) {
ctx.addFailureAt(text.length - 1, 1, Rule.FAILURE_STRING_TRAILING);
ctx.addFailureAt(text.length - 2, 1, Rule.FAILURE_STRING_TRAILING);
}
}
4 changes: 4 additions & 0 deletions test/dt-header/correct/index.d.ts.lint
@@ -0,0 +1,4 @@
// Type definitions for dt-header 1.0
// Project: https://github.com/bobby-headers/dt-header
// Definitions by: Jane Doe <https://github.com/janedoe>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Empty file.
5 changes: 5 additions & 0 deletions test/dt-header/correct/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"dt-header": true
}
}
5 changes: 5 additions & 0 deletions test/dt-header/wrong/index.d.ts.lint
@@ -0,0 +1,5 @@
// Type definitions for dt-header v1.0.3
~ [Error parsing header. Expected: foo MAJOR.MINOR (patch version not allowed)]
// Project: https://github.com/bobby-headers/dt-header
// Definitions by: Jane Doe <https://github.com/janedoe>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
2 changes: 2 additions & 0 deletions test/dt-header/wrong/notIndex.d.ts.lint
@@ -0,0 +1,2 @@
// Type definitions for
~~~~~~~~~~~~~~~~~~~~~~~ [Header should only be in `index.d.ts`.]
5 changes: 5 additions & 0 deletions test/dt-header/wrong/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"dt-header": true
}
}
5 changes: 5 additions & 0 deletions test/export-just-namespace/ok.d.ts.lint
@@ -0,0 +1,5 @@
namespace N {
export const x: number;
}
function N(): void;
export = N;
5 changes: 5 additions & 0 deletions test/export-just-namespace/test.d.ts.lint
@@ -0,0 +1,5 @@
namespace N {
export const x: number;
}
export = N;
~~~~~~~~~~~ [Instead of `export =`-ing a namespace, use the body of the namespace as the module body.]
5 changes: 5 additions & 0 deletions test/export-just-namespace/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"export-just-namespace": true
}
}
4 changes: 4 additions & 0 deletions test/no-bad-reference/decl.d.ts.lint
@@ -0,0 +1,4 @@
/// <reference path="../foo" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Don't use <reference path> to reference another package. Use an import or <reference types> instead.]

/// <reference path="foo" />
7 changes: 7 additions & 0 deletions test/no-bad-reference/test.ts.lint
@@ -0,0 +1,7 @@
/// <reference path="../foo" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [0]

/// <reference path="foo" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [0]

[0]: Don't use <reference path> in test files. Use <reference types> or include the file in 'tsconfig.json'.
5 changes: 5 additions & 0 deletions test/no-bad-reference/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"no-bad-reference": true
}
}
8 changes: 8 additions & 0 deletions test/no-dead-reference/test.ts.lint
@@ -0,0 +1,8 @@
/// <reference types="foo" />
import * as bar from "bar";
/// <reference path="baz" />
~~~~~~~~~~~~~~ [0]
/// <reference types="bang" />
~~~~~~~~~~~~~~ [0]

[0]: `/// <reference>` directive must be at top of file to take effect.
5 changes: 5 additions & 0 deletions test/no-dead-reference/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"no-dead-reference": true
}
}
27 changes: 27 additions & 0 deletions test/no-padding/test.ts.lint
@@ -0,0 +1,27 @@
function f() {
~ [Don't leave a blank line after '{']

return [
~ [Don't leave a blank line after '[']

f(
~ [Don't leave a blank line after '(']

0

)
~ [Don't leave a blank line before ')']

];
~ [Don't leave a blank line before ']']

}
~ [Don't leave a blank line before '}']

function f() {
return [
f(
0
)
];
}
5 changes: 5 additions & 0 deletions test/no-padding/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"no-padding": true
}
}
11 changes: 11 additions & 0 deletions test/no-redundant-modifiers/testAmbient.d.ts.lint
@@ -0,0 +1,11 @@
declare function f(): void;

declare module "m" {}

declare type T = number;
~ [0]

declare interface I {}
~ [0]

[0]: 'declare' keyword is redundant here.
11 changes: 11 additions & 0 deletions test/no-redundant-modifiers/testModule.d.ts.lint
@@ -0,0 +1,11 @@
export declare function f(): void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ['export declare' is redundant, just use 'export'.]

declare function g(): void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Prefer 'export' to 'declare' in an external module.]

export namespace N {
export function f(): void;
~~~~~~~~~~~~~~~~~~~~~~~~~~ ['export' keyword is redundant here.]
// TS compiler warns for 'declare' here.
}
5 changes: 5 additions & 0 deletions test/no-redundant-modifiers/tslint.json
@@ -0,0 +1,5 @@
{
"rules": {
"no-redundant-modifiers": true
}
}
1 change: 1 addition & 0 deletions test/no-relative-import-in-test/decl.d.ts.lint
@@ -0,0 +1 @@
import { x } from "./declarationFile.d";
1 change: 1 addition & 0 deletions test/no-relative-import-in-test/declarationFile.d.ts
@@ -0,0 +1 @@
export const x: number;
5 changes: 5 additions & 0 deletions test/no-relative-import-in-test/test.ts.lint
@@ -0,0 +1,5 @@
import { x } from "./declarationFile.d";
~~~~~~~~~~~~~~~~~~~~~ [0]
import { y } from "./testFile";

[0]: Test file should not use a relative import. Use a global import as if this were a user of the package.

0 comments on commit 8696ac9

Please sign in to comment.