update: upgrade dependencies and fix tests
- remove spectron - use electron-mocha to run mocha test suites inside electron
This commit is contained in:
parent
4c169178d9
commit
d5697540a8
|
@ -9,7 +9,6 @@
|
|||
node_modules
|
||||
.nyc_output
|
||||
/src/**/*.js
|
||||
/mocks/**/*.js
|
||||
/frontend
|
||||
/test-paths
|
||||
/out
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
"devDependencies": [
|
||||
"**/*.{spec,mock}.*",
|
||||
"src/**/test/*",
|
||||
"mocks/**/*",
|
||||
"src/renderer/**/*",
|
||||
"templates/**/*",
|
||||
"scripts/**/*"
|
||||
|
@ -154,8 +153,6 @@
|
|||
"rules": {
|
||||
"no-unused-expressions": "off",
|
||||
|
||||
"import/order": "off",
|
||||
|
||||
"@typescript-eslint/no-magic-numbers": "off",
|
||||
"@typescript-eslint/typedef": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
|
|
|
@ -7,8 +7,6 @@ node_modules
|
|||
# generated code
|
||||
/src/**/*.js
|
||||
/src/**/*.js.map
|
||||
/mocks/**/*.js
|
||||
/mocks/**/*.js.map
|
||||
/frontend
|
||||
|
||||
# created by testing
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"spec": "src/**/*.spec.js"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# https://github.com/mochajs/mocha/blob/master/example/config
|
||||
spec: 'src/**/*.spec.js'
|
|
@ -16,7 +16,6 @@
|
|||
node_modules
|
||||
.nyc_output
|
||||
/src/**/*.js
|
||||
/mocks/**/*.js
|
||||
/frontend
|
||||
/test-paths
|
||||
/out
|
||||
|
|
|
@ -137,34 +137,27 @@ The point of these libraries is to make uniform code possible over various edito
|
|||
|
||||
The testing framework of choice is [Mocha](https://mochajs.org/). Call `npm run test` to run all tests. Tests are written in typescript and need to be transpiled before testing.
|
||||
|
||||
- assertion is (mainly) done by [Chai](https://www.chaijs.com/)
|
||||
- Electron specific testing is done by [Spectron](https://electronjs.org/spectron)
|
||||
- it writes its electron files into a temporary directory, so the local app installation should not be compromised
|
||||
- assertion is (mainly) done by [Chai](https://www.chaijs.com/)should not be compromised
|
||||
- spies, stubs and mocks are provided by [Sinon.JS](https://sinonjs.org/)
|
||||
- HTTP server mocking is done by [nock](https://github.com/nock/nock)
|
||||
- property based testing is made possible by [fast-check](https://github.com/dubzzz/fast-check)
|
||||
|
||||
For the creation of test files look at existing ones, they are named `*.spec.ts`.
|
||||
For the creation of test files look at existing ones, they are named `*.spec.ts`. They are run inside electron via [electron-mocha](https://github.com/jprichardson/electron-mocha).
|
||||
|
||||
#### Mocks
|
||||
|
||||
There are 2 ways in which mocks are defined/used:
|
||||
Mocks are defined/used for own modules, just beside their file.
|
||||
|
||||
0. for external modules, in [mocks](mocks)
|
||||
- uses the [rewiremock](https://github.com/theKashey/rewiremock) package
|
||||
- use this only when there is some magic happening like for electron which normally runs in its own node process
|
||||
1. for own modules, just beside their file
|
||||
- name the file `*.mock.ts` and use existing mock files for orientation on how to build them
|
||||
- use sparingly and only when not having a mock makes it more complex e.g. for modules which interact with the file system
|
||||
- name the file `*.mock.ts` and use existing mock files for orientation on how to build them
|
||||
- use sparingly and only when not having a mock makes it more complex e.g. for modules which interact with the file system
|
||||
|
||||
#### Tagging
|
||||
|
||||
Mocha does [not have a separate tagging feature](https://github.com/mochajs/mocha/wiki/Tagging), but it can filter via title. Use the following tags in your test titles:
|
||||
|
||||
| tag | usage when |
|
||||
| ----------- | ------------------------- |
|
||||
| ------- | ------------------------- |
|
||||
| `@slow` | test is particularly slow |
|
||||
| `@spectron` | test uses spectron |
|
||||
|
||||
#### Coverage
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
import path from 'path';
|
||||
import { rewiremock } from './rewiremock';
|
||||
import WebContents = Electron.WebContents;
|
||||
|
||||
const electronMock: DeepPartial<typeof Electron> = {
|
||||
app: {
|
||||
on(): void {},
|
||||
getPath(name: string): string {
|
||||
return path.resolve('test-paths', name);
|
||||
},
|
||||
quit(): void {},
|
||||
getAppPath(): string {
|
||||
return path.resolve(__dirname, '..');
|
||||
},
|
||||
},
|
||||
BrowserWindow: class {
|
||||
public webContents: DeepPartial<WebContents> = {
|
||||
openDevTools(): void {},
|
||||
};
|
||||
public loadFile(): void {}
|
||||
public on(): void {}
|
||||
},
|
||||
ipcMain: {
|
||||
on(): void {},
|
||||
},
|
||||
};
|
||||
|
||||
rewiremock('electron').with(electronMock);
|
|
@ -1,6 +0,0 @@
|
|||
import rewiremock from 'rewiremock';
|
||||
|
||||
rewiremock.overrideEntryPoint(module);
|
||||
rewiremock.enable();
|
||||
|
||||
export { rewiremock };
|
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
|
@ -15,8 +15,9 @@
|
|||
},
|
||||
"scripts": {
|
||||
"postinstall": "npm run rebuild",
|
||||
"postupdate": "npm run rebuild",
|
||||
"start": "electron . --enable-logging --env=dev",
|
||||
"rebuild": "electron-rebuild -f -b -t prod,dev,optional",
|
||||
"rebuild": "electron-rebuild -f -b -o better-sqlite3",
|
||||
"electron-version": "electron scripts/electron-version.js",
|
||||
"typeorm:migrate": "npm run typeorm:migrate:library && npm run typeorm:migrate:store",
|
||||
"typeorm:migrate:library": "typeorm migration:run -c library",
|
||||
|
@ -29,11 +30,10 @@
|
|||
"dev:ts": "tsc -w --pretty --preserveWatchOutput",
|
||||
"build": "concurrently -c green,yellow,cyan -n webpack,index,typescript \"npm run build:webpack\" \"npm run build:index\" \"npm run build:ts\"",
|
||||
"dev": "concurrently -c green,yellow,cyan -n webpack,index,typescript \"npm run dev:webpack\" \"npm run dev:index\" \"npm run dev:ts\"",
|
||||
"test:fast": "mocha --grep \"@(slow|spectron)\" --invert",
|
||||
"test": "mocha",
|
||||
"coverage:fast": "nyc npm run test:fast",
|
||||
"test:fast": "electron-mocha --config .mocharc.json --grep \\\"@slow\\\" --invert",
|
||||
"test": "electron-mocha --config .mocharc.json",
|
||||
"coverage": "nyc npm run test",
|
||||
"prelint": "eslint --print-config scripts/forge.config.js | eslint-config-prettier-check",
|
||||
"prelint": "eslint-config-prettier src/main.ts",
|
||||
"lint": "eslint ./**/*.* --max-warnings 1",
|
||||
"lint:fix": "eslint ./**/*.* --fix",
|
||||
"prettier": "prettier -c **/*.*",
|
||||
|
@ -41,11 +41,11 @@
|
|||
"fix": "npm run lint:fix && npm run prettier:fix",
|
||||
"forge:make": "electron-forge --platform win32 --arch x64 make",
|
||||
"forge": "npm audit --production --audit-level=high && npm run build && npm run forge:make",
|
||||
"precommit": "npm run prettier && npm run lint && npm run build && npm run coverage:fast",
|
||||
"precommit": "npm run prettier && npm run lint && npm run build && npm run test:fast",
|
||||
"prepush": "npm run build && npm run coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^7.1.1",
|
||||
"better-sqlite3": "^7.1.2",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"inversify": "^5.0.1",
|
||||
|
@ -53,7 +53,7 @@
|
|||
"node-fetch": "^2.6.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"typeorm": "^0.2.29",
|
||||
"uuid": "^8.3.1"
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.0.0-beta.54",
|
||||
|
@ -61,40 +61,41 @@
|
|||
"@types/better-sqlite3": "^5.4.1",
|
||||
"@types/chai": "^4.2.14",
|
||||
"@types/chai-fs": "^2.0.2",
|
||||
"@types/fs-extra": "^9.0.3",
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/minimist": "^1.2.1",
|
||||
"@types/mocha": "^8.0.3",
|
||||
"@types/node": "^12.19.3",
|
||||
"@types/mocha": "^8.2.0",
|
||||
"@types/node": "^14.14.16",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/sinon": "^9.0.8",
|
||||
"@types/sinon": "^9.0.10",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/webpack": "^4.41.24",
|
||||
"@typescript-eslint/eslint-plugin": "^4.7.0",
|
||||
"@typescript-eslint/parser": "^4.7.0",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@typescript-eslint/eslint-plugin": "^4.11.1",
|
||||
"@typescript-eslint/parser": "^4.11.1",
|
||||
"chai": "^4.2.0",
|
||||
"chai-fs": "^2.0.0",
|
||||
"chokidar": "^3.4.3",
|
||||
"concurrently": "^5.3.0",
|
||||
"electron": "^10.1.5",
|
||||
"electron-rebuild": "^2.3.2",
|
||||
"eslint": "^7.13.0",
|
||||
"eslint-config-prettier": "^6.15.0",
|
||||
"electron": "^10.2.0",
|
||||
"electron-mocha": "^10.0.0",
|
||||
"electron-rebuild": "^2.3.4",
|
||||
"eslint": "^7.16.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"fast-check": "^2.6.1",
|
||||
"fast-check": "^2.10.0",
|
||||
"glob": "^7.1.6",
|
||||
"handlebars": "^4.7.6",
|
||||
"husky": "^4.3.0",
|
||||
"husky": "^4.3.6",
|
||||
"lodash": "^4.17.20",
|
||||
"mocha": "^8.2.1",
|
||||
"nock": "^13.0.4",
|
||||
"nock": "^13.0.5",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.1.2",
|
||||
"rewiremock": "^3.14.3",
|
||||
"sinon": "^9.2.1",
|
||||
"spectron": "^12.0.0",
|
||||
"svelte": "^3.29.6",
|
||||
"prettier": "^2.2.1",
|
||||
"sinon": "^9.2.2",
|
||||
"svelte": "^3.31.0",
|
||||
"svelte-loader": "^2.13.6",
|
||||
"ts-loader": "^8.0.11",
|
||||
"typescript": "^4.0.5",
|
||||
"ts-loader": "^8.0.12",
|
||||
"typescript": "^4.1.3",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
|
|
|
@ -6,7 +6,6 @@ const ignoreList = [
|
|||
|
||||
/^\/\.nyc_output($|\/)/,
|
||||
/^\/declarations($|\/)/,
|
||||
/^\/mocks($|\/)/,
|
||||
/^\/templates($|\/)/,
|
||||
/^\/test-paths($|\/)/,
|
||||
/^\/types($|\/)/,
|
||||
|
@ -15,15 +14,17 @@ const ignoreList = [
|
|||
|
||||
/^\/\.editorconfig/,
|
||||
/^\/\.eslintignore/,
|
||||
/^\/\.prettierignore/,
|
||||
/^\/\.eslintrc\.json/,
|
||||
/^\/\.gitignore/,
|
||||
/^\/\.mocharc\.yml/,
|
||||
/^\/\.mocharc\.json/,
|
||||
/^\/\.nycrc\.yml/,
|
||||
/^\/\.prettierrc\.yml/,
|
||||
/^\/CONTRIBUTING\.md/,
|
||||
/^\/ormconfig\.yml/,
|
||||
/^\/package-lock\.json/,
|
||||
/^\/tsconfig\.json/,
|
||||
/^\/tsconfig\.renderer\.json/,
|
||||
|
||||
/^\/node_modules\/\.cache($|\/)/,
|
||||
// test and mock files:
|
||||
|
@ -36,8 +37,10 @@ const ignoreList = [
|
|||
|
||||
const name = packageJson.productName;
|
||||
|
||||
if(name !== 'Renai') {
|
||||
throw new TypeError(`The product name "${name}" in package.json is not "Renai"! Change it before building but do not commit it.`)
|
||||
if (name !== 'Renai') {
|
||||
throw new TypeError(
|
||||
`The product name "${name}" in package.json is not "Renai"! Change it before building but do not commit it.`
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import { expect } from 'chai';
|
||||
import rewiremock from 'rewiremock';
|
||||
|
||||
import 'mocha';
|
||||
import { IApplicationContext } from './main/test/i-application-context';
|
||||
import { createApplication } from './main/test/spectron-util';
|
||||
|
||||
rewiremock.disable();
|
||||
|
||||
describe('Application @spectron', function () {
|
||||
this.timeout(20000);
|
||||
|
||||
before(function (this: IApplicationContext) {
|
||||
this.app = createApplication();
|
||||
return this.app.start();
|
||||
});
|
||||
|
||||
after(function (this: IApplicationContext) {
|
||||
if (this.app && this.app.isRunning()) {
|
||||
return this.app.stop();
|
||||
}
|
||||
});
|
||||
|
||||
it('shows an initial window', function (this: IApplicationContext) {
|
||||
if (!this.app) {
|
||||
throw Error('this.app is falsy');
|
||||
}
|
||||
return this.app.client.getWindowCount().then((count: number) => {
|
||||
expect(count).to.be.gte(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,19 +1,8 @@
|
|||
import rewiremock from 'rewiremock';
|
||||
import '../../../mocks/electron';
|
||||
|
||||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { Database, getConnection } from './database';
|
||||
|
||||
describe('Database Service', () => {
|
||||
before(() => {
|
||||
rewiremock.enable();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
rewiremock.disable();
|
||||
});
|
||||
|
||||
it('returns a connection', async () => {
|
||||
const libraryConnection = await getConnection(Database.LIBRARY);
|
||||
expect(libraryConnection).to.not.equal(undefined);
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
import rewiremock from 'rewiremock';
|
||||
import '../../../mocks/electron';
|
||||
|
||||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { isDev } from './env';
|
||||
|
||||
export function setDev(dev = true): void {
|
||||
if (dev) {
|
||||
process.argv.push('--env=dev');
|
||||
process.argv.splice(2, 0, '--env=dev');
|
||||
} else {
|
||||
process.argv = process.argv.filter((value) => value !== '--env=dev');
|
||||
}
|
||||
}
|
||||
|
||||
describe('Environment Service', () => {
|
||||
before(() => {
|
||||
rewiremock.enable();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
rewiremock.disable();
|
||||
});
|
||||
|
||||
it('correctly identifies the development process argument', () => {
|
||||
setDev();
|
||||
expect(isDev()).to.be.true;
|
||||
|
|
|
@ -35,7 +35,7 @@ export abstract class UrlAppWindow extends AppWindow implements IUrlAppWindow {
|
|||
const waitInterval = 1000;
|
||||
let failedLoad = true;
|
||||
do {
|
||||
await new Promise((resolve) => {
|
||||
await new Promise<void>((resolve) => {
|
||||
if (!this._window) {
|
||||
throw new WindowClosedError();
|
||||
}
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
import rewiremock from 'rewiremock';
|
||||
import '../../../../mocks/electron';
|
||||
|
||||
import { createInterface, Interface } from 'readline';
|
||||
import chai, { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import chaiFs from 'chai-fs';
|
||||
import fc from 'fast-check';
|
||||
import fs from 'fs-extra';
|
||||
import { container } from '../../core/container';
|
||||
import { setDev } from '../../core/env.spec';
|
||||
import { ILogger } from './i-logger';
|
||||
import fs from 'fs-extra';
|
||||
import { createInterface, Interface } from 'readline';
|
||||
import fc from 'fast-check';
|
||||
import { LogLevel } from './log-level';
|
||||
import chaiFs from 'chai-fs';
|
||||
|
||||
chai.use(chaiFs);
|
||||
|
||||
|
@ -44,14 +41,6 @@ describe('Logger Service', () => {
|
|||
|
||||
const logLevelNumberArbitrary = fc.constantFrom(...logLevelsNumber);
|
||||
|
||||
before(() => {
|
||||
rewiremock.enable();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
rewiremock.disable();
|
||||
});
|
||||
|
||||
it('creates log files', () => {
|
||||
const logger: ILogger = container.get('logger');
|
||||
|
||||
|
@ -68,8 +57,18 @@ describe('Logger Service', () => {
|
|||
it("default log file doesn't get bigger than 50KB @slow", async () => {
|
||||
const logger: ILogger = container.get('logger');
|
||||
|
||||
for (let i = 0; i < maxLogSize; i++) {
|
||||
let prevLogFileSize = (await fs.stat(logger.getLogFile())).size;
|
||||
let minNumberOfLines = maxLogSize;
|
||||
const sizeIncreases = [];
|
||||
for (let i = 0; i <= minNumberOfLines; i++) {
|
||||
await logger.log(4, 'your waifu is trash');
|
||||
const currLogFileSize = (await fs.stat(logger.getLogFile())).size;
|
||||
const sizeIncrease = currLogFileSize - prevLogFileSize;
|
||||
if (sizeIncrease) {
|
||||
sizeIncreases.push(sizeIncrease);
|
||||
minNumberOfLines = maxLogSize / (sizeIncreases.reduce((sum, e) => sum + e, 0) / sizeIncreases.length);
|
||||
}
|
||||
prevLogFileSize = currLogFileSize;
|
||||
}
|
||||
|
||||
const logFileStats = await fs.stat(logger.getLogFile());
|
||||
|
@ -79,12 +78,22 @@ describe('Logger Service', () => {
|
|||
it("exception log file doesn't get bigger than 50KB @slow", async () => {
|
||||
const logger: ILogger = container.get('logger');
|
||||
|
||||
for (let i = 0; i < maxLogSize; ++i) {
|
||||
let prevLogFileSize = (await fs.stat(logger.getExceptionsLogFile())).size;
|
||||
let minNumberOfLines = maxLogSize;
|
||||
const sizeIncreases = [];
|
||||
for (let i = 0; i <= minNumberOfLines; i++) {
|
||||
await logger.exception(new Error('your waifu is trash'));
|
||||
const currLogFileSize = (await fs.stat(logger.getExceptionsLogFile())).size;
|
||||
const sizeIncrease = currLogFileSize - prevLogFileSize;
|
||||
if (sizeIncrease) {
|
||||
sizeIncreases.push(sizeIncrease);
|
||||
minNumberOfLines = maxLogSize / (sizeIncreases.reduce((sum, e) => sum + e, 0) / sizeIncreases.length);
|
||||
}
|
||||
prevLogFileSize = currLogFileSize;
|
||||
}
|
||||
|
||||
const logFileStats = await fs.stat(logger.getLogFile());
|
||||
expect(logFileStats.size).lessThan(maxLogSize, 'log is bigger than its max size');
|
||||
const logFileStats = await fs.stat(logger.getExceptionsLogFile());
|
||||
expect(logFileStats.size).lessThan(maxLogSize, 'exception log is bigger than its max size');
|
||||
}).timeout(15000);
|
||||
|
||||
it('logs different levels directly', () => {
|
||||
|
|
|
@ -180,11 +180,17 @@ export class NhentaiAppWindow extends UrlAppWindow implements INhentaiAppWindow
|
|||
}
|
||||
|
||||
private async getBookTorrent(bookUrl: string): Promise<IFavorite> {
|
||||
if (!this._window) {
|
||||
throw new WindowClosedError();
|
||||
}
|
||||
const galleryId = getGalleryId(bookUrl);
|
||||
const fileName = `${galleryId}.torrent`;
|
||||
const filePath = path.resolve(os.tmpdir(), fileName);
|
||||
await this.loadUrlSafe(bookUrl);
|
||||
await new Promise<string>((resolve, reject) => {
|
||||
const downloadLink: string = (await this._window.webContents.executeJavaScript(
|
||||
`document.getElementById('${downloadLinkId}').href`
|
||||
)) as string;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
if (!this._window) {
|
||||
throw new WindowClosedError();
|
||||
}
|
||||
|
@ -206,7 +212,7 @@ export class NhentaiAppWindow extends UrlAppWindow implements INhentaiAppWindow
|
|||
item.resume();
|
||||
});
|
||||
});
|
||||
void this._window.webContents.executeJavaScript(`document.getElementById('${downloadLinkId}').click()`);
|
||||
void this.loadUrlSafe(downloadLink);
|
||||
});
|
||||
|
||||
const readable = createReadStream(filePath, { emitClose: true });
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import rewiremock from 'rewiremock';
|
||||
import '../../../../mocks/electron';
|
||||
|
||||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { container } from '../../core/container';
|
||||
|
@ -9,14 +6,6 @@ import { IStore } from './i-store';
|
|||
describe('Store Service', function () {
|
||||
this.timeout(10000);
|
||||
|
||||
before(() => {
|
||||
rewiremock.enable();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
rewiremock.disable();
|
||||
});
|
||||
|
||||
it('loads saved data', () => {
|
||||
const store: IStore = container.get('store');
|
||||
const testData = {
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
import { Context } from 'mocha';
|
||||
import { Application } from 'spectron';
|
||||
|
||||
export interface IApplicationContext extends Context {
|
||||
app?: Application;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import * as electron from 'electron';
|
||||
import { Application } from 'spectron';
|
||||
|
||||
export function createApplication(): Application {
|
||||
return new Application({
|
||||
path: ((electron as unknown) as { default: string }).default,
|
||||
args: ['.', '--enable-logging'],
|
||||
});
|
||||
}
|
|
@ -15,5 +15,5 @@
|
|||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": ["declarations/**/*.ts", "types/**/*.ts", "src/**/*.ts", "mocks/**/*.ts"]
|
||||
"include": ["declarations/**/*.ts", "types/**/*.ts", "src/**/*.ts"]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
/**
|
||||
* @see MethodDecorator
|
||||
*/
|
||||
type IpcControllerMethodDecorator = <T>(target: IIpcController, propertyKey: string, descriptor: TypedPropertyDescriptor<T>) => void
|
||||
type IpcControllerMethodDecorator = <T>(
|
||||
target: IIpcController,
|
||||
propertyKey: string,
|
||||
descriptor: TypedPropertyDescriptor<T>
|
||||
) => void;
|
||||
|
|
Loading…
Reference in New Issue