Skip to content

Commit

Permalink
Implement zero-config support (theintern#1141)
Browse files Browse the repository at this point in the history
  • Loading branch information
abolfazlghalandary committed Jan 10, 2023
1 parent c03d068 commit c9b6f62
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 29 deletions.
10 changes: 5 additions & 5 deletions src/bin/intern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ getConfig()
console.log(getConfigDescription(config));
} else {
if (!file) {
console.warn('No config file was loaded');
console.warn('No config file was loaded, using default one...');
}

intern.configure({ reporters: 'runner' });
Expand All @@ -29,9 +29,9 @@ getConfig()
if (
intern.environment === 'browser' &&
((intern.config.suites &&
intern.config.suites.some(pattern => pattern.endsWith('.ts'))) ||
intern.config.suites.some((pattern) => pattern.endsWith('.ts'))) ||
(intern.config.plugins &&
intern.config.plugins.some(plugin =>
intern.config.plugins.some((plugin) =>
plugin.script.endsWith('.ts')
)))
) {
Expand All @@ -42,7 +42,7 @@ getConfig()
return intern.run();
}
})
.catch(error => {
.catch((error) => {
// If intern wasn't initialized, then this error won't have been
// reported
if (!error.reported) {
Expand Down Expand Up @@ -76,7 +76,7 @@ function printHelp(config: any, file?: string) {

const internConfig = (<any>intern)._config;
const opts = Object.keys(internConfig)
.map(key => {
.map((key) => {
return { name: key, value: JSON.stringify(internConfig[key]) };
})
.sort((a, b) => {
Expand Down
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
}

if (!result.file) {
console.warn('No config file was found');
console.warn('No config file was found, using default one...');
}

// Add the HTML and console reporters to the default
Expand Down
39 changes: 26 additions & 13 deletions src/lib/browser/util.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { request, CancellablePromise, global } from '@theintern/common';
import { CancellablePromise, global, request } from '@theintern/common';

import {
createDefaultConfig,
getBasePath,
loadConfig,
parseArgs,
splitConfigPath
splitConfigPath,
} from '../common/util';

/**
Expand All @@ -30,31 +31,32 @@ export function getConfig(file?: string) {
// If no config parameter was provided, try 'intern.json'. If that file
// doesn't exist, just return the args
file = resolvePath('intern.json', configBase);
load = loadConfig(file, loadText, args).catch(error => {
load = loadConfig(file, loadText, args).catch((error) => {
if (error.message.indexOf('Request failed') === 0) {
// The file wasn't found, clear the file name
file = undefined;
return args;
return getSuitesExtension(configBase).then((extension) =>
createDefaultConfig(args, extension)
);
}
throw error;
});
}

return load
.then(config => {
.then((config) => {
// If a basePath wasn't set in the config or via a query arg, and we
// have a config file path, use that.
if (file) {
config.basePath = getBasePath(
file,
config.basePath,
path => path[0] === '/',
(path) => path[0] === '/',
'/'
);
}
return config;
})
.then(config => ({ config, file }));
.then((config) => ({ config, file }));
}

/**
Expand Down Expand Up @@ -138,17 +140,18 @@ export type Url = {
};
export function parseUrl(url: string): Url | undefined {
if (url) {
const match = /^(([^:\/?#]+):)?(\/\/(([^:\/?#]*)(:(\d+))?))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(
url
);
const match =
/^(([^:\/?#]+):)?(\/\/(([^:\/?#]*)(:(\d+))?))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(
url
);
if (match) {
return {
protocol: match[2],
hostname: match[5],
port: match[7],
path: match[8],
query: match[10],
hash: match[12]
hash: match[12],
};
}
}
Expand All @@ -158,7 +161,7 @@ export function parseUrl(url: string): Url | undefined {
* Load a text resource
*/
function loadText(path: string): CancellablePromise<any> {
return request(path).then(response => {
return request(path).then((response) => {
if (!response.ok) {
throw new Error('Request failed: ' + response.status);
}
Expand Down Expand Up @@ -191,3 +194,13 @@ function resolvePath(path: string, basePath: string) {

return basePathParts.join('/');
}

async function getSuitesExtension(basePath: string) {
return existsAsync(resolvePath('tsconfig.json', basePath)).then(
(tsconfigExists) => (tsconfigExists ? 'ts' : 'js')
);
}

async function existsAsync(filePath: string) {
return request(filePath, { method: 'HEAD' }).then((response) => response.ok);
}
12 changes: 12 additions & 0 deletions src/lib/common/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,18 @@ export function setOption(
}
}

/**
* Create a default config to make zero-config running possible
*/
export function createDefaultConfig(baseConfig: any, suitesExtension: string) {
let config = Object.assign({}, baseConfig);
config.suites = [
`tests/**/*.${suitesExtension}`,
`src/**/*.spec.${suitesExtension}`,
];
return config;
}

/**
* Split a config path into a file name and a child config name.
*
Expand Down
25 changes: 15 additions & 10 deletions src/lib/node/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
join,
normalize,
resolve,
sep
sep,
} from 'path';
import { parse } from 'shell-quote';
import { RawSourceMap } from 'source-map';
Expand All @@ -16,10 +16,11 @@ import { Task, CancellablePromise } from '@theintern/common';

import process from './process';
import {
createDefaultConfig,
getBasePath,
loadConfig,
parseArgs,
splitConfigPath
splitConfigPath,
} from '../common/util';
/**
* Expand a list of glob patterns into a flat file list. Patterns may be simple
Expand Down Expand Up @@ -50,10 +51,10 @@ export function expandFiles(patterns?: string[] | string) {
}

const allPaths = includes
.map(pattern => glob(pattern, { ignore: excludes }))
.map((pattern) => glob(pattern, { ignore: excludes }))
.reduce((allFiles, files) => allFiles.concat(files), paths);
const uniquePaths: { [name: string]: boolean } = {};
allPaths.forEach(path => (uniquePaths[path] = true));
allPaths.forEach((path) => (uniquePaths[path] = true));

return Object.keys(uniquePaths);
}
Expand Down Expand Up @@ -116,23 +117,22 @@ export function getConfig(
(error: NodeJS.ErrnoException) => {
if (error.code === 'ENOENT') {
file = undefined;
return args;
return createDefaultConfig(args, getSuitesExtension());
}
throw error;
}
);
}

return load
.then(config => {
.then((config) => {
// If a basePath wasn't set in the config or via a query arg, and we
// have a config file path, use that.
if (file) {
config.basePath = getBasePath(file, config.basePath, isAbsolute, sep);
}
return config;
})
.then(config => ({ config, file }));
.then((config) => ({ config, file }));
}

/**
Expand Down Expand Up @@ -213,7 +213,7 @@ export function transpileSource(filename: string, code: string) {
{
_compile(source: string) {
code = source;
}
},
} as any,
filename
);
Expand All @@ -222,4 +222,9 @@ export function transpileSource(filename: string, code: string) {
}

// Regex for matching sourceMappingUrl comments
const sourceMapRegEx = /^(?:\/{2}[#@]{1,2}|\/\*)\s+sourceMappingURL\s*=\s*(data:(?:[^;]+;)+base64,)?(\S+)/;
const sourceMapRegEx =
/^(?:\/{2}[#@]{1,2}|\/\*)\s+sourceMappingURL\s*=\s*(data:(?:[^;]+;)+base64,)?(\S+)/;

function getSuitesExtension() {
return existsSync(resolve('tsconfig.json')) ? 'ts' : 'js';
}

0 comments on commit c9b6f62

Please sign in to comment.