ava 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/types/make.js ADDED
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ // TypeScript definitions are generated here.
4
+ // AVA allows chaining of function names, like `test.after.cb.always`.
5
+ // The order of these names is not important.
6
+ // Writing these definitions by hand is hard. Because of chaining,
7
+ // the number of combinations grows fast (2^n). To reduce this number,
8
+ // illegal combinations are filtered out in `verify`.
9
+ // The order of the options is not important. We could generate full
10
+ // definitions for each possible order, but that would give a very big
11
+ // output. Instead, we write an alias for different orders. For instance,
12
+ // `after.cb` is fully written, and `cb.after` is emitted as an alias
13
+ // using `typeof after.cb`.
14
+
15
+ const path = require('path');
16
+ const fs = require('fs');
17
+ const runner = require('../lib/runner');
18
+
19
+ const arrayHas = parts => part => parts.includes(part);
20
+
21
+ const base = fs.readFileSync(path.join(__dirname, 'base.d.ts'), 'utf8');
22
+
23
+ // All suported function names
24
+ const allParts = Object.keys(runner._chainableMethods).filter(name => name !== 'test');
25
+
26
+ const output = base + generatePrefixed([]);
27
+ fs.writeFileSync(path.join(__dirname, 'generated.d.ts'), output);
28
+
29
+ // Generates type definitions, for the specified prefix
30
+ // The prefix is an array of function names
31
+ function generatePrefixed(prefix) {
32
+ let output = '';
33
+ let children = '';
34
+
35
+ for (const part of allParts) {
36
+ const parts = prefix.concat([part]);
37
+
38
+ if (prefix.includes(part) || !verify(parts, true)) {
39
+ // Function already in prefix or not allowed here
40
+ continue;
41
+ }
42
+
43
+ // If `parts` is not sorted, we alias it to the sorted chain.
44
+ if (!isSorted(parts)) {
45
+ const chain = parts.sort().join('.');
46
+ if (exists(parts)) {
47
+ output += '\texport const ' + part + ': typeof test.' + chain + ';\n';
48
+ }
49
+ continue;
50
+ }
51
+
52
+ // Check that `part` is a valid function name.
53
+ // `always` is a valid prefix, for instance of `always.after`,
54
+ // but not a valid function name.
55
+ if (verify(parts, false)) {
56
+ if (prefix.includes(parts, 'todo')) {
57
+ output += '\t' + writeFunction(part, 'name: string', 'void');
58
+ } else {
59
+ const type = testType(parts);
60
+ output += '\t' + writeFunction(part, 'name: string, implementation: ' + type);
61
+ output += '\t' + writeFunction(part, 'implementation: ' + type);
62
+ output += '\t' + writeFunction(part, 'name: string, implementation: Macros<' + type + 'Context>, ...args: any[]');
63
+ output += '\t' + writeFunction(part, 'implementation: Macros<' + type + 'Context>, ...args: any[]');
64
+ }
65
+ }
66
+
67
+ children += generatePrefixed(parts);
68
+ }
69
+
70
+ if (output === '') {
71
+ return children;
72
+ }
73
+
74
+ return 'export namespace ' + ['test'].concat(prefix).join('.') + ' {\n' + output + '}\n' + children;
75
+ }
76
+
77
+ function writeFunction(name, args) {
78
+ return 'export function ' + name + '(' + args + '): void;\n';
79
+ }
80
+
81
+ // Checks whether a chain is a valid function name (when `asPrefix === false`)
82
+ // or a valid prefix that could contain members.
83
+ // For instance, `test.always` is not a valid function name, but it is a valid
84
+ // prefix of `test.always.after`.
85
+ function verify(parts, asPrefix) {
86
+ const has = arrayHas(parts);
87
+
88
+ if (has('only') + has('skip') + has('todo') > 1) {
89
+ return false;
90
+ }
91
+
92
+ const beforeAfterCount = has('before') + has('beforeEach') + has('after') + has('afterEach');
93
+
94
+ if (beforeAfterCount > 1) {
95
+ return false;
96
+ }
97
+
98
+ if (beforeAfterCount === 1) {
99
+ if (has('only')) {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ if (has('always')) {
105
+ // `always` can only be used with `after` or `afterEach`.
106
+ // Without it can still be a valid prefix
107
+ if (has('after') || has('afterEach')) {
108
+ return true;
109
+ }
110
+ if (!verify(parts.concat(['after']), false) && !verify(parts.concat(['afterEach']), false)) {
111
+ // If `after` nor `afterEach` cannot be added to this prefix,
112
+ // `always` is not allowed here.
113
+ return false;
114
+ }
115
+ // Only allowed as a prefix
116
+ return asPrefix;
117
+ }
118
+
119
+ return true;
120
+ }
121
+
122
+ // Checks whether a chain is a valid function name or a valid prefix with some member
123
+ function exists(parts) {
124
+ if (verify(parts, false)) {
125
+ // valid function name
126
+ return true;
127
+ }
128
+ if (!verify(parts, true)) {
129
+ // not valid prefix
130
+ return false;
131
+ }
132
+ // valid prefix, check whether it has members
133
+ for (const prefix of allParts) {
134
+ if (!parts.includes(prefix) && exists(parts.concat([prefix]))) {
135
+ return true;
136
+ }
137
+ }
138
+ return false;
139
+ }
140
+
141
+ // Checks that an array is sorted
142
+ function isSorted(a) {
143
+ for (let i = 1; i < a.length; i++) {
144
+ if (a[i - 1] >= a[i]) {
145
+ return false;
146
+ }
147
+ }
148
+
149
+ return true;
150
+ }
151
+
152
+ // Returns the type name of for the test implementation
153
+ function testType(parts) {
154
+ const has = arrayHas(parts);
155
+ let type = 'Test';
156
+
157
+ if (has('cb')) {
158
+ type = 'Callback' + type;
159
+ }
160
+
161
+ if (!has('before') && !has('after')) {
162
+ type = 'Contextual' + type;
163
+ }
164
+
165
+ return type;
166
+ }
package/index.d.ts DELETED
@@ -1,206 +0,0 @@
1
- export interface Observable {
2
- subscribe(observer: (value: {}) => void): void;
3
- }
4
-
5
- export type Test = (t: TestContext) => Promise<void> | Iterator<any> | Observable | void;
6
- export type ContextualTest = (t: ContextualTestContext) => Promise<void> | Iterator<any> | Observable | void;
7
- export type SerialTest = (t: TestContext) => void;
8
- export type ContextualSerialTest = (t: ContextualTestContext) => void;
9
- export type CallbackTest = (t: CallbackTestContext) => void;
10
- export type ContextualCallbackTest = (t: ContextualCallbackTestContext) => void;
11
-
12
- export interface Runner {
13
- (name: string, run: Test): void;
14
- (run: Test): void;
15
- skip: Runner;
16
- cb: CallbackRunner;
17
- }
18
- export interface ContextualRunner {
19
- (name: string, run: ContextualTest): void;
20
- (run: ContextualTest): void;
21
- skip: ContextualRunner;
22
- cb: ContextualCallbackRunner;
23
- }
24
- export interface SerialRunner {
25
- (name: string, run: SerialTest): void;
26
- (run: SerialTest): void;
27
- skip: SerialRunner;
28
- }
29
- export interface ContextualSerialRunner {
30
- (name: string, run: ContextualSerialTest): void;
31
- (run: ContextualSerialTest): void;
32
- skip: ContextualSerialRunner;
33
- }
34
- export interface CallbackRunner {
35
- (name: string, run: CallbackTest): void;
36
- (run: CallbackTest): void;
37
- skip: CallbackRunner;
38
- }
39
- export interface ContextualCallbackRunner {
40
- (name: string, run: ContextualCallbackTest): void;
41
- (run: ContextualCallbackTest): void;
42
- skip: ContextualCallbackRunner;
43
- }
44
-
45
- export function test(name: string, run: ContextualTest): void;
46
- export function test(run: ContextualTest): void;
47
- export namespace test {
48
- export const before: Runner;
49
- export const after: Runner;
50
- export const beforeEach: ContextualRunner;
51
- export const afterEach: ContextualRunner;
52
-
53
- export const skip: typeof test;
54
- export const only: typeof test;
55
-
56
- export function serial(name: string, run: ContextualSerialTest): void;
57
- export function serial(run: ContextualSerialTest): void;
58
- export function failing(name: string, run: ContextualCallbackTest): void;
59
- export function failing(run: ContextualCallbackTest): void;
60
- export function cb(name: string, run: ContextualCallbackTest): void;
61
- export function cb(run: ContextualCallbackTest): void;
62
- export function todo(name: string): void;
63
- }
64
- export namespace test.serial {
65
- export const before: SerialRunner;
66
- export const after: SerialRunner;
67
- export const beforeEach: ContextualSerialRunner;
68
- export const afterEach: ContextualSerialRunner;
69
-
70
- export const skip: typeof test.serial;
71
- export const only: typeof test.serial;
72
-
73
- export function cb(name: string, run: ContextualCallbackTest): void;
74
- export function cb(run: ContextualCallbackTest): void;
75
- }
76
- export namespace test.failing {
77
- export const before: CallbackRunner;
78
- export const after: CallbackRunner;
79
- export const beforeEach: ContextualCallbackRunner;
80
- export const afterEach: ContextualCallbackRunner;
81
-
82
- export const skip: typeof test.cb;
83
- export const only: typeof test.cb;
84
-
85
- export function cb(name: string, run: ContextualCallbackTest): void;
86
- export function cb(run: ContextualCallbackTest): void;
87
- }
88
- export namespace test.cb {
89
- export const before: CallbackRunner;
90
- export const after: CallbackRunner;
91
- export const beforeEach: ContextualCallbackRunner;
92
- export const afterEach: ContextualCallbackRunner;
93
-
94
- export const skip: typeof test.cb;
95
- export const only: typeof test.cb;
96
- }
97
- export default test;
98
-
99
- export type ErrorValidator
100
- = (new (...args: any[]) => any)
101
- | RegExp
102
- | string
103
- | ((error: any) => boolean);
104
-
105
- export interface AssertContext {
106
- /**
107
- * Passing assertion.
108
- */
109
- pass(message?: string): void;
110
- /**
111
- * Failing assertion.
112
- */
113
- fail(message?: string): void;
114
- /**
115
- * Assert that value is truthy.
116
- */
117
- truthy(value: any, message?: string): void;
118
- /**
119
- * Assert that value is falsy.
120
- */
121
- falsy(value: any, message?: string): void;
122
- /**
123
- * DEPRECATED, use `truthy`. Assert that value is truthy.
124
- */
125
- ok(value: any, message?: string): void;
126
- /**
127
- * DEPRECATED, use `falsy`. Assert that value is falsy.
128
- */
129
- notOk(value: any, message?: string): void;
130
- /**
131
- * Assert that value is true.
132
- */
133
- true(value: boolean, message?: string): void;
134
- /**
135
- * Assert that value is false.
136
- */
137
- false(value: boolean, message?: string): void;
138
- /**
139
- * Assert that value is equal to expected.
140
- */
141
- is<U>(value: U, expected: U, message?: string): void;
142
- /**
143
- * Assert that value is not equal to expected.
144
- */
145
- not<U>(value: U, expected: U, message?: string): void;
146
- /**
147
- * Assert that value is deep equal to expected.
148
- */
149
- deepEqual<U>(value: U, expected: U, message?: string): void;
150
- /**
151
- * Assert that value is not deep equal to expected.
152
- */
153
- notDeepEqual<U>(value: U, expected: U, message?: string): void;
154
- /**
155
- * Assert that function throws an error or promise rejects.
156
- * @param error Can be a constructor, regex, error message or validation function.
157
- */
158
- /**
159
- * DEPRECATED, use `deepEqual`. Assert that value is deep equal to expected.
160
- */
161
- same<U>(value: U, expected: U, message?: string): void;
162
- /**
163
- * DEPRECATED use `notDeepEqual`. Assert that value is not deep equal to expected.
164
- */
165
- notSame<U>(value: U, expected: U, message?: string): void;
166
- /**
167
- * Assert that function throws an error or promise rejects.
168
- * @param error Can be a constructor, regex, error message or validation function.
169
- */
170
- throws(value: Promise<{}>, error?: ErrorValidator, message?: string): Promise<any>;
171
- throws(value: () => void, error?: ErrorValidator, message?: string): any;
172
- /**
173
- * Assert that function doesn't throw an error or promise resolves.
174
- */
175
- notThrows<U>(value: Promise<U>, message?: string): Promise<U>;
176
- notThrows(value: () => void, message?: string): void;
177
- /**
178
- * Assert that contents matches regex.
179
- */
180
- regex(contents: string, regex: RegExp, message?: string): void;
181
- /**
182
- * Assert that error is falsy.
183
- */
184
- ifError(error: any, message?: string): void;
185
- }
186
- export interface TestContext extends AssertContext {
187
- /**
188
- * Plan how many assertion there are in the test.
189
- * The test will fail if the actual assertion count doesn't match planned assertions.
190
- */
191
- plan(count: number): void;
192
-
193
- skip: AssertContext;
194
- }
195
- export interface CallbackTestContext extends TestContext {
196
- /**
197
- * End the test.
198
- */
199
- end(): void;
200
- }
201
- export interface ContextualTestContext extends TestContext {
202
- context: any;
203
- }
204
- export interface ContextualCallbackTestContext extends CallbackTestContext {
205
- context: any;
206
- }
package/lib/ava-files.js DELETED
@@ -1,262 +0,0 @@
1
- var fs = require('fs');
2
- var path = require('path');
3
- var Promise = require('bluebird');
4
- var slash = require('slash');
5
- var globby = require('globby');
6
- var flatten = require('arr-flatten');
7
- var defaultIgnore = require('ignore-by-default').directories();
8
- var multimatch = require('multimatch');
9
-
10
- function defaultExcludePatterns() {
11
- return [
12
- '!**/node_modules/**',
13
- '!**/fixtures/**',
14
- '!**/helpers/**'
15
- ];
16
- }
17
-
18
- function defaultIncludePatterns() {
19
- return [
20
- 'test.js',
21
- 'test-*.js',
22
- 'test',
23
- '**/__tests__',
24
- '**/*.test.js'
25
- ];
26
- }
27
-
28
- function AvaFiles(files, sources) {
29
- if (!(this instanceof AvaFiles)) {
30
- throw new TypeError('Class constructor AvaFiles cannot be invoked without \'new\'');
31
- }
32
-
33
- if (!files || !files.length) {
34
- files = defaultIncludePatterns();
35
- }
36
-
37
- this.excludePatterns = defaultExcludePatterns();
38
-
39
- this.files = files;
40
- this.sources = sources || [];
41
- }
42
-
43
- AvaFiles.prototype.findTestFiles = function () {
44
- return handlePaths(this.files, this.excludePatterns, {
45
- cache: Object.create(null),
46
- statCache: Object.create(null),
47
- realpathCache: Object.create(null),
48
- symlinks: Object.create(null)
49
- });
50
- };
51
-
52
- function getDefaultIgnorePatterns() {
53
- return defaultIgnore.map(function (dir) {
54
- return dir + '/**/*';
55
- });
56
- }
57
-
58
- // Used on paths before they're passed to multimatch to harmonize matching
59
- // across platforms.
60
- var matchable = process.platform === 'win32' ? slash : function (path) {
61
- return path;
62
- };
63
-
64
- AvaFiles.prototype.makeSourceMatcher = function () {
65
- var mixedPatterns = [];
66
- var defaultIgnorePatterns = getDefaultIgnorePatterns();
67
- var overrideDefaultIgnorePatterns = [];
68
-
69
- var hasPositivePattern = false;
70
- this.sources.forEach(function (pattern) {
71
- mixedPatterns.push(pattern);
72
- // TODO: why not just pattern[0] !== '!'
73
- if (!hasPositivePattern && pattern[0] !== '!') {
74
- hasPositivePattern = true;
75
- }
76
-
77
- // Extract patterns that start with an ignored directory. These need to be
78
- // rematched separately.
79
- if (defaultIgnore.indexOf(pattern.split('/')[0]) >= 0) {
80
- overrideDefaultIgnorePatterns.push(pattern);
81
- }
82
- });
83
-
84
- // Same defaults as used for Chokidar.
85
- if (!hasPositivePattern) {
86
- mixedPatterns = ['package.json', '**/*.js'].concat(mixedPatterns);
87
- }
88
-
89
- return function (path) {
90
- path = matchable(path);
91
-
92
- // Ignore paths outside the current working directory. They can't be matched
93
- // to a pattern.
94
- if (/^\.\.\//.test(path)) {
95
- return false;
96
- }
97
-
98
- var isSource = multimatch(path, mixedPatterns).length === 1;
99
- if (!isSource) {
100
- return false;
101
- }
102
-
103
- var isIgnored = multimatch(path, defaultIgnorePatterns).length === 1;
104
- if (!isIgnored) {
105
- return true;
106
- }
107
-
108
- var isErroneouslyIgnored = multimatch(path, overrideDefaultIgnorePatterns).length === 1;
109
- if (isErroneouslyIgnored) {
110
- return true;
111
- }
112
-
113
- return false;
114
- };
115
- };
116
-
117
- AvaFiles.prototype.makeTestMatcher = function () {
118
- var excludePatterns = this.excludePatterns;
119
- var initialPatterns = this.files.concat(excludePatterns);
120
-
121
- return function (filepath) {
122
- // Like in api.js, tests must be .js files and not start with _
123
- if (path.extname(filepath) !== '.js' || path.basename(filepath)[0] === '_') {
124
- return false;
125
- }
126
-
127
- // Check if the entire path matches a pattern.
128
- if (multimatch(matchable(filepath), initialPatterns).length === 1) {
129
- return true;
130
- }
131
-
132
- // Check if the path contains any directory components.
133
- var dirname = path.dirname(filepath);
134
- if (dirname === '.') {
135
- return false;
136
- }
137
-
138
- // Compute all possible subpaths. Note that the dirname is assumed to be
139
- // relative to the working directory, without a leading `./`.
140
- var subpaths = dirname.split(/[\\\/]/).reduce(function (subpaths, component) {
141
- var parent = subpaths[subpaths.length - 1];
142
- if (parent) {
143
- // Always use / to makes multimatch consistent across platforms.
144
- subpaths.push(parent + '/' + component);
145
- } else {
146
- subpaths.push(component);
147
- }
148
- return subpaths;
149
- }, []);
150
-
151
- // Check if any of the possible subpaths match a pattern. If so, generate a
152
- // new pattern with **/*.js.
153
- var recursivePatterns = subpaths.filter(function (subpath) {
154
- return multimatch(subpath, initialPatterns).length === 1;
155
- }).map(function (subpath) {
156
- // Always use / to makes multimatch consistent across platforms.
157
- return subpath + '/**/*.js';
158
- });
159
-
160
- // See if the entire path matches any of the subpaths patterns, taking the
161
- // excludePatterns into account. This mimicks the behavior in api.js
162
- return multimatch(matchable(filepath), recursivePatterns.concat(excludePatterns)).length === 1;
163
- };
164
- };
165
-
166
- AvaFiles.prototype.getChokidarPatterns = function () {
167
- var paths = [];
168
- var ignored = [];
169
-
170
- this.sources.forEach(function (pattern) {
171
- if (pattern[0] === '!') {
172
- ignored.push(pattern.slice(1));
173
- } else {
174
- paths.push(pattern);
175
- }
176
- });
177
-
178
- // Allow source patterns to override the default ignore patterns. Chokidar
179
- // ignores paths that match the list of ignored patterns. It uses anymatch
180
- // under the hood, which supports negation patterns. For any source pattern
181
- // that starts with an ignored directory, ensure the corresponding negation
182
- // pattern is added to the ignored paths.
183
- var overrideDefaultIgnorePatterns = paths.filter(function (pattern) {
184
- return defaultIgnore.indexOf(pattern.split('/')[0]) >= 0;
185
- }).map(function (pattern) {
186
- return '!' + pattern;
187
- });
188
- ignored = getDefaultIgnorePatterns().concat(ignored, overrideDefaultIgnorePatterns);
189
-
190
- if (paths.length === 0) {
191
- paths = ['package.json', '**/*.js'];
192
- }
193
- paths = paths.concat(this.files);
194
-
195
- return {
196
- paths: paths,
197
- ignored: ignored
198
- };
199
- };
200
-
201
- function handlePaths(files, excludePatterns, globOptions) {
202
- // convert pinkie-promise to Bluebird promise
203
- files = Promise.resolve(globby(files.concat(excludePatterns), globOptions));
204
-
205
- var searchedParents = Object.create(null);
206
- var foundFiles = Object.create(null);
207
-
208
- function alreadySearchingParent(dir) {
209
- if (searchedParents[dir]) {
210
- return true;
211
- }
212
-
213
- var parentDir = path.dirname(dir);
214
-
215
- if (parentDir === dir) {
216
- // We have reached the root path.
217
- return false;
218
- }
219
-
220
- return alreadySearchingParent(parentDir);
221
- }
222
-
223
- return files
224
- .map(function (file) {
225
- if (fs.statSync(file).isDirectory()) {
226
- if (alreadySearchingParent(file)) {
227
- return null;
228
- }
229
-
230
- searchedParents[file] = true;
231
-
232
- var pattern = path.join(file, '**', '*.js');
233
-
234
- if (process.platform === 'win32') {
235
- // Always use / in patterns, harmonizing matching across platforms.
236
- pattern = slash(pattern);
237
- }
238
-
239
- return handlePaths([pattern], excludePatterns, globOptions);
240
- }
241
-
242
- // globby returns slashes even on Windows. Normalize here so the file
243
- // paths are consistently platform-accurate as tests are run.
244
- return path.normalize(file);
245
- })
246
- .then(flatten)
247
- .filter(function (file) {
248
- return file && path.extname(file) === '.js' && path.basename(file)[0] !== '_';
249
- })
250
- .map(function (file) {
251
- return path.resolve(file);
252
- })
253
- .filter(function (file) {
254
- var alreadyFound = foundFiles[file];
255
- foundFiles[file] = true;
256
- return !alreadyFound;
257
- });
258
- }
259
-
260
- module.exports = AvaFiles;
261
- module.exports.defaultIncludePatterns = defaultIncludePatterns;
262
- module.exports.defaultExcludePatterns = defaultExcludePatterns;
package/lib/send.js DELETED
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- // utility to send messages to processes
4
- module.exports = function (ps, name, data) {
5
- if (typeof ps === 'string') {
6
- data = name || {};
7
- name = ps;
8
- ps = process;
9
- }
10
-
11
- ps.send({
12
- name: 'ava-' + name,
13
- data: data,
14
- ava: true
15
- });
16
- };