playwright-windows-wrapper 1.0.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/README.md +23 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +172 -0
- package/package.json +28 -0
- package/src/index.ts +194 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# playwright-windows-wrapper
|
|
2
|
+
|
|
3
|
+
A unified, hybrid test automation wrapper that bridges **Playwright** (for web automation) and **Appium/WinAppDriver** (for native Windows desktop applications). Write single-script end-to-end flows that seamlessly jump between standard browsers and native `.exe` applications.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Key Features
|
|
8
|
+
|
|
9
|
+
* **Unified API:** Control both web elements and native desktop UI components using one client interface.
|
|
10
|
+
* **Advanced Desktop Interactions:** Right-clicks, double-clicks, drag-and-drop, and hardware keyboard shortcuts (`Ctrl + A`, etc.) mapped natively to Windows.
|
|
11
|
+
* **Window Controls:** Maximize, minimize, and inspect native application windows easily.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🛠️ Prerequisites
|
|
16
|
+
|
|
17
|
+
Because Windows desktop automation requires access to OS-level accessibility trees, you must configure your host machine before running desktop tests:
|
|
18
|
+
|
|
19
|
+
1. **Enable Windows Developer Mode:**
|
|
20
|
+
Go to **Settings > Update & Security > For developers** and toggle **Developer Mode** to **On**.
|
|
21
|
+
2. **Install Appium Globally:**
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g appium
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const playwright_1 = require("playwright");
|
|
4
|
+
const webdriverio_1 = require("webdriverio");
|
|
5
|
+
const webdriverio_2 = require("webdriverio"); // Used for native key simulations
|
|
6
|
+
class UltimateAutomationWrapper {
|
|
7
|
+
webBrowser = null;
|
|
8
|
+
webPage = null;
|
|
9
|
+
desktopSession = null;
|
|
10
|
+
// ==========================================
|
|
11
|
+
// INITIALIZATION
|
|
12
|
+
// ==========================================
|
|
13
|
+
async initWeb() {
|
|
14
|
+
this.webBrowser = await playwright_1.chromium.launch({ headless: false });
|
|
15
|
+
this.webPage = await this.webBrowser.newPage();
|
|
16
|
+
return this.webPage;
|
|
17
|
+
}
|
|
18
|
+
async initDesktop(appPathOrId) {
|
|
19
|
+
const appiumOptions = {
|
|
20
|
+
hostname: '127.0.0.1',
|
|
21
|
+
port: 4723,
|
|
22
|
+
logLevel: 'error',
|
|
23
|
+
capabilities: {
|
|
24
|
+
platformName: 'Windows',
|
|
25
|
+
'appium:automationName': 'windows',
|
|
26
|
+
'appium:app': appPathOrId,
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
this.desktopSession = await (0, webdriverio_1.remote)(appiumOptions);
|
|
30
|
+
return this.desktopSession;
|
|
31
|
+
}
|
|
32
|
+
// ==========================================
|
|
33
|
+
// WINDOW STATE OPERATIONS
|
|
34
|
+
// ==========================================
|
|
35
|
+
async windowMaximize() {
|
|
36
|
+
if (!this.desktopSession)
|
|
37
|
+
throw new Error('Desktop session uninitialized.');
|
|
38
|
+
await this.desktopSession.maximizeWindow();
|
|
39
|
+
}
|
|
40
|
+
async windowMinimize() {
|
|
41
|
+
if (!this.desktopSession)
|
|
42
|
+
throw new Error('Desktop session uninitialized.');
|
|
43
|
+
await this.desktopSession.minimizeWindow();
|
|
44
|
+
}
|
|
45
|
+
async getWindowTitle() {
|
|
46
|
+
if (!this.desktopSession)
|
|
47
|
+
throw new Error('Desktop session uninitialized.');
|
|
48
|
+
return await this.desktopSession.getTitle();
|
|
49
|
+
}
|
|
50
|
+
// ==========================================
|
|
51
|
+
// BASIC & ADVANCED MOUSE OPERATIONS
|
|
52
|
+
// ==========================================
|
|
53
|
+
async click(selector) {
|
|
54
|
+
const el = await this.desktopSession.$(selector);
|
|
55
|
+
await el.click();
|
|
56
|
+
}
|
|
57
|
+
async doubleClick(selector) {
|
|
58
|
+
const el = await this.desktopSession.$(selector);
|
|
59
|
+
await el.doubleClick();
|
|
60
|
+
}
|
|
61
|
+
async rightClick(selector) {
|
|
62
|
+
const el = await this.desktopSession.$(selector);
|
|
63
|
+
// Uses WebdriverIO / Appium W3C Actions for a custom context-click context
|
|
64
|
+
await this.desktopSession.action('pointer')
|
|
65
|
+
.move({ origin: el })
|
|
66
|
+
.down({ button: 2 }) // 2 is the Right Mouse Button
|
|
67
|
+
.up({ button: 2 })
|
|
68
|
+
.perform();
|
|
69
|
+
}
|
|
70
|
+
async dragAndDrop(sourceSelector, targetSelector) {
|
|
71
|
+
const source = await this.desktopSession.$(sourceSelector);
|
|
72
|
+
const target = await this.desktopSession.$(targetSelector);
|
|
73
|
+
await this.desktopSession.action('pointer')
|
|
74
|
+
.move({ origin: source })
|
|
75
|
+
.down({ button: 0 }) // Left click hold
|
|
76
|
+
.pause(100)
|
|
77
|
+
.move({ origin: target, duration: 500 }) // Smooth drag
|
|
78
|
+
.up({ button: 0 }) // Release
|
|
79
|
+
.perform();
|
|
80
|
+
}
|
|
81
|
+
// ==========================================
|
|
82
|
+
// KEYBOARD & INPUT OPERATIONS
|
|
83
|
+
// ==========================================
|
|
84
|
+
async typeText(selector, text) {
|
|
85
|
+
const el = await this.desktopSession.$(selector);
|
|
86
|
+
await el.setValue(text);
|
|
87
|
+
}
|
|
88
|
+
async clearInput(selector) {
|
|
89
|
+
const el = await this.desktopSession.$(selector);
|
|
90
|
+
await el.clearValue();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Simulates hotkey combinations (e.g., Ctrl + S, Ctrl + A)
|
|
94
|
+
*/
|
|
95
|
+
async pressShortcut(modifier, letter) {
|
|
96
|
+
// Maps semantic keys to WebdriverIO Key Enums
|
|
97
|
+
const modKey = modifier.toLowerCase() === 'ctrl' ? webdriverio_2.Key.Control : webdriverio_2.Key.Alt;
|
|
98
|
+
await this.desktopSession.action('key')
|
|
99
|
+
.down(modKey)
|
|
100
|
+
.down(letter)
|
|
101
|
+
.up(letter)
|
|
102
|
+
.up(modKey)
|
|
103
|
+
.perform();
|
|
104
|
+
}
|
|
105
|
+
async pressGlobalKey(keyName) {
|
|
106
|
+
// Sends independent key strokes like 'Enter', 'Tab', 'Escape'
|
|
107
|
+
await this.desktopSession.keys([keyName]);
|
|
108
|
+
}
|
|
109
|
+
// ==========================================
|
|
110
|
+
// INSPECTION & ASSERTION OPERATIONS
|
|
111
|
+
// ==========================================
|
|
112
|
+
async isElementDisplayed(selector) {
|
|
113
|
+
const el = await this.desktopSession.$(selector);
|
|
114
|
+
return await el.isDisplayed();
|
|
115
|
+
}
|
|
116
|
+
async isElementEnabled(selector) {
|
|
117
|
+
const el = await this.desktopSession.$(selector);
|
|
118
|
+
return await el.isEnabled();
|
|
119
|
+
}
|
|
120
|
+
async getElementText(selector) {
|
|
121
|
+
const el = await this.desktopSession.$(selector);
|
|
122
|
+
return await el.getText();
|
|
123
|
+
}
|
|
124
|
+
// ==========================================
|
|
125
|
+
// TEARDOWN
|
|
126
|
+
// ==========================================
|
|
127
|
+
async closeAll() {
|
|
128
|
+
if (this.webBrowser)
|
|
129
|
+
await this.webBrowser.close();
|
|
130
|
+
if (this.desktopSession)
|
|
131
|
+
await this.desktopSession.deleteSession();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ==========================================
|
|
135
|
+
// RUNNING THE WORKFLOW IN WINDOWS CALC & NOTEPAD
|
|
136
|
+
// ==========================================
|
|
137
|
+
(async () => {
|
|
138
|
+
const driver = new UltimateAutomationWrapper();
|
|
139
|
+
try {
|
|
140
|
+
console.log('--- Instantiating Windows Calculator App ---');
|
|
141
|
+
// 'Microsoft.WindowsCalculator_8wekyb3d8bbwe!App' is the AppID for standard Win10/Win11 calc
|
|
142
|
+
await driver.initDesktop('Microsoft.WindowsCalculator_8wekyb3d8bbwe!App');
|
|
143
|
+
await driver.windowMaximize();
|
|
144
|
+
console.log('Performing native UI Math: 7 x 8 =');
|
|
145
|
+
await driver.click('~num7Button'); // '~' is WebdriverIO shorthand for AccessibilityId
|
|
146
|
+
await driver.click('~multiplyButton');
|
|
147
|
+
await driver.click('~num8Button');
|
|
148
|
+
await driver.click('~equalButton');
|
|
149
|
+
const result = await driver.getElementText('~CalculatorResults');
|
|
150
|
+
console.log(`Retrieved UI Text State: "${result}"`);
|
|
151
|
+
// Clean up Calculator session to open up Notepad
|
|
152
|
+
await driver.closeAll();
|
|
153
|
+
console.log('\n--- Instantiating Windows Notepad App ---');
|
|
154
|
+
await driver.initDesktop('notepad.exe');
|
|
155
|
+
console.log('Typing Text & Clearing Input...');
|
|
156
|
+
await driver.typeText('//*[@Name="Text Editor"]', 'This text will be replaced.');
|
|
157
|
+
await driver.clearInput('//*[@Name="Text Editor"]');
|
|
158
|
+
console.log('Typing formal entry...');
|
|
159
|
+
await driver.typeText('//*[@Name="Text Editor"]', 'Final clean text string automation input.');
|
|
160
|
+
console.log('Executing Windows Hotkeys (Ctrl + A)...');
|
|
161
|
+
await driver.pressShortcut('ctrl', 'a');
|
|
162
|
+
console.log('Sending Backspace key to erase execution selection...');
|
|
163
|
+
await driver.pressGlobalKey(webdriverio_2.Key.Backspace);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
console.error('Automation Runtime Failure:', err);
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
await driver.closeAll();
|
|
170
|
+
console.log('Wrapper execution cleaned up safely.');
|
|
171
|
+
}
|
|
172
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "playwright-windows-wrapper",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A unified automation wrapper combining Playwright and Appium for hybrid web and Windows native testing.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "npx tsc",
|
|
9
|
+
"prepare": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"playwright",
|
|
13
|
+
"appium",
|
|
14
|
+
"windows",
|
|
15
|
+
"automation",
|
|
16
|
+
"testing"
|
|
17
|
+
],
|
|
18
|
+
"author": "Your Name",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"appium": "^2.0.0",
|
|
22
|
+
"playwright": "^1.40.0",
|
|
23
|
+
"webdriverio": "^8.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"typescript": "^5.0.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { chromium, Browser as PWBrowser, Page as PWPage } from 'playwright';
|
|
2
|
+
import { remote, RemoteOptions, Browser as AppiumBrowser } from 'webdriverio';
|
|
3
|
+
import { Key } from 'webdriverio'; // Used for native key simulations
|
|
4
|
+
|
|
5
|
+
class UltimateAutomationWrapper {
|
|
6
|
+
private webBrowser: PWBrowser | null = null;
|
|
7
|
+
private webPage: PWPage | null = null;
|
|
8
|
+
private desktopSession: AppiumBrowser | null = null;
|
|
9
|
+
|
|
10
|
+
// ==========================================
|
|
11
|
+
// INITIALIZATION
|
|
12
|
+
// ==========================================
|
|
13
|
+
async initWeb(): Promise<PWPage> {
|
|
14
|
+
this.webBrowser = await chromium.launch({ headless: false });
|
|
15
|
+
this.webPage = await this.webBrowser.newPage();
|
|
16
|
+
return this.webPage;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async initDesktop(appPathOrId: string): Promise<AppiumBrowser> {
|
|
20
|
+
const appiumOptions: RemoteOptions = {
|
|
21
|
+
hostname: '127.0.0.1',
|
|
22
|
+
port: 4723,
|
|
23
|
+
logLevel: 'error',
|
|
24
|
+
capabilities: {
|
|
25
|
+
platformName: 'Windows',
|
|
26
|
+
'appium:automationName': 'windows',
|
|
27
|
+
'appium:app': appPathOrId,
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
this.desktopSession = await remote(appiumOptions);
|
|
31
|
+
return this.desktopSession;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ==========================================
|
|
35
|
+
// WINDOW STATE OPERATIONS
|
|
36
|
+
// ==========================================
|
|
37
|
+
async windowMaximize(): Promise<void> {
|
|
38
|
+
if (!this.desktopSession) throw new Error('Desktop session uninitialized.');
|
|
39
|
+
await this.desktopSession.maximizeWindow();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async windowMinimize(): Promise<void> {
|
|
43
|
+
if (!this.desktopSession) throw new Error('Desktop session uninitialized.');
|
|
44
|
+
await this.desktopSession.minimizeWindow();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async getWindowTitle(): Promise<string> {
|
|
48
|
+
if (!this.desktopSession) throw new Error('Desktop session uninitialized.');
|
|
49
|
+
return await this.desktopSession.getTitle();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ==========================================
|
|
53
|
+
// BASIC & ADVANCED MOUSE OPERATIONS
|
|
54
|
+
// ==========================================
|
|
55
|
+
async click(selector: string): Promise<void> {
|
|
56
|
+
const el = await this.desktopSession!.$(selector);
|
|
57
|
+
await el.click();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async doubleClick(selector: string): Promise<void> {
|
|
61
|
+
const el = await this.desktopSession!.$(selector);
|
|
62
|
+
await el.doubleClick();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async rightClick(selector: string): Promise<void> {
|
|
66
|
+
const el = await this.desktopSession!.$(selector);
|
|
67
|
+
// Uses WebdriverIO / Appium W3C Actions for a custom context-click context
|
|
68
|
+
await this.desktopSession!.action('pointer')
|
|
69
|
+
.move({ origin: el })
|
|
70
|
+
.down({ button: 2 }) // 2 is the Right Mouse Button
|
|
71
|
+
.up({ button: 2 })
|
|
72
|
+
.perform();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async dragAndDrop(sourceSelector: string, targetSelector: string): Promise<void> {
|
|
76
|
+
const source = await this.desktopSession!.$(sourceSelector);
|
|
77
|
+
const target = await this.desktopSession!.$(targetSelector);
|
|
78
|
+
|
|
79
|
+
await this.desktopSession!.action('pointer')
|
|
80
|
+
.move({ origin: source })
|
|
81
|
+
.down({ button: 0 }) // Left click hold
|
|
82
|
+
.pause(100)
|
|
83
|
+
.move({ origin: target, duration: 500 }) // Smooth drag
|
|
84
|
+
.up({ button: 0 }) // Release
|
|
85
|
+
.perform();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ==========================================
|
|
89
|
+
// KEYBOARD & INPUT OPERATIONS
|
|
90
|
+
// ==========================================
|
|
91
|
+
async typeText(selector: string, text: string): Promise<void> {
|
|
92
|
+
const el = await this.desktopSession!.$(selector);
|
|
93
|
+
await el.setValue(text);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async clearInput(selector: string): Promise<void> {
|
|
97
|
+
const el = await this.desktopSession!.$(selector);
|
|
98
|
+
await el.clearValue();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Simulates hotkey combinations (e.g., Ctrl + S, Ctrl + A)
|
|
103
|
+
*/
|
|
104
|
+
async pressShortcut(modifier: string, letter: string): Promise<void> {
|
|
105
|
+
// Maps semantic keys to WebdriverIO Key Enums
|
|
106
|
+
const modKey = modifier.toLowerCase() === 'ctrl' ? Key.Control : Key.Alt;
|
|
107
|
+
|
|
108
|
+
await this.desktopSession!.action('key')
|
|
109
|
+
.down(modKey)
|
|
110
|
+
.down(letter)
|
|
111
|
+
.up(letter)
|
|
112
|
+
.up(modKey)
|
|
113
|
+
.perform();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async pressGlobalKey(keyName: string): Promise<void> {
|
|
117
|
+
// Sends independent key strokes like 'Enter', 'Tab', 'Escape'
|
|
118
|
+
await this.desktopSession!.keys([keyName]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ==========================================
|
|
122
|
+
// INSPECTION & ASSERTION OPERATIONS
|
|
123
|
+
// ==========================================
|
|
124
|
+
async isElementDisplayed(selector: string): Promise<boolean> {
|
|
125
|
+
const el = await this.desktopSession!.$(selector);
|
|
126
|
+
return await el.isDisplayed();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async isElementEnabled(selector: string): Promise<boolean> {
|
|
130
|
+
const el = await this.desktopSession!.$(selector);
|
|
131
|
+
return await el.isEnabled();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async getElementText(selector: string): Promise<string> {
|
|
135
|
+
const el = await this.desktopSession!.$(selector);
|
|
136
|
+
return await el.getText();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ==========================================
|
|
140
|
+
// TEARDOWN
|
|
141
|
+
// ==========================================
|
|
142
|
+
async closeAll(): Promise<void> {
|
|
143
|
+
if (this.webBrowser) await this.webBrowser.close();
|
|
144
|
+
if (this.desktopSession) await this.desktopSession.deleteSession();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ==========================================
|
|
149
|
+
// RUNNING THE WORKFLOW IN WINDOWS CALC & NOTEPAD
|
|
150
|
+
// ==========================================
|
|
151
|
+
(async () => {
|
|
152
|
+
const driver = new UltimateAutomationWrapper();
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
console.log('--- Instantiating Windows Calculator App ---');
|
|
156
|
+
// 'Microsoft.WindowsCalculator_8wekyb3d8bbwe!App' is the AppID for standard Win10/Win11 calc
|
|
157
|
+
await driver.initDesktop('Microsoft.WindowsCalculator_8wekyb3d8bbwe!App');
|
|
158
|
+
await driver.windowMaximize();
|
|
159
|
+
|
|
160
|
+
console.log('Performing native UI Math: 7 x 8 =');
|
|
161
|
+
await driver.click('~num7Button'); // '~' is WebdriverIO shorthand for AccessibilityId
|
|
162
|
+
await driver.click('~multiplyButton');
|
|
163
|
+
await driver.click('~num8Button');
|
|
164
|
+
await driver.click('~equalButton');
|
|
165
|
+
|
|
166
|
+
const result = await driver.getElementText('~CalculatorResults');
|
|
167
|
+
console.log(`Retrieved UI Text State: "${result}"`);
|
|
168
|
+
|
|
169
|
+
// Clean up Calculator session to open up Notepad
|
|
170
|
+
await driver.closeAll();
|
|
171
|
+
|
|
172
|
+
console.log('\n--- Instantiating Windows Notepad App ---');
|
|
173
|
+
await driver.initDesktop('notepad.exe');
|
|
174
|
+
|
|
175
|
+
console.log('Typing Text & Clearing Input...');
|
|
176
|
+
await driver.typeText('//*[@Name="Text Editor"]', 'This text will be replaced.');
|
|
177
|
+
await driver.clearInput('//*[@Name="Text Editor"]');
|
|
178
|
+
|
|
179
|
+
console.log('Typing formal entry...');
|
|
180
|
+
await driver.typeText('//*[@Name="Text Editor"]', 'Final clean text string automation input.');
|
|
181
|
+
|
|
182
|
+
console.log('Executing Windows Hotkeys (Ctrl + A)...');
|
|
183
|
+
await driver.pressShortcut('ctrl', 'a');
|
|
184
|
+
|
|
185
|
+
console.log('Sending Backspace key to erase execution selection...');
|
|
186
|
+
await driver.pressGlobalKey(Key.Backspace);
|
|
187
|
+
|
|
188
|
+
} catch (err) {
|
|
189
|
+
console.error('Automation Runtime Failure:', err);
|
|
190
|
+
} finally {
|
|
191
|
+
await driver.closeAll();
|
|
192
|
+
console.log('Wrapper execution cleaned up safely.');
|
|
193
|
+
}
|
|
194
|
+
})();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"declaration": true, // Generates corresponding '.d.ts' file for type safety
|
|
7
|
+
"outDir": "./dist", // Redirect output structure to the directory
|
|
8
|
+
"rootDir": "./src", // Only look for TypeScript files inside /src
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|