Skip to content

Commit

Permalink
Initial smoke for usage of jest (#17)
Browse files Browse the repository at this point in the history
* Initial smoke for usage of jest

* Exclude definition files and helpers

* Allow using Omit

* Isolated modules (for babel typescript)

* Update parser to match typescript version

* Explicitely define type files

* Actual smoke test

* 💥 move file

I don't know why, but vscode complains unless it lives here
  • Loading branch information
SleeplessByte authored Jun 1, 2019
1 parent 8c869f6 commit 86324e4
Show file tree
Hide file tree
Showing 15 changed files with 2,364 additions and 1,394 deletions.
6 changes: 6 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"presets": [
["@babel/preset-env", { "targets": { "node": "current" } } ],
"@babel/preset-typescript",
]
}
File renamed without changes.
20 changes: 20 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
verbose: true,
projects: [
'<rootDir>'
],
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/test/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)"
],
testPathIgnorePatterns: [
'/node_modules/',
'.d.ts$',
'<rootDir>/test/fixtures',
'<rootDir>/test/helpers'
],
transform: {
'^.+\\.[jt]sx?$': 'babel-jest',
},
};
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,24 @@
"analyze:dev": "yarn build && yarn analyze",
"analyze:dev:bat": "yarn build && yarn analyze:bat",
"build": "yarn tsc",
"prepublish": "yarn build",
"test": "ava"
"prepublish": "yarn test",
"test": "yarn build && jest"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/preset-typescript": "^7.3.3",
"@types/jest": "^24.0.13",
"@types/node": "^11.11.6",
"@types/yargs": "^12.0.10",
"ava": "^1.3.1",
"babel-jest": "^24.8.0",
"eslint": "^5.15.3",
"typescript": "^3.3.4000"
"jest": "^24.8.0",
"typescript": "^3.4.5"
},
"dependencies": {
"@typescript-eslint/parser": "^1.5.0",
"@typescript-eslint/typescript-estree": "^1.5.0",
"@typescript-eslint/parser": "^1.9.0",
"@typescript-eslint/typescript-estree": "^1.9.0",
"esm": "^3.2.20",
"yargs": "^13.2.2"
}
Expand Down
4 changes: 2 additions & 2 deletions src/analyzers/base_analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parse as parseToTree, ParserOptions } from '@typescript-eslint/typescript-estree'
import { parse as parseToTree, TSESTreeOptions as ParserOptions } from '@typescript-eslint/typescript-estree'
import { Program } from '@typescript-eslint/typescript-estree/dist/ts-estree/ts-estree'

import { Solution } from '../solution'
Expand Down Expand Up @@ -50,7 +50,7 @@ export abstract class BaseAnalyzer {
*
* @memberof BaseAnalyzer
*/
public readonly run = async (): Promise<AnalyzerOutput> => {
public async run(): Promise<AnalyzerOutput> {
await this.execute()
.catch((err) => {
if (err instanceof EarlyFinalization) {
Expand Down
8 changes: 5 additions & 3 deletions src/analyzers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Solution } from '../solution'

import { get as getLogger } from '../utils/logger'

import path from 'path'

export class Analyzers {

/**
Expand All @@ -29,13 +31,13 @@ export class Analyzers {
}

private static autoload(exercise: Readonly<Exercise>) {
const path = `./${exercise.slug}/index.js` // explicit path
const modulePath = path.join(__dirname, exercise.slug, 'index') // explicit path (no extension)
try {
return require(path)
return require(modulePath)
} catch(err) {
const logger = getLogger()
logger.error(`
Could not find the index.js analyzer in "${__dirname}/${exercise.slug}"
Could not find the index.js analyzer in "${modulePath}"
Make sure that:
- the slug "${exercise.slug}" is valid (hint: use dashes, not underscores)
Expand Down
4 changes: 1 addition & 3 deletions src/analyzers/utils/extract_export.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Program, Node, ExportDefaultDeclaration, ExportNamedDeclaration, ClassDeclaration, VariableDeclaration, ExportDeclaration, ExportSpecifier, AssignmentExpression } from "@typescript-eslint/typescript-estree/dist/ts-estree/ts-estree"
import { AST_NODE_TYPES } from "@typescript-eslint/typescript-estree"
import { traverse, Traverser } from 'eslint/lib/util/traverser'

export { Traverser }
import { traverse } from 'eslint/lib/util/traverser'

export type ExportDeclarationNode = ExportDefaultDeclaration | ExportNamedDeclaration | AssignmentExpression | undefined
export type ExportedNode = ClassDeclaration | VariableDeclaration | ExportDeclaration | ExportSpecifier | undefined
Expand Down
4 changes: 1 addition & 3 deletions src/analyzers/utils/find_all.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Node } from "@typescript-eslint/typescript-estree/dist/ts-estree/ts-estree"
import { traverse, Traverser } from 'eslint/lib/util/traverser'

export { Traverser }

/**
* Find all nodes, traversing from root, that match the given predicate
*
Expand All @@ -25,7 +23,7 @@ export { Traverser }
* @param predicate predicate function that gets the traverse as bound this
* @returns the nodes that return true for the predicate
*/
export function findAll(root: Node, predicate: (this: Traverser , node: Node) => boolean): Node[] {
export function findAll(root: Node, predicate: (this: Traverser, node: Node) => boolean): Node[] {
const results: Node[] = []

traverse(root, {
Expand Down
4 changes: 1 addition & 3 deletions src/analyzers/utils/find_first.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Node } from "@typescript-eslint/typescript-estree/dist/ts-estree/ts-estree"
import { Traverser, traverse } from 'eslint/lib/util/traverser'

export { Traverser }
import { traverse, Traverser } from 'eslint/lib/util/traverser'

/**
* Find the first note (starting at root) that matches the given predicate.
Expand Down
25 changes: 25 additions & 0 deletions test/helpers/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ExecutionOptions } from "../../src/utils/execution_options";
import { Exercise } from "../../src/exercise";
import { set as setGlobalLogger, Logger } from "../../src/utils/logger";
import { BootstrapResult } from "../../dist/utils/bootstrap";

export function bootstrap({ exercise, ...overrides }: { exercise: string } & Partial<ExecutionOptions>): Omit<BootstrapResult, 'solution'> {
const options = new ExecutionOptions({
debug: false,
console: false,
output: '__fake__',
inputDir: '__fake__',
dry: true,
templates: true,
exercise,
...overrides
})

const logger = setGlobalLogger(new Logger(options))

return {
options,
exercise: new Exercise(exercise),
logger
}
}
29 changes: 29 additions & 0 deletions test/helpers/inline-solution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Solution } from "../../src/solution";
import { Exercise } from "../../src/exercise";

export class InlineSolution extends Solution {
/**
* Create a new solution reference
*
* @param rootDir the path to the root directory of the solution
* @param exercise the exercise this solution belongs to
*/
constructor(private readonly solutionFiles: string[], exercise: Exercise) {
super('__fake__', exercise)
}

/**
* Read the solution file(s)
*
* @param n number of files to return
* @returns promise that resolves all the files at once
*/
public async read(n = 1): Promise<Buffer[]> {

return Promise.all(
Object.keys(this.solutionFiles)
.slice(0, n)
.map(name => Buffer.from(this.solutionFiles[name], 'utf8'))
)
}
}
83 changes: 83 additions & 0 deletions test/smoke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Runner } from '../src/runner'
import { Analyzers } from '../src/analyzers'
import { TwoFerAnalyzer } from '../src/analyzers/two-fer'
import { InlineSolution } from './helpers/inline-solution'
import { bootstrap } from './helpers/bootstrap'

const { options, exercise } = bootstrap({ exercise: 'two-fer' })


describe('When running analysis', () => {
it('can approve as optimal', async () => {

const solutionContent = `
export const twoFer = (name = 'you') => {
return \`One for \${name}, one for me.\`;
};
`.trim()

const solution = new InlineSolution([solutionContent], exercise)
const analyzer = new TwoFerAnalyzer(solution)

const output = await Runner.call(analyzer, options);
expect(output.status).toBe('approve_as_optimal');
expect(output.comments.length).toBe(0);
})

it('can approve with comment', async () => {

const solutionContent = `
const twoFer = (name = 'you') => {
return \`One for \${name}, one for me.\`;
};
export { twoFer }
`.trim()

const solution = new InlineSolution([solutionContent], exercise)
const analyzer = new TwoFerAnalyzer(solution)

const output = await Runner.call(analyzer, options);
expect(output.status).toBe('approve_with_comment');
expect(output.comments.length).toBeGreaterThanOrEqual(1);
})

it('can dissapprove with comment', async () => {

const solutionContent = `
export const twoFer = (name) => {
return \`One for \${name || 'you'}, one for me.\`;
};
`.trim()

const solution = new InlineSolution([solutionContent], exercise)
const analyzer = new TwoFerAnalyzer(solution)

const output = await Runner.call(analyzer, options);
expect(output.status).toBe('disapprove_with_comment');
expect(output.comments.length).toBeGreaterThanOrEqual(1);
})

it('can refer to mentor', async () => {

const solutionContent = `
const whomst = 'for'
export const twoFer = (name = 'you') => {
return \`One \${whomst} \${name}, one \${whomst} me.\`;
};
`.trim()

const solution = new InlineSolution([solutionContent], exercise)
const analyzer = new TwoFerAnalyzer(solution)

const output = await Runner.call(analyzer, options);
expect(output.status).toBe('refer_to_mentor');
})
})

describe('When autoloading analyzers', () => {
it('can find an analyzer based on an exercise', () => {
const ActualAnalyzer = Analyzers.find(exercise)
expect(ActualAnalyzer).toBe(TwoFerAnalyzer)
})
})
1 change: 1 addition & 0 deletions test/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
10 changes: 5 additions & 5 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
Expand All @@ -18,7 +18,7 @@
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
Expand Down Expand Up @@ -57,6 +57,6 @@
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"include": ["src"],
"exclude": ["test/solutions"]
"include": ["src", "declarations.d.ts", "types.d.ts"],
"exclude": ["test/fixtures"]
}
Loading

0 comments on commit 86324e4

Please sign in to comment.