Skip to content

Commit 0ba27f8

Browse files
committed
File exisits check
1 parent cc829e0 commit 0ba27f8

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-0
lines changed

Tests/api-definition-tests.ts

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
import TKUnit = require("Tests/TKUnit");
2+
import fs = require("file-system");
3+
import xmlModule = require("xml");
4+
import file_access_module = require("file-system/file-system-access");
5+
import types = require("utils/types");
6+
import app = require("application");
7+
import trace = require("trace");
8+
9+
export var traceCategory = "definitionTest";
10+
11+
var ignoredModules = [
12+
"camera",
13+
"media-player",
14+
"ui/pagesNew",
15+
"ui/scroll-view",
16+
"ui/slide-out",
17+
"ui/web-view"];
18+
19+
var whitelist = {
20+
common: [
21+
"Function not defined: application:.onLaunch",
22+
"Function not defined: application:.onSuspend",
23+
"Function not defined: application:.onResume",
24+
"Function not defined: application:.onExit",
25+
"Function not defined: application:.onLowMemory",
26+
],
27+
android: [
28+
"Variable not defined: application:.ios",
29+
"Cannot find submodule: utils/utils:ios when searching for utils/utils:ios.collections.jsArrayToNSArray",
30+
"Cannot find submodule: utils/utils:ios when searching for utils/utils:ios.collections.nsArrayToJSArray",
31+
"Cannot find submodule: utils/utils:ios when searching for utils/utils:ios.getColor",
32+
"Cannot find submodule: utils/utils:ios when searching for utils/utils:ios.getActualHeight"],
33+
ios: [
34+
"Variable not defined: application:.android",
35+
"Class not defined: ui/panels/panel:.NativePanel",
36+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.collections.stringArrayToStringSet",
37+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.collections.stringSetToStringArray",
38+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.UNSPECIFIED",
39+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.EXACTLY",
40+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.AT_MOST",
41+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getMeasureSpecMode",
42+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getMeasureSpecSize",
43+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.makeMeasureSpec",
44+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getDisplayMetrics",
45+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getDisplayDensity",
46+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getDevicePixels",
47+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.layout.getDeviceIndependentPixels",
48+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.id.home",
49+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.resources.getDrawableId",
50+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.resources.getStringId",
51+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.resources.getId",
52+
"Cannot find submodule: utils/utils:ad when searching for utils/utils:ad.async", ],
53+
};
54+
55+
interface FuncInfo {
56+
name: string;
57+
paramsCount: number
58+
}
59+
60+
export var test_all_public_definitions_are_defined = function () {
61+
// Read specified CSS file from the current folder and assign it to the specified page
62+
var path = fs.path.join(fs.knownFolders.currentApp().path, "tns_modules", "Tests", "api.xml");
63+
64+
if (!fs.File.exists(path)) {
65+
throw new Error("api.xml file not found");
66+
}
67+
68+
var fileAccess = new file_access_module.FileSystemAccess();
69+
var xml: string;
70+
// Read the XML file.
71+
fileAccess.readText(path, (text) => {
72+
xml = text;
73+
});
74+
75+
parseAndTest(xml)
76+
};
77+
78+
function applyWhitelist(erros: Array<string>): Array<string> {
79+
var list = app.android ? whitelist.android : whitelist.ios;
80+
list = list.concat(whitelist.common);
81+
82+
return erros.filter((val, index, all) => {
83+
return list.indexOf(val) < 0;
84+
});
85+
}
86+
87+
function parseAndTest(xml: string) {
88+
var count: number = 0;
89+
var moduleNesting = 0;
90+
var currentModule = undefined;
91+
var currentModuleName: string = undefined;
92+
93+
var subModuleStack = [];
94+
var functionStack = new Array<FuncInfo>();
95+
var errors = new Array<string>();
96+
97+
var getModuleToCheck = function (name: string): Object {
98+
var moduleToCheck = currentModule;
99+
for (var i = 0; i < subModuleStack.length; i++) {
100+
moduleToCheck = moduleToCheck[subModuleStack[i]];
101+
if (!moduleToCheck) {
102+
var missingSubmodule = currentModuleName + ":" + subModuleStack.slice(0, i + 1).join(".");
103+
errors.push("Cannot find submodule: " + missingSubmodule + " when searching for " + getFullName(name));
104+
return undefined;
105+
}
106+
}
107+
108+
return moduleToCheck;
109+
}
110+
111+
var getFullName = function (name: string) {
112+
if (subModuleStack.length > 0) {
113+
return currentModuleName + ":" + subModuleStack.join(".") + "." + name;
114+
}
115+
else {
116+
return currentModuleName + ":" + "." + name;
117+
}
118+
}
119+
120+
var getShortName = function (name: string) {
121+
return name.substring(name.lastIndexOf(":") + 1, name.length);
122+
}
123+
124+
var checkFunction = function (info: FuncInfo) {
125+
if (!info.name) {
126+
return;
127+
}
128+
129+
trace.write("Check function exists: " + getFullName(info.name), traceCategory);
130+
var moduleToCheck = getModuleToCheck(info.name);
131+
if (moduleToCheck) {
132+
var actual = moduleToCheck[info.name];
133+
if (!types.isFunction(actual)) {
134+
errors.push("Function not defined: " + getFullName(info.name));
135+
}
136+
else if (actual.length !== info.paramsCount) {
137+
errors.push("Function " + getFullName(info.name) + " expected params: " + info.paramsCount + " actual params: " + actual.length);
138+
}
139+
}
140+
}
141+
142+
var checkClass = function (className: string) {
143+
trace.write("Check class exists: " + getFullName(className), traceCategory);
144+
var moduleToCheck = getModuleToCheck(className);
145+
if (moduleToCheck) {
146+
if (!types.isFunction(moduleToCheck[className])) {
147+
errors.push("Class not defined: " + getFullName(className));
148+
}
149+
}
150+
}
151+
152+
var checkVar = function (varName: string) {
153+
trace.write("Check variable exists: " + getFullName(varName), traceCategory);
154+
var moduleToCheck = getModuleToCheck(varName);
155+
if (moduleToCheck) {
156+
if (!types.isDefined(moduleToCheck[varName])) {
157+
errors.push("Variable not defined: " + getFullName(varName));
158+
}
159+
}
160+
}
161+
162+
var onEventCallback = function (event: xmlModule.ParserEvent) {
163+
try {
164+
switch (event.eventType) {
165+
166+
case xmlModule.ParserEventType.StartElement:
167+
if (event.elementName === "js:module") {
168+
var moduleName: string = event.attributes["qname"];
169+
170+
if (moduleNesting === 0) {
171+
moduleName = moduleName.replace(/&quot;/g, "");
172+
if (ignoredModules.indexOf(moduleName) < 0) {
173+
currentModuleName = moduleName;
174+
trace.write("--- START CHECKING MODULE: " + currentModuleName, traceCategory);
175+
currentModule = require(currentModuleName);
176+
}
177+
}
178+
else {
179+
moduleName = getShortName(moduleName);
180+
//trace.write("Push submodule: " + moduleName);
181+
subModuleStack.push(moduleName);
182+
}
183+
184+
moduleNesting++;
185+
}
186+
else if (event.elementName === "js:function") {
187+
functionStack.push({
188+
name: (event.attributes && event.attributes["name"]) ? event.attributes["name"] : undefined,
189+
paramsCount: 0
190+
});
191+
}
192+
else if (event.elementName === "js:param" && functionStack.length > 0) {
193+
if (!event.attributes || event.attributes["rest"] !== "true") {
194+
functionStack[functionStack.length - 1].paramsCount++;
195+
}
196+
}
197+
else if (event.elementName === "js:class" && event.attributes && event.attributes["qname"]) {
198+
checkClass(getShortName(event.attributes["qname"]));
199+
}
200+
201+
else if (event.elementName === "js:var" && event.attributes && event.attributes["name"]) {
202+
checkVar(getShortName(event.attributes["name"]));
203+
}
204+
break;
205+
206+
case xmlModule.ParserEventType.EndElement:
207+
if (event.elementName === "js:module") {
208+
moduleNesting--;
209+
if (moduleNesting === 0) {
210+
trace.write("--- FINISHED CHECKING MODULE: " + currentModuleName, traceCategory);
211+
currentModule = undefined;
212+
currentModuleName = undefined;
213+
}
214+
else {
215+
var submodule = subModuleStack.pop();
216+
//trace.write("Pop submodule: " + submodule);
217+
}
218+
}
219+
else if (event.elementName === "js:function") {
220+
checkFunction(functionStack.pop());
221+
}
222+
223+
break;
224+
}
225+
}
226+
catch (error) {
227+
errors.push("Error is event callback: " + error.message);
228+
}
229+
};
230+
231+
var onErrorCallback = function (error: Error) {
232+
errors.push("Error while parsing api.xml: " + error.message);
233+
};
234+
235+
var xmlParser = new xmlModule.XmlParser(onEventCallback, onErrorCallback);
236+
xmlParser.parse(xml);
237+
238+
errors = applyWhitelist(errors);
239+
240+
TKUnit.assert(errors.length == 0, errors.join("\n"));
241+
}

0 commit comments

Comments
 (0)