@lvce-editor/test-with-playwright-worker 0.1.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/index.js +6 -0
- package/package.json +25 -0
- package/src/parts/Assert/Assert.js +59 -0
- package/src/parts/AssertionError/AssertionError.js +6 -0
- package/src/parts/Callback/Callback.js +39 -0
- package/src/parts/Character/Character.js +11 -0
- package/src/parts/CleanStack/CleanStack.js +93 -0
- package/src/parts/Cli/Cli.js +8 -0
- package/src/parts/CliCommandType/CliCommandType.js +2 -0
- package/src/parts/Command/Command.js +9 -0
- package/src/parts/CommandMap/CommandMap.js +6 -0
- package/src/parts/CommandNotFoundError/CommandNotFoundError.js +9 -0
- package/src/parts/CommandState/CommandState.js +17 -0
- package/src/parts/EncodingType/EncodingType.js +1 -0
- package/src/parts/ErrorCodes/ErrorCodes.js +19 -0
- package/src/parts/GetErrorResponse/GetErrorResponse.js +56 -0
- package/src/parts/GetPort/GetPort.js +5 -0
- package/src/parts/GetResponse/GetResponse.js +12 -0
- package/src/parts/GetServerPath/GetServerPath.js +4 -0
- package/src/parts/GetSuccessResponse/GetSuccessResponse.js +12 -0
- package/src/parts/GetTestState/GetTestState.js +24 -0
- package/src/parts/GetTests/GetTests.js +22 -0
- package/src/parts/HandleCliArgs/HandleCliArgs.js +19 -0
- package/src/parts/HandleIpc/HandleIpc.js +13 -0
- package/src/parts/Id/Id.js +7 -0
- package/src/parts/IpcChild/IpcChild.js +9 -0
- package/src/parts/IpcChildModule/IpcChildModule.js +12 -0
- package/src/parts/IpcChildType/IpcChildType.js +13 -0
- package/src/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +41 -0
- package/src/parts/IpcChildWithNodeWorker/IpcChildWithNodeWorker.js +27 -0
- package/src/parts/IpcError/IpcError.js +6 -0
- package/src/parts/IsTestFile/IsTestFile.js +6 -0
- package/src/parts/JoinLines/JoinLines.js +5 -0
- package/src/parts/Json/Json.js +17 -0
- package/src/parts/JsonError/JsonError.js +64 -0
- package/src/parts/JsonParsingError/JsonParsingError.js +17 -0
- package/src/parts/JsonRpc/JsonRpc.js +35 -0
- package/src/parts/JsonRpcErrorCode/JsonRpcErrorCode.js +2 -0
- package/src/parts/JsonRpcVersion/JsonRpcVersion.js +1 -0
- package/src/parts/Logger/Logger.js +43 -0
- package/src/parts/Main/Main.js +36 -0
- package/src/parts/NoTestFilesFoundError/NoTestFilesFoundError.js +8 -0
- package/src/parts/PrettyError/PrettyError.js +139 -0
- package/src/parts/PrintPrettyError/PrintPrettyError.js +5 -0
- package/src/parts/Process/Process.js +20 -0
- package/src/parts/ProcessListeners/ProcessListeners.js +3 -0
- package/src/parts/RunAllTests/RunAllTests.js +45 -0
- package/src/parts/RunTest/RunTest.js +37 -0
- package/src/parts/RunTests/RunTests.js +44 -0
- package/src/parts/SetupTests/SetupTests.js +25 -0
- package/src/parts/Signal/Signal.js +1 -0
- package/src/parts/SplitLines/SplitLines.js +5 -0
- package/src/parts/StartBrowser/StartBrowser.js +21 -0
- package/src/parts/StartServer/StartServer.js +29 -0
- package/src/parts/TearDownTests/TearDownTests.js +6 -0
- package/src/parts/TestOverlayState/TestOverlayState.js +3 -0
- package/src/parts/TestState/TestState.js +3 -0
- package/src/parts/TestWorkerCommandType/TestWorkerCommandType.js +1 -0
- package/src/workerMain.js +3 -0
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lvce-editor/test-with-playwright-worker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src/parts/RunAllTests/RunAllTests.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git@github.com:lvce-editor/test-with-playwright.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@playwright/test": "^1.34.2",
|
|
16
|
+
"get-port": "^6.1.2",
|
|
17
|
+
"minimist": "^1.2.8",
|
|
18
|
+
"read-pkg-up": "^9.1.0",
|
|
19
|
+
"verror": "^1.10.1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/jest": "^29.5.1",
|
|
23
|
+
"@types/verror": "^1.10.6"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AssertionError } from '../AssertionError/AssertionError.js'
|
|
2
|
+
|
|
3
|
+
const getType = (value) => {
|
|
4
|
+
switch (typeof value) {
|
|
5
|
+
case 'number':
|
|
6
|
+
return 'number'
|
|
7
|
+
case 'function':
|
|
8
|
+
return 'function'
|
|
9
|
+
case 'string':
|
|
10
|
+
return 'string'
|
|
11
|
+
case 'object':
|
|
12
|
+
if (value === null) {
|
|
13
|
+
return 'null'
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
return 'array'
|
|
17
|
+
}
|
|
18
|
+
return 'object'
|
|
19
|
+
case 'boolean':
|
|
20
|
+
return 'boolean'
|
|
21
|
+
default:
|
|
22
|
+
return 'unknown'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const object = (value) => {
|
|
27
|
+
const type = getType(value)
|
|
28
|
+
if (type !== 'object') {
|
|
29
|
+
throw new AssertionError('expected value to be of type object')
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const number = (value) => {
|
|
34
|
+
const type = getType(value)
|
|
35
|
+
if (type !== 'number') {
|
|
36
|
+
throw new AssertionError('expected value to be of type number')
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const array = (value) => {
|
|
41
|
+
const type = getType(value)
|
|
42
|
+
if (type !== 'array') {
|
|
43
|
+
throw new AssertionError('expected value to be of type array')
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const string = (value) => {
|
|
48
|
+
const type = getType(value)
|
|
49
|
+
if (type !== 'string') {
|
|
50
|
+
throw new AssertionError('expected value to be of type string')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const boolean = (value) => {
|
|
55
|
+
const type = getType(value)
|
|
56
|
+
if (type !== 'boolean') {
|
|
57
|
+
throw new AssertionError('expected value to be of type boolean')
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Id from '../Id/Id.js'
|
|
2
|
+
|
|
3
|
+
export const state = {
|
|
4
|
+
callbacks: Object.create(null),
|
|
5
|
+
onceListeners: new Set(),
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const registerPromise = () => {
|
|
9
|
+
const id = Id.create()
|
|
10
|
+
const promise = new Promise((resolve, reject) => {
|
|
11
|
+
state.callbacks[id] = { resolve, reject }
|
|
12
|
+
})
|
|
13
|
+
return { id, promise }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// TODO merge resolve and resolveEmpty
|
|
17
|
+
export const resolve = (id, args) => {
|
|
18
|
+
const { callbacks } = state
|
|
19
|
+
if (!(id in callbacks)) {
|
|
20
|
+
console.warn(`callback ${id} may already be disposed`)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
callbacks[id].resolve(args)
|
|
24
|
+
delete callbacks[id]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const reject = (id, error) => {
|
|
28
|
+
const { callbacks } = state
|
|
29
|
+
if (!(id in callbacks)) {
|
|
30
|
+
console.warn(`callback (rejected) ${id} may already be disposed`)
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
callbacks[id].reject(error)
|
|
34
|
+
delete callbacks[id]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const isAllEmpty = () => {
|
|
38
|
+
return Object.keys(state.callbacks).length === 0 && state.onceListeners.size === 0
|
|
39
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const Backslash = '\\'
|
|
2
|
+
export const Dash = '-'
|
|
3
|
+
export const Dot = '.'
|
|
4
|
+
export const EmptyString = ''
|
|
5
|
+
export const NewLine = '\n'
|
|
6
|
+
export const OpenAngleBracket = '<'
|
|
7
|
+
export const Slash = '/'
|
|
8
|
+
export const Space = ' '
|
|
9
|
+
export const Tab = '\t'
|
|
10
|
+
export const Underline = '_'
|
|
11
|
+
export const T = 't'
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as SplitLines from '../SplitLines/SplitLines.js'
|
|
2
|
+
|
|
3
|
+
const RE_AT = /^\s+at/
|
|
4
|
+
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/
|
|
5
|
+
const RE_OBJECT_AS = /^\s*at (async )?Object\.\w+ \[as ([\w\.]+)\]/
|
|
6
|
+
const RE_GET_RESPONSE = /^\s*at async getResponse/
|
|
7
|
+
const RE_WEBSOCKET_HANDLE_MESSAGE = /^\s*at async WebSocket.handleMessage/
|
|
8
|
+
const RE_EXECUTE_COMMAND_ASYNC = /^\s*at executeCommandAsync/
|
|
9
|
+
const RE_HANDLE_OTHER_MESSAGES_FROM_MESSAGE_PORT = /^\s*at async MessagePort\.handleOtherMessagesFromMessagePort/
|
|
10
|
+
|
|
11
|
+
const isInternalLine = (line) => {
|
|
12
|
+
return line.includes('node:') || RE_AT_PROMISE_INDEX.test(line) || line.includes('node_modules/ws')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const isRelevantLine = (line) => {
|
|
16
|
+
return !isInternalLine(line)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isApplicationUsefulLine = (line, index) => {
|
|
20
|
+
if (index === 0) {
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
if (RE_GET_RESPONSE.test(line)) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
if (RE_WEBSOCKET_HANDLE_MESSAGE.test(line)) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
if (RE_EXECUTE_COMMAND_ASYNC.test(line)) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
if (RE_HANDLE_OTHER_MESSAGES_FROM_MESSAGE_PORT.test(line)) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const isNormalStackLine = (line) => {
|
|
39
|
+
return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const cleanLine = (line) => {
|
|
43
|
+
if (line.startsWith(' at exports.')) {
|
|
44
|
+
return ' at ' + line.slice(' at exports.'.length)
|
|
45
|
+
}
|
|
46
|
+
if (line.startsWith(' at async exports.')) {
|
|
47
|
+
return ' at async ' + line.slice(' at async exports.'.length)
|
|
48
|
+
}
|
|
49
|
+
if (line.startsWith(' at async Module.')) {
|
|
50
|
+
return ' at async ' + line.slice(' at async Module.'.length)
|
|
51
|
+
}
|
|
52
|
+
if (line.startsWith(' at Module.')) {
|
|
53
|
+
return ' at ' + line.slice(' at Module.'.length)
|
|
54
|
+
}
|
|
55
|
+
const objectMatch = line.match(RE_OBJECT_AS)
|
|
56
|
+
if (objectMatch) {
|
|
57
|
+
const rest = line.slice(objectMatch[0].length)
|
|
58
|
+
if (objectMatch[1]) {
|
|
59
|
+
return ' at ' + objectMatch[1] + objectMatch[2] + rest
|
|
60
|
+
}
|
|
61
|
+
return ' at ' + objectMatch[2] + rest
|
|
62
|
+
}
|
|
63
|
+
return line
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const getDetails = (lines) => {
|
|
67
|
+
const index = lines.findIndex(isNormalStackLine)
|
|
68
|
+
return {
|
|
69
|
+
custom: lines.slice(0, index),
|
|
70
|
+
actualStack: lines.slice(index).map(cleanLine),
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const RE_PATH_1 = /^\/(.*)(\d+)$/
|
|
75
|
+
|
|
76
|
+
const mergeCustom = (custom, relevantStack) => {
|
|
77
|
+
if (custom.length === 0) {
|
|
78
|
+
return relevantStack
|
|
79
|
+
}
|
|
80
|
+
const firstLine = custom[0]
|
|
81
|
+
if (RE_PATH_1.test(firstLine)) {
|
|
82
|
+
return [` at ${firstLine}`, ...relevantStack]
|
|
83
|
+
}
|
|
84
|
+
return relevantStack
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const cleanStack = (stack) => {
|
|
88
|
+
const lines = SplitLines.splitLines(stack)
|
|
89
|
+
const { custom, actualStack } = getDetails(lines)
|
|
90
|
+
const relevantStack = actualStack.filter(isRelevantLine).filter(isApplicationUsefulLine)
|
|
91
|
+
const merged = mergeCustom(custom, relevantStack)
|
|
92
|
+
return merged
|
|
93
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const state = {
|
|
2
|
+
commands: Object.create(null),
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const registerCommand = (key, fn) => {
|
|
6
|
+
state.commands[key] = fn
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const registerCommands = (commandMap) => {
|
|
10
|
+
for (const [key, value] of Object.entries(commandMap)) {
|
|
11
|
+
registerCommand(key, value)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getCommand = (key) => {
|
|
16
|
+
return state.commands[key]
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const Utf8 = 'utf8'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const E_COLOR_THEME_NOT_FOUND = 'E_COLOR_THEME_NOT_FOUND'
|
|
2
|
+
export const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND'
|
|
3
|
+
export const E_ICON_THEME_NOT_FOUND = 'E_ICON_THEME_NOT_FOUND'
|
|
4
|
+
export const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE'
|
|
5
|
+
export const E_MANIFEST_NOT_FOUND = 'E_MANIFEST_NOT_FOUND'
|
|
6
|
+
export const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON'
|
|
7
|
+
export const EACCES = 'EACCES'
|
|
8
|
+
export const ECONNRESET = 'ECONNRESET'
|
|
9
|
+
export const EEXIST = 'EEXIST'
|
|
10
|
+
export const EISDIR = 'EISDIR'
|
|
11
|
+
export const ELOOP = 'ELOOP'
|
|
12
|
+
export const ENOENT = 'ENOENT'
|
|
13
|
+
export const ENOTDIR = 'ENOTDIR'
|
|
14
|
+
export const EPERM = 'EPERM'
|
|
15
|
+
export const EPIPE = 'EPIPE'
|
|
16
|
+
export const ERR_IPC_CHANNEL_CLOSED = 'ERR_IPC_CHANNEL_CLOSED'
|
|
17
|
+
export const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND'
|
|
18
|
+
export const EXDEV = 'EXDEV'
|
|
19
|
+
export const E_NO_TEST_FILES = 'E_NO_TEST_FILES'
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CommandNotFoundError } from '../CommandNotFoundError/CommandNotFoundError.js'
|
|
2
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
3
|
+
import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
|
|
4
|
+
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
5
|
+
import * as PrettyError from '../PrettyError/PrettyError.js'
|
|
6
|
+
import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
|
|
7
|
+
|
|
8
|
+
const shouldLogError = (error) => {
|
|
9
|
+
if (error && error.code === ErrorCodes.ENOENT) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getErrorResponse = (message, error) => {
|
|
16
|
+
if (error && error instanceof CommandNotFoundError) {
|
|
17
|
+
return {
|
|
18
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
19
|
+
id: message.id,
|
|
20
|
+
error: {
|
|
21
|
+
code: JsonRpcErrorCode.MethodNotFound,
|
|
22
|
+
message: error.message,
|
|
23
|
+
data: error.stack,
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!shouldLogError(error)) {
|
|
28
|
+
return {
|
|
29
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
30
|
+
id: message.id,
|
|
31
|
+
error: {
|
|
32
|
+
code: JsonRpcErrorCode.Custom,
|
|
33
|
+
message: `${error}`,
|
|
34
|
+
data: {
|
|
35
|
+
code: error.code,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const prettyError = PrettyError.prepare(error)
|
|
41
|
+
PrintPrettyError.printPrettyError(prettyError, `[terminal-process] `)
|
|
42
|
+
return {
|
|
43
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
44
|
+
id: message.id,
|
|
45
|
+
error: {
|
|
46
|
+
code: JsonRpcErrorCode.Custom,
|
|
47
|
+
message: prettyError.message,
|
|
48
|
+
data: {
|
|
49
|
+
stack: prettyError.stack,
|
|
50
|
+
codeFrame: prettyError.codeFrame,
|
|
51
|
+
type: prettyError.type,
|
|
52
|
+
code: prettyError.code,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Command from '../Command/Command.js'
|
|
2
|
+
import * as GetErrorResponse from '../GetErrorResponse/GetErrorResponse.js'
|
|
3
|
+
import * as GetSuccessResponse from '../GetSuccessResponse/GetSuccessResponse.js'
|
|
4
|
+
|
|
5
|
+
export const getResponse = async (message, ipc) => {
|
|
6
|
+
try {
|
|
7
|
+
const result = await Command.execute(message.method, ipc, ...message.params)
|
|
8
|
+
return GetSuccessResponse.getSuccessResponse(message, result)
|
|
9
|
+
} catch (error) {
|
|
10
|
+
return GetErrorResponse.getErrorResponse(message, error)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
2
|
+
|
|
3
|
+
export const getSuccessResponse = (message, result) => {
|
|
4
|
+
if (!message.id) {
|
|
5
|
+
return undefined
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
9
|
+
id: message.id,
|
|
10
|
+
result: result ?? null,
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as TestOverlayState from '../TestOverlayState/TestOverlayState.js'
|
|
2
|
+
import * as TestState from '../TestState/TestState.js'
|
|
3
|
+
|
|
4
|
+
export const getTestState = (testOverlayState, text) => {
|
|
5
|
+
switch (testOverlayState) {
|
|
6
|
+
case TestOverlayState.Pass:
|
|
7
|
+
return {
|
|
8
|
+
status: TestState.Pass,
|
|
9
|
+
error: '',
|
|
10
|
+
}
|
|
11
|
+
case TestOverlayState.Skip:
|
|
12
|
+
return {
|
|
13
|
+
status: TestState.Skip,
|
|
14
|
+
error: '',
|
|
15
|
+
}
|
|
16
|
+
case TestOverlayState.Fail:
|
|
17
|
+
return {
|
|
18
|
+
status: TestState.Fail,
|
|
19
|
+
error: `${text}`,
|
|
20
|
+
}
|
|
21
|
+
default:
|
|
22
|
+
throw new Error(`unexpected test state: ${testOverlayState}`)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readdir } from 'fs/promises'
|
|
2
|
+
import VError from 'verror'
|
|
3
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
4
|
+
import * as IsTestFile from '../IsTestFile/IsTestFile.js'
|
|
5
|
+
import { NoTestFilesFoundError } from '../NoTestFilesFoundError/NoTestFilesFoundError.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} testSrc
|
|
9
|
+
*/
|
|
10
|
+
export const getTests = async (testSrc) => {
|
|
11
|
+
try {
|
|
12
|
+
const dirents = await readdir(testSrc)
|
|
13
|
+
return dirents.filter(IsTestFile.isTestFile)
|
|
14
|
+
} catch (error) {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
if (error && error.code === ErrorCodes.ENOENT) {
|
|
17
|
+
throw new NoTestFilesFoundError(testSrc)
|
|
18
|
+
}
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
throw new VError(error, `Failed to get test files`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as RunAllTests from '../RunAllTests/RunAllTests.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {{argv:string[], env:any}} param0
|
|
6
|
+
*/
|
|
7
|
+
export const handleCliArgs = async ({ argv, env }) => {
|
|
8
|
+
const cwd = process.cwd()
|
|
9
|
+
const extensionPath = env.ONLY_EXTENSION
|
|
10
|
+
const testPath = env.TEST_PATH || ''
|
|
11
|
+
const headless = argv.includes('--headless')
|
|
12
|
+
// TODO
|
|
13
|
+
await RunAllTests.runAllTests({
|
|
14
|
+
extensionPath,
|
|
15
|
+
testPath,
|
|
16
|
+
cwd,
|
|
17
|
+
headless,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
|
+
import * as GetResponse from '../GetResponse/GetResponse.js'
|
|
3
|
+
|
|
4
|
+
export const handleIpc = (ipc) => {
|
|
5
|
+
Assert.object(ipc)
|
|
6
|
+
const handleMessage = async (message) => {
|
|
7
|
+
const response = await GetResponse.getResponse(message, ipc)
|
|
8
|
+
if (response) {
|
|
9
|
+
ipc.send(response)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
ipc.on('message', handleMessage)
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as IpcChildModule from '../IpcChildModule/IpcChildModule.js'
|
|
2
|
+
|
|
3
|
+
export const listen = async ({ method, ...params }) => {
|
|
4
|
+
const module = await IpcChildModule.getModule(method)
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const rawIpc = await module.listen(params)
|
|
7
|
+
const ipc = module.wrap(rawIpc)
|
|
8
|
+
return ipc
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as IpcChildType from '../IpcChildType/IpcChildType.js'
|
|
2
|
+
|
|
3
|
+
export const getModule = (method) => {
|
|
4
|
+
switch (method) {
|
|
5
|
+
case IpcChildType.NodeForkedProcess:
|
|
6
|
+
return import('../IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js')
|
|
7
|
+
case IpcChildType.NodeWorker:
|
|
8
|
+
return import('../IpcChildWithNodeWorker/IpcChildWithNodeWorker.js')
|
|
9
|
+
default:
|
|
10
|
+
throw new Error('unexpected ipc type')
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const NodeWorker = 1
|
|
2
|
+
export const NodeForkedProcess = 2
|
|
3
|
+
|
|
4
|
+
export const Auto = () => {
|
|
5
|
+
const { argv } = process
|
|
6
|
+
if (argv.includes('--ipc-type=node-worker')) {
|
|
7
|
+
return NodeWorker
|
|
8
|
+
}
|
|
9
|
+
if (argv.includes('--ipc-type=node-forked-process')) {
|
|
10
|
+
return NodeForkedProcess
|
|
11
|
+
}
|
|
12
|
+
throw new Error(`[test-worker] unknown ipc type`)
|
|
13
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { IpcError } from '../IpcError/IpcError.js'
|
|
2
|
+
|
|
3
|
+
export const listen = async () => {
|
|
4
|
+
if (!process.send) {
|
|
5
|
+
throw new IpcError('process ipc is not available')
|
|
6
|
+
}
|
|
7
|
+
process.send('ready')
|
|
8
|
+
return process
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const getActualData = (message, handle) => {
|
|
12
|
+
if (handle) {
|
|
13
|
+
return {
|
|
14
|
+
...message,
|
|
15
|
+
params: [...message.params, handle],
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return message
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const wrap = (process) => {
|
|
22
|
+
return {
|
|
23
|
+
process,
|
|
24
|
+
on(event, listener) {
|
|
25
|
+
if (event === 'message') {
|
|
26
|
+
const wrappedListener = (message, handle) => {
|
|
27
|
+
const actualData = getActualData(message, handle)
|
|
28
|
+
listener(actualData)
|
|
29
|
+
}
|
|
30
|
+
this.process.on(event, wrappedListener)
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
off(event, listener) {
|
|
34
|
+
this.process.off(event, listener)
|
|
35
|
+
},
|
|
36
|
+
send(message) {
|
|
37
|
+
this.process.send(message)
|
|
38
|
+
},
|
|
39
|
+
dispose() {},
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { parentPort } from 'node:worker_threads'
|
|
2
|
+
|
|
3
|
+
export const listen = async () => {
|
|
4
|
+
if (!parentPort) {
|
|
5
|
+
throw new Error('parentPort is required')
|
|
6
|
+
}
|
|
7
|
+
parentPort.postMessage('ready')
|
|
8
|
+
return parentPort
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const wrap = (parentPort) => {
|
|
12
|
+
return {
|
|
13
|
+
parentPort,
|
|
14
|
+
on(event, listener) {
|
|
15
|
+
this.parentPort.on(event, listener)
|
|
16
|
+
},
|
|
17
|
+
off(event, listener) {
|
|
18
|
+
this.parentPort.off(event, listener)
|
|
19
|
+
},
|
|
20
|
+
send(message) {
|
|
21
|
+
this.parentPort.postMessage(message)
|
|
22
|
+
},
|
|
23
|
+
dispose() {
|
|
24
|
+
this.parentPort.close()
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// parsing error handling based on https://github.com/sindresorhus/parse-json/blob/main/index.js
|
|
2
|
+
|
|
3
|
+
import { JsonParsingError } from '../JsonParsingError/JsonParsingError.js'
|
|
4
|
+
|
|
5
|
+
export const parse = async (string, filePath) => {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(string)
|
|
8
|
+
} catch (error) {
|
|
9
|
+
const JsonError = await import('../JsonError/JsonError.js')
|
|
10
|
+
const errorProps = JsonError.getErrorPropsFromError(error, string, filePath)
|
|
11
|
+
throw new JsonParsingError(errorProps.message, errorProps.codeFrame, errorProps.stack)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const stringify = (value) => {
|
|
16
|
+
return JSON.stringify(value, null, 2) + '\n'
|
|
17
|
+
}
|