-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12775 from keymanapp/chore/rename-test-callbacks
chore: rename TestCompilerCallbacks.ts
- Loading branch information
Showing
3 changed files
with
169 additions
and
239 deletions.
There are no files selected for viewing
168 changes: 168 additions & 0 deletions
168
developer/src/common/web/test-helpers/TestCompilerCallbacks.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,168 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSystemCallbacks, | ||
CompilerError, CompilerNetAsyncCallbacks, DefaultCompilerFileSystemAsyncCallbacks, | ||
CompilerFileSystemAsyncCallbacks } from '@keymanapp/developer-utils'; | ||
import { fileURLToPath } from 'url'; | ||
|
||
const { TEST_SAVE_FIXTURES } = process.env; | ||
|
||
/** | ||
* A CompilerCallbacks implementation for testing | ||
*/ | ||
export class TestCompilerCallbacks implements CompilerCallbacks { | ||
/* TestCompilerCallbacks */ | ||
|
||
messages: CompilerEvent[] = []; | ||
readonly _net: TestCompilerNetAsyncCallbacks; | ||
readonly _fsAsync: DefaultCompilerFileSystemAsyncCallbacks = new DefaultCompilerFileSystemAsyncCallbacks(this); | ||
|
||
constructor(basePath?: string) { | ||
if(basePath) { | ||
this._net = new TestCompilerNetAsyncCallbacks(basePath); | ||
} | ||
} | ||
|
||
clear() { | ||
this.messages = []; | ||
} | ||
|
||
printMessages() { | ||
if(this.messages.length) { | ||
process.stdout.write(CompilerError.formatEvent(this.messages)); | ||
} | ||
} | ||
|
||
hasMessage(code: number): boolean { | ||
return this.messages.find((item) => item.code == code) === undefined ? false : true; | ||
} | ||
|
||
fileURLToPath(url: string | URL): string { | ||
return fileURLToPath(url); | ||
} | ||
|
||
/** true of at least one error */ | ||
hasError(): boolean { | ||
return CompilerError.hasError(this.messages); | ||
} | ||
|
||
/* CompilerCallbacks */ | ||
|
||
loadFile(filename: string): Uint8Array { | ||
try { | ||
return fs.readFileSync(filename); | ||
} catch(e) { | ||
if (e.code === 'ENOENT') { | ||
return null; | ||
} else { | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
fileSize(filename: string): number { | ||
return fs.statSync(filename)?.size; | ||
} | ||
|
||
isDirectory(filename: string): boolean { | ||
return fs.statSync(filename)?.isDirectory(); | ||
} | ||
|
||
get path(): CompilerPathCallbacks { | ||
return { | ||
...path, | ||
isAbsolute: path.win32.isAbsolute | ||
}; | ||
} | ||
|
||
get fs(): CompilerFileSystemCallbacks { | ||
return fs; | ||
} | ||
|
||
get net(): CompilerNetAsyncCallbacks { | ||
return this._net; | ||
} | ||
|
||
get fsAsync(): CompilerFileSystemAsyncCallbacks { | ||
return this._fsAsync; | ||
} | ||
|
||
resolveFilename(baseFilename: string, filename: string): string { | ||
const basePath = | ||
baseFilename.endsWith('/') || baseFilename.endsWith('\\') ? | ||
baseFilename : | ||
path.dirname(baseFilename); | ||
// Transform separators to platform separators -- we are agnostic | ||
// in our use here but path prefers files may use | ||
// either / or \, although older kps files were always \. | ||
if(path.sep == '/') { | ||
filename = filename.replace(/\\/g, '/'); | ||
} else { | ||
filename = filename.replace(/\//g, '\\'); | ||
} | ||
if(!path.isAbsolute(filename)) { | ||
filename = path.resolve(basePath, filename); | ||
} | ||
return filename; | ||
} | ||
|
||
reportMessage(event: CompilerEvent): void { | ||
// console.log(event.message); | ||
this.messages.push(event); | ||
} | ||
|
||
debug(msg: string) { | ||
console.debug(msg); | ||
} | ||
}; | ||
|
||
class TestCompilerNetAsyncCallbacks implements CompilerNetAsyncCallbacks { | ||
constructor(private basePath: string) { | ||
} | ||
|
||
urlToPath(url: string): string { | ||
const p = new URL(url); | ||
return path.join(this.basePath, p.hostname, p.pathname.replaceAll(/[^a-z0-9_.!@#$%() -]/ig, '#')); | ||
} | ||
|
||
async fetchBlob(url: string): Promise<Uint8Array> { | ||
const p = this.urlToPath(url); | ||
|
||
if(TEST_SAVE_FIXTURES) { | ||
// When TEST_SAVE_FIXTURES env variable is set, we will do the actual | ||
// fetch from the origin so that we can build the fixtures easily | ||
console.log(`Downloading file ${url} --> ${p}`); | ||
let response: Response; | ||
try { | ||
response = await fetch(url); | ||
} catch(e) { | ||
console.error(`failed to download ${url}`); | ||
console.error(e); | ||
throw e; // yes, we want to abort the download | ||
} | ||
|
||
fs.mkdirSync(path.dirname(p), {recursive: true}); | ||
if(!response.ok) { | ||
// We won't save a file, just delete any existing file | ||
if(fs.existsSync(p)) { | ||
fs.rmSync(p); | ||
} | ||
} else { | ||
const data = new Uint8Array(await response.arrayBuffer()); | ||
fs.writeFileSync(p, data); | ||
} | ||
} | ||
|
||
if(!fs.existsSync(p)) { | ||
// missing file, this is okay | ||
return null; | ||
} | ||
const data: Uint8Array = fs.readFileSync(p); | ||
return data; | ||
} | ||
|
||
async fetchJSON(url: string): Promise<any> { | ||
const data = await this.fetchBlob(url); | ||
return data ? JSON.parse(new TextDecoder().decode(data)) : null; | ||
} | ||
} |
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,164 +1,2 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerError, CompilerNetAsyncCallbacks, DefaultCompilerFileSystemAsyncCallbacks, CompilerFileSystemAsyncCallbacks } from '@keymanapp/developer-utils'; | ||
import { fileURLToPath } from 'url'; | ||
export { verifyCompilerMessagesObject } from './verifyCompilerMessagesObject.js'; | ||
|
||
const { TEST_SAVE_FIXTURES } = process.env; | ||
|
||
class TestCompilerNetAsyncCallbacks implements CompilerNetAsyncCallbacks { | ||
constructor(private basePath: string) { | ||
} | ||
|
||
urlToPath(url: string): string { | ||
const p = new URL(url); | ||
return path.join(this.basePath, p.hostname, p.pathname.replaceAll(/[^a-z0-9_.!@#$%() -]/ig, '#')); | ||
} | ||
|
||
async fetchBlob(url: string): Promise<Uint8Array> { | ||
const p = this.urlToPath(url); | ||
|
||
if(TEST_SAVE_FIXTURES) { | ||
// When TEST_SAVE_FIXTURES env variable is set, we will do the actual | ||
// fetch from the origin so that we can build the fixtures easily | ||
console.log(`Downloading file ${url} --> ${p}`); | ||
let response: Response; | ||
try { | ||
response = await fetch(url); | ||
} catch(e) { | ||
console.error(`failed to download ${url}`); | ||
console.error(e); | ||
throw e; // yes, we want to abort the download | ||
} | ||
|
||
fs.mkdirSync(path.dirname(p), {recursive: true}); | ||
if(!response.ok) { | ||
// We won't save a file, just delete any existing file | ||
if(fs.existsSync(p)) { | ||
fs.rmSync(p); | ||
} | ||
} else { | ||
const data = new Uint8Array(await response.arrayBuffer()); | ||
fs.writeFileSync(p, data); | ||
} | ||
} | ||
|
||
if(!fs.existsSync(p)) { | ||
// missing file, this is okay | ||
return null; | ||
} | ||
const data: Uint8Array = fs.readFileSync(p); | ||
return data; | ||
} | ||
|
||
async fetchJSON(url: string): Promise<any> { | ||
const data = await this.fetchBlob(url); | ||
return data ? JSON.parse(new TextDecoder().decode(data)) : null; | ||
} | ||
} | ||
|
||
/** | ||
* A CompilerCallbacks implementation for testing | ||
*/ | ||
export class TestCompilerCallbacks implements CompilerCallbacks { | ||
/* TestCompilerCallbacks */ | ||
|
||
messages: CompilerEvent[] = []; | ||
readonly _net: TestCompilerNetAsyncCallbacks; | ||
readonly _fsAsync: DefaultCompilerFileSystemAsyncCallbacks = new DefaultCompilerFileSystemAsyncCallbacks(this); | ||
|
||
constructor(basePath?: string) { | ||
if(basePath) { | ||
this._net = new TestCompilerNetAsyncCallbacks(basePath); | ||
} | ||
} | ||
|
||
clear() { | ||
this.messages = []; | ||
} | ||
|
||
printMessages() { | ||
if(this.messages.length) { | ||
process.stdout.write(CompilerError.formatEvent(this.messages)); | ||
} | ||
} | ||
|
||
hasMessage(code: number): boolean { | ||
return this.messages.find((item) => item.code == code) === undefined ? false : true; | ||
} | ||
|
||
fileURLToPath(url: string | URL): string { | ||
return fileURLToPath(url); | ||
} | ||
|
||
/** true of at least one error */ | ||
hasError(): boolean { | ||
return CompilerError.hasError(this.messages); | ||
} | ||
|
||
/* CompilerCallbacks */ | ||
|
||
loadFile(filename: string): Uint8Array { | ||
try { | ||
return fs.readFileSync(filename); | ||
} catch(e) { | ||
if (e.code === 'ENOENT') { | ||
return null; | ||
} else { | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
fileSize(filename: string): number { | ||
return fs.statSync(filename)?.size; | ||
} | ||
|
||
isDirectory(filename: string): boolean { | ||
return fs.statSync(filename)?.isDirectory(); | ||
} | ||
|
||
get path(): CompilerPathCallbacks { | ||
return path; | ||
} | ||
|
||
get fs(): CompilerFileSystemCallbacks { | ||
return fs; | ||
} | ||
|
||
get net(): CompilerNetAsyncCallbacks { | ||
return this._net; | ||
} | ||
|
||
get fsAsync(): CompilerFileSystemAsyncCallbacks { | ||
return this._fsAsync; | ||
} | ||
|
||
resolveFilename(baseFilename: string, filename: string): string { | ||
const basePath = | ||
baseFilename.endsWith('/') || baseFilename.endsWith('\\') ? | ||
baseFilename : | ||
path.dirname(baseFilename); | ||
// Transform separators to platform separators -- we are agnostic | ||
// in our use here but path prefers files may use | ||
// either / or \, although older kps files were always \. | ||
if(path.sep == '/') { | ||
filename = filename.replace(/\\/g, '/'); | ||
} else { | ||
filename = filename.replace(/\//g, '\\'); | ||
} | ||
if(!path.isAbsolute(filename)) { | ||
filename = path.resolve(basePath, filename); | ||
} | ||
return filename; | ||
} | ||
|
||
reportMessage(event: CompilerEvent): void { | ||
// console.log(event.message); | ||
this.messages.push(event); | ||
} | ||
|
||
debug(msg: string) { | ||
console.debug(msg); | ||
} | ||
}; | ||
export { TestCompilerCallbacks } from './TestCompilerCallbacks.js'; |
Oops, something went wrong.