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",
"request": "launch",
"name": "Jest All",
"name": "Jest App Server",
"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",
"internalConsoleOptions": "neverOpen",
"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"
},
"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 { resolve } = require("path");
const send = require('koa-send');
const { getPackageForBuilder, getComponents,
const { getPackageForBuilder, getRootComponents: getComponents,
savePackage, getApps } = require("../utilities/builder");
const builderPath = resolve(__dirname, "../builder");
const appUiPath = appname => {
}
module.exports = (config, app) => {
@ -33,21 +30,27 @@ module.exports = (config, app) => {
ctx.throw(StatusCodes.NOT_FOUND, "App Name not declared");
}
const instance = await ctx.master.getInstanceApiForSession(
pathParts[1],
ctx.sessionId);
const appname = pathParts[1];
if(appname === "_builder") {
await next();
} else {
const instance = await ctx.master.getInstanceApiForSession(
appname,
ctx.sessionId);
ctx.instance = instance.instance;
ctx.publicPath = instance.publicPath;
ctx.isAuthenticated = !!instance.instance;
ctx.instance = instance.instance;
ctx.publicPath = instance.publicPath;
ctx.isAuthenticated = !!instance.instance;
await next();
await next();
}
})
.get("/_builder", async (ctx) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder";
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder";
return;
}
@ -56,8 +59,8 @@ module.exports = (config, app) => {
})
.get("/_builder/*", async (ctx, next) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder";
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder";
return;
}
@ -117,8 +120,8 @@ module.exports = (config, app) => {
})
.get("/_builder/api/apps", async (ctx) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder";
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.response.body = "run in dev mode to access builder";
return;
}
@ -128,8 +131,8 @@ module.exports = (config, app) => {
})
.get("/_builder/api/:appname/appPackage", async (ctx) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.request.body = "run in dev mode to access builder";
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder";
return;
}
@ -141,7 +144,7 @@ module.exports = (config, app) => {
})
.post("/_builder/api/:appname/appPackage", async (ctx) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder";
return;
}
@ -154,7 +157,7 @@ module.exports = (config, app) => {
})
.get("/_builder/api/:appname/components", async (ctx) => {
if(!config.dev) {
ctx.request.status = StatusCodes.FORBIDDEN;
ctx.response.status = StatusCodes.FORBIDDEN;
ctx.body = "run in dev mode to access builder";
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,
latestPackagesFolder: "./appPackages",
extraMasterPlugins,
customizeMaster
customizeMaster,
dev:true
}

View File

@ -6,20 +6,29 @@ const {
writeFile,
readFile,
readdir,
exists
exists,
stat
} = require("./fsawait");
const { resolve } = require("path");
const {
resolve,
join
} = require("path");
const { $ } = require("budibase-core").common;
const {
keys,
reduce,
map,
flatten,
some
some,
keyBy
} = require("lodash/fp");
const {merge} = require("lodash");
module.exports.getPackageForBuilder = async (config, appname) => {
const appPath = appPackageFolder(config, appname);
const pages = JSON.parse(await readFile(
`${appPath}/pages.json`,
"utf8"));
return ({
appDefinition: JSON.parse(await readFile(
`${appPath}/appDefinition.json`,
@ -29,9 +38,12 @@ module.exports.getPackageForBuilder = async (config, appname) => {
`${appPath}/access_levels.json`,
"utf8")),
pages: JSON.parse(await readFile(
`${appPath}/pages.json`,
"utf8"))
pages,
rootComponents: await getRootComponents(appPath, pages),
derivedComponents: keyBy("_name")(
await fetchDerivedComponents(appPath))
})
}
@ -50,7 +62,7 @@ module.exports.savePackage = async (config, appname, pkg) => {
await writeFile(
`${appPath}/pages.json`,
JSON.stringify(pkg.accessLevels),
JSON.stringify(pkg.pages),
"utf8");
}
@ -58,9 +70,9 @@ module.exports.getApps = async (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))
("./~\\".split(""));
@ -77,10 +89,10 @@ module.exports.getComponents = async (config, appname, lib) => {
let components;
try {
components = JSON.parse(
readFile(componentsPath, "utf8"));
await readFile(componentsPath, "utf8"));
} catch(e) {
const e = new Error(`could not parse JSON - ${componentsPath} `);
throw e;
const err = `could not parse JSON - ${componentsPath} : ${e.message}`;
throw new Error(err);
}
return $(components, [
@ -94,9 +106,7 @@ module.exports.getComponents = async (config, appname, lib) => {
let libs;
if(!lib) {
const appPath = appPackageFolder(config, appname);
const pages = JSON.parse(await readFile(
pages = pages || JSON.parse(await readFile(
`${appPath}/pages.json`,
"utf8"));
@ -107,9 +117,51 @@ module.exports.getComponents = async (config, appname, lib) => {
libs = [lib];
}
return $(libs, [
map(componentsInLibrary),
flatten
]);
const components = {};
for(let l of libs) {
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;