-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(configuration): migrate algorithm to Chain of Responsibility…
… pattern for improved extensibility and separation of concerns
- Loading branch information
1 parent
bedd61d
commit b0c5ab2
Showing
9 changed files
with
163 additions
and
55 deletions.
There are no files selected for viewing
85 changes: 85 additions & 0 deletions
85
lib/src/runner/configuration-loaders/configuration-loader.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
import { CypressRunnerConfig } from '../cypress-runner-config'; | ||
|
||
/** | ||
* Object delegated to load CypressRunnerConfig. | ||
* Each loader in the chain is responsible for attempting to load a configuration file | ||
* based on its specific file extension. If a loader cannot find or parse the file, | ||
* it delegates the responsibility to the next loader in the chain. | ||
*/ | ||
export abstract class ConfigurationLoader { | ||
private static readonly CYPRESS_RUNNER_CONFIG_FILENAME = '.cypressrunnerrc'; | ||
|
||
private _next: ConfigurationLoader | undefined; | ||
private _parent: ConfigurationLoader | undefined; | ||
private get supportedExtensions(): string[] { | ||
const parentFormats = this._parent?.supportedExtensions ?? []; | ||
|
||
return [...parentFormats, this.extension]; | ||
} | ||
|
||
/** | ||
* The file extension supported by this loader. | ||
*/ | ||
protected abstract readonly extension: string; | ||
|
||
/** | ||
* Parse the configuration file at the given path. | ||
*/ | ||
protected abstract parse(path: string): CypressRunnerConfig; | ||
|
||
/** | ||
* Attempts to load the configuration file. If the file is found and valid, | ||
* it is parsed and returned. Otherwise, the responsibility is delegated | ||
* to the next loader in the chain. | ||
*/ | ||
public load(): CypressRunnerConfig { | ||
const jsonPath = this.resolveConfigurationPath(); | ||
if (fs.existsSync(jsonPath)) { | ||
return this.parse(jsonPath); | ||
} | ||
|
||
return this.next(); | ||
} | ||
|
||
/** | ||
* Sets the next loader in the chain and establishes a parent-child relationship. | ||
*/ | ||
public setNext(loader: ConfigurationLoader): ConfigurationLoader { | ||
this._next = loader; | ||
loader._parent = this; | ||
|
||
return loader; | ||
} | ||
|
||
/** | ||
* Delegates the loading process to the next loader in the chain. | ||
* Throws an error if no configuration file is found by any loader in the chain. | ||
*/ | ||
protected next(): CypressRunnerConfig { | ||
const { CYPRESS_RUNNER_CONFIG_FILENAME } = ConfigurationLoader; | ||
if (!this._next) { | ||
const supportedExtensions = this.supportedExtensions | ||
.filter((extension) => extension.trim().length > 0) | ||
.join('|'); | ||
|
||
throw new Error( | ||
`No configuration file found. Please create a ${CYPRESS_RUNNER_CONFIG_FILENAME} file with the appropriate format: ${CYPRESS_RUNNER_CONFIG_FILENAME}{${supportedExtensions}}?.`, | ||
); | ||
} | ||
|
||
return this._next.load(); | ||
} | ||
|
||
/** | ||
* Resolves the path to the configuration file based on the current working directory | ||
* and the file extension supported by this loader. | ||
*/ | ||
protected resolveConfigurationPath(): string { | ||
const { CYPRESS_RUNNER_CONFIG_FILENAME } = ConfigurationLoader; | ||
|
||
return path.resolve(process.cwd(), CYPRESS_RUNNER_CONFIG_FILENAME + this.extension); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import * as fs from 'fs'; | ||
|
||
import { CypressRunnerConfig } from '../cypress-runner-config'; | ||
import { JsonConfigurationLoader } from './json'; | ||
|
||
export class DefaultConfigurationLoader extends JsonConfigurationLoader { | ||
protected extension = ''; | ||
|
||
protected parse(path: string): CypressRunnerConfig { | ||
return JSON.parse(fs.readFileSync(path, 'utf-8')); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { DefaultConfigurationLoader } from './default'; | ||
import { JavaScriptConfigurationLoader } from './javascript'; | ||
import { JsonConfigurationLoader } from './json'; | ||
import { TypeScriptConfigurationLoader } from './typescript'; | ||
|
||
export * from './configuration-loader'; | ||
export * from './default'; | ||
export * from './javascript'; | ||
export * from './json'; | ||
export * from './typescript'; | ||
|
||
const defaultLoader = new DefaultConfigurationLoader(); | ||
defaultLoader | ||
.setNext(new JsonConfigurationLoader()) | ||
.setNext(new JavaScriptConfigurationLoader()) | ||
.setNext(new TypeScriptConfigurationLoader()); | ||
|
||
export const loader = defaultLoader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { CypressRunnerConfig } from '../cypress-runner-config'; | ||
import { ConfigurationLoader } from './configuration-loader'; | ||
|
||
export class JavaScriptConfigurationLoader extends ConfigurationLoader { | ||
protected extension = '.js'; | ||
|
||
protected parse(path: string): CypressRunnerConfig { | ||
return require(path); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import * as fs from 'fs'; | ||
|
||
import { CypressRunnerConfig } from '../cypress-runner-config'; | ||
import { ConfigurationLoader } from './configuration-loader'; | ||
|
||
export class JsonConfigurationLoader extends ConfigurationLoader { | ||
protected extension = '.json'; | ||
|
||
protected parse(path: string): CypressRunnerConfig { | ||
return JSON.parse(fs.readFileSync(path, 'utf-8')); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { register } from 'ts-node'; | ||
|
||
import { CypressRunnerConfig } from '../cypress-runner-config'; | ||
import { ConfigurationLoader } from './configuration-loader'; | ||
|
||
export class TypeScriptConfigurationLoader extends ConfigurationLoader { | ||
protected extension = '.ts'; | ||
|
||
protected parse(path: string): CypressRunnerConfig { | ||
register({ | ||
transpileOnly: true, | ||
compilerOptions: { | ||
module: 'commonjs', | ||
}, | ||
}); | ||
|
||
const config = require(path).default; | ||
if (!config) { | ||
throw new Error('Missing default export configuration'); | ||
} | ||
|
||
return config; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
export * from './banner'; | ||
export * from './cypress-runner-config'; | ||
export * from './kill-concurrently-result'; | ||
export * from './load-configuration'; | ||
export * from './runner'; | ||
export * from './start-web-server-commands'; | ||
export * from './wait-web-services'; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters