get components server endpoint ... tested

This commit is contained in:
michael shanks 2019-07-26 15:13:15 +01:00
parent 4891c6de80
commit ebf5dfeeea
15 changed files with 202 additions and 60 deletions

View File

@ -13,9 +13,22 @@
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "Jest All", "name": "Jest App Server",
"program": "${workspaceFolder}/node_modules/.bin/jest", "program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"], "args": ["apps", "--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"windows": {
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
}
},
{
"type": "node",
"request": "launch",
"name": "Jest Builder",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["builder", "--runInBand"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen", "internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true, "disableOptimisticBPs": true,

View File

@ -0,0 +1,4 @@
{
"_component": "./customComponents/textbox",
"label": "hello"
}

View File

@ -0,0 +1,4 @@
{
"_component": "./moreCustomComponents/textbox",
"label": "hello"
}

View File

@ -0,0 +1,11 @@
{
"textbox" : {
"path": "./textbox",
"name": "Textbox",
"description": "A text input, with a label",
"props": {
"label": "string"
},
"tags": ["textboxt", "input", "text"]
}
}

View File

@ -15,5 +15,5 @@
}, },
"appBody" : "./unauthenticated.app.json" "appBody" : "./unauthenticated.app.json"
}, },
"componentLibraries": ["./myComponents"] "componentLibraries": ["./customComponents", "./moreCustomComponents"]
} }

View File

@ -1,12 +0,0 @@
const Sequencer = require('@jest/test-sequencer').default;
const testOrder = [""]
class CustomSequencer extends Sequencer {
sort(tests) {
// Test structure information
// https://github.com/facebook/jest/blob/6b8b1404a1d9254e7d5d90a8934087a9c9899dab/packages/jest-runner/src/types.ts#L17-L21
const copyTests = Array.from(tests);
return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1));
}
}

View File

@ -4,13 +4,10 @@ const StatusCodes = require("../utilities/statusCodes");
const fs = require("fs"); const fs = require("fs");
const { resolve } = require("path"); const { resolve } = require("path");
const send = require('koa-send'); const send = require('koa-send');
const { getPackageForBuilder, getComponents, const { getPackageForBuilder, getRootComponents: getComponents,
savePackage, getApps } = require("../utilities/builder"); savePackage, getApps } = require("../utilities/builder");
const builderPath = resolve(__dirname, "../builder"); const builderPath = resolve(__dirname, "../builder");
const appUiPath = appname => {
}
module.exports = (config, app) => { module.exports = (config, app) => {
@ -33,8 +30,13 @@ module.exports = (config, app) => {
ctx.throw(StatusCodes.NOT_FOUND, "App Name not declared"); ctx.throw(StatusCodes.NOT_FOUND, "App Name not declared");
} }
const appname = pathParts[1];
if(appname === "_builder") {
await next();
} else {
const instance = await ctx.master.getInstanceApiForSession( const instance = await ctx.master.getInstanceApiForSession(
pathParts[1], appname,
ctx.sessionId); ctx.sessionId);
@ -43,11 +45,12 @@ module.exports = (config, app) => {
ctx.isAuthenticated = !!instance.instance; ctx.isAuthenticated = !!instance.instance;
await next(); await next();
}
}) })
.get("/_builder", async (ctx) => { .get("/_builder", async (ctx) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder"; ctx.body = "run in dev mode to access builder";
return; return;
} }
@ -56,8 +59,8 @@ module.exports = (config, app) => {
}) })
.get("/_builder/*", async (ctx, next) => { .get("/_builder/*", async (ctx, next) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder"; ctx.body = "run in dev mode to access builder";
return; return;
} }
@ -117,8 +120,8 @@ module.exports = (config, app) => {
}) })
.get("/_builder/api/apps", async (ctx) => { .get("/_builder/api/apps", async (ctx) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder"; ctx.response.body = "run in dev mode to access builder";
return; return;
} }
@ -128,8 +131,8 @@ module.exports = (config, app) => {
}) })
.get("/_builder/api/:appname/appPackage", async (ctx) => { .get("/_builder/api/:appname/appPackage", async (ctx) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder"; ctx.body = "run in dev mode to access builder";
return; return;
} }
@ -141,7 +144,7 @@ module.exports = (config, app) => {
}) })
.post("/_builder/api/:appname/appPackage", async (ctx) => { .post("/_builder/api/:appname/appPackage", async (ctx) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder"; ctx.body = "run in dev mode to access builder";
return; return;
} }
@ -154,7 +157,7 @@ module.exports = (config, app) => {
}) })
.get("/_builder/api/:appname/components", async (ctx) => { .get("/_builder/api/:appname/components", async (ctx) => {
if(!config.dev) { if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN; ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder"; ctx.body = "run in dev mode to access builder";
return; return;
} }

View File

@ -0,0 +1,66 @@
const testAppDef = require("../appPackages/testApp/appDefinition.json");
const testAccessLevels = require("../appPackages/testApp/access_levels.json");
const testPages = require("../appPackages/testApp/pages.json");
const testComponents = require("../appPackages/testApp/customComponents/components.json");
const testMoreComponents = require("../appPackages/testApp/moreCustomComponents/components.json");
const statusCodes = require("../utilities/statusCodes");
const derivedComponent1 = require("../appPackages/testApp/components/myTextBox.json");
const derivedComponent2 = require("../appPackages/testApp/components/subfolder/otherTextBox.json");
const app = require("./testApp")();
beforeAll(async () => await app.start());
afterAll(async () => await app.destroy());
it("/apppackage should get appDefinition", async () => {
const {body} = await app.get("/_builder/api/testApp/appPackage")
.expect(statusCodes.OK);
expect(body.appDefinition).toEqual(testAppDef);
});
it("/apppackage should get access levels", async () => {
const {body} = await app.get("/_builder/api/testApp/appPackage")
.expect(statusCodes.OK);
expect(body.accessLevels).toEqual(testAccessLevels);
});
it("/apppackage should get pages", async () => {
const {body} = await app.get("/_builder/api/testApp/appPackage")
.expect(statusCodes.OK);
expect(body.pages).toEqual(testPages);
});
it("/apppackage should get rootComponents", async () => {
const {body} = await app.get("/_builder/api/testApp/appPackage")
.expect(statusCodes.OK);
expect(body.rootComponents["./customComponents/textbox"]).toBeDefined();
expect(body.rootComponents["./moreCustomComponents/textbox"]).toBeDefined();
expect(body.rootComponents["./customComponents/textbox"])
.toEqual(testComponents.textbox);
expect(body.rootComponents["./moreCustomComponents/textbox"])
.toEqual(testMoreComponents.textbox);
});
it("/apppackage should get derivedComponents", async () => {
const {body} = await app.get("/_builder/api/testApp/appPackage")
.expect(statusCodes.OK);
const expectedComponents = {
"myTextBox" : {...derivedComponent1, _name:"myTextBox"},
"subfolder/otherTextBox": {...derivedComponent2, _name:"subfolder/otherTextBox"}
};
expect(body.derivedComponents).toEqual(expectedComponents);
});

View File

@ -46,7 +46,8 @@ const config = {
port: 4002, port: 4002,
latestPackagesFolder: "./appPackages", latestPackagesFolder: "./appPackages",
extraMasterPlugins, extraMasterPlugins,
customizeMaster customizeMaster,
dev:true
} }

View File

@ -6,20 +6,29 @@ const {
writeFile, writeFile,
readFile, readFile,
readdir, readdir,
exists exists,
stat
} = require("./fsawait"); } = require("./fsawait");
const { resolve } = require("path"); const {
resolve,
join
} = require("path");
const { $ } = require("budibase-core").common; const { $ } = require("budibase-core").common;
const { const {
keys, keys,
reduce, reduce,
map, some,
flatten, keyBy
some
} = require("lodash/fp"); } = require("lodash/fp");
const {merge} = require("lodash");
module.exports.getPackageForBuilder = async (config, appname) => { module.exports.getPackageForBuilder = async (config, appname) => {
const appPath = appPackageFolder(config, appname); const appPath = appPackageFolder(config, appname);
const pages = JSON.parse(await readFile(
`${appPath}/pages.json`,
"utf8"));
return ({ return ({
appDefinition: JSON.parse(await readFile( appDefinition: JSON.parse(await readFile(
`${appPath}/appDefinition.json`, `${appPath}/appDefinition.json`,
@ -29,9 +38,12 @@ module.exports.getPackageForBuilder = async (config, appname) => {
`${appPath}/access_levels.json`, `${appPath}/access_levels.json`,
"utf8")), "utf8")),
pages: JSON.parse(await readFile( pages,
`${appPath}/pages.json`,
"utf8")) rootComponents: await getRootComponents(appPath, pages),
derivedComponents: keyBy("_name")(
await fetchDerivedComponents(appPath))
}) })
} }
@ -50,7 +62,7 @@ module.exports.savePackage = async (config, appname, pkg) => {
await writeFile( await writeFile(
`${appPath}/pages.json`, `${appPath}/pages.json`,
JSON.stringify(pkg.accessLevels), JSON.stringify(pkg.pages),
"utf8"); "utf8");
} }
@ -58,9 +70,9 @@ module.exports.getApps = async (config) =>
await readdir(appsFolder(config)); await readdir(appsFolder(config));
module.exports.getComponents = async (config, appname, lib) => { const getRootComponents = async (appPath, pages ,lib) => {
const componentsInLibrary = (libname) => { const componentsInLibrary = async (libname) => {
const isRelative = some(c => c === libname.substring(0,1)) const isRelative = some(c => c === libname.substring(0,1))
("./~\\".split("")); ("./~\\".split(""));
@ -77,10 +89,10 @@ module.exports.getComponents = async (config, appname, lib) => {
let components; let components;
try { try {
components = JSON.parse( components = JSON.parse(
readFile(componentsPath, "utf8")); await readFile(componentsPath, "utf8"));
} catch(e) { } catch(e) {
const e = new Error(`could not parse JSON - ${componentsPath} `); const err = `could not parse JSON - ${componentsPath} : ${e.message}`;
throw e; throw new Error(err);
} }
return $(components, [ return $(components, [
@ -94,9 +106,7 @@ module.exports.getComponents = async (config, appname, lib) => {
let libs; let libs;
if(!lib) { if(!lib) {
const appPath = appPackageFolder(config, appname); pages = pages || JSON.parse(await readFile(
const pages = JSON.parse(await readFile(
`${appPath}/pages.json`, `${appPath}/pages.json`,
"utf8")); "utf8"));
@ -107,9 +117,51 @@ module.exports.getComponents = async (config, appname, lib) => {
libs = [lib]; libs = [lib];
} }
return $(libs, [ const components = {};
map(componentsInLibrary), for(let l of libs) {
flatten merge(components, await componentsInLibrary(l))
]); }
return components;
} }
const fetchDerivedComponents = async (appPath, relativePath = "") => {
const currentDir = join(appPath, "components", relativePath);
const contents = await readdir(currentDir);
const components = [];
for(let item of contents) {
const itemRelativePath = join(relativePath, item);
const itemFullPath = join(currentDir, item);
const stats = await stat(itemFullPath);
if(stats.isFile()) {
if(!item.endsWith(".json")) continue;
const component = JSON.parse(
await readFile(itemFullPath, "utf8"));
component._name = itemRelativePath
.substring(0, itemRelativePath.length - 5)
.replace(/\\/g, "/");
components.push(component);
} else {
const childComponents = await fetchDerivedComponents(
appPath, join(relativePath, item)
);
for(let c of childComponents) {
components.push(c);
}
}
}
return components;
}
module.exports.getRootComponents = getRootComponents;