Merge branch 'develop' into link-component

This commit is contained in:
Gervwyk 2022-02-07 23:30:37 +02:00
commit d5db970b55
24 changed files with 294 additions and 512 deletions

2
.pnp.cjs generated
View File

@ -3214,6 +3214,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageLocation": "./packages/docs/",
"packageDependencies": [
["@lowdefy/docs", "workspace:packages/docs"],
["@swc/core", "npm:1.2.135"],
["@swc/jest", "virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:0.2.17"],
["jest", "virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:27.4.7"]
],
"linkType": "SOFT",

View File

@ -0,0 +1,33 @@
/*
Copyright 2020-2021 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { getFileExtension } from '@lowdefy/node-utils';
jest.mock('@lowdefy/node-utils', () => {
return {
getFileExtension,
readFile: jest.fn(),
};
});
test('readConfigFile', async () => {
const nodeUtils = await import('@lowdefy/node-utils');
nodeUtils.mockImplementation(() => Promise.resove('config value'));
const createReadConfigFile = (await import('./readConfigFile.js')).default;
const readConfigFile = createReadConfigFile({ buildDirectory: '/build' });
const res = await readConfigFile('file');
expect(res).toEqual('config value');
});

View File

@ -7,6 +7,7 @@ export default {
'<rootDir>/.lowdefy/',
'<rootDir>/jest.config.js',
'<rootDir>/coverage/',
'<rootDir>/howto/',
],
coverageReporters: [['lcov', { projectRoot: '../..' }], 'text', 'clover'],
errorOnDeprecated: true,
@ -15,5 +16,9 @@ export default {
'<rootDir>/.lowdefy/',
'<rootDir>/jest.config.js',
'<rootDir>/coverage/',
'<rootDir>/howto/',
],
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest', { configFile: '../../.swcrc.test' }],
},
};

View File

@ -32,6 +32,8 @@
"test": "jest --coverage"
},
"devDependencies": {
"@swc/core": "1.2.135",
"@swc/jest": "0.2.17",
"jest": "27.4.7"
},
"publishConfig": {

View File

@ -3,11 +3,11 @@ export default {
collectCoverage: true,
collectCoverageFrom: ['src/**/*.js'],
coverageDirectory: 'coverage',
coveragePathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/test/', '<rootDir>/dist/index.js'],
coveragePathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/test/', '<rootDir>/src/index.js'],
coverageReporters: [['lcov', { projectRoot: '../..' }], 'text', 'clover'],
errorOnDeprecated: true,
testEnvironment: 'jsdom',
testPathIgnorePatterns: ['<rootDir>/dist/'],
testPathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/src/index.js'],
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest', { configFile: '../../.swcrc.test' }],
},

View File

@ -15,17 +15,18 @@
*/
import _index from './_index.js';
jest.mock('@lowdefy/operators');
const input = {
arrayIndices: [0],
location: 'location',
params: 'params',
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('args calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
_index(input);
test('_index calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
_index({
arrayIndices: [0],
location: 'location',
params: 'params',
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,22 +15,23 @@
*/
import actions from './actions.js';
jest.mock('@lowdefy/operators');
const input = {
actions: {
action_id: {
response: 'returned from action',
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('actions calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
actions({
actions: {
action_id: {
response: 'returned from action',
},
},
},
arrayIndices: [0],
location: 'location',
params: 'params',
};
test('actions calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
actions(input);
arrayIndices: [0],
location: 'location',
params: 'params',
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,18 +15,19 @@
*/
import event from './event.js';
jest.mock('@lowdefy/operators');
const input = {
arrayIndices: [0],
event: { event: true },
location: 'location',
params: 'params',
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('event calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
event(input);
test('event calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
event({
arrayIndices: [0],
event: { event: true },
location: 'location',
params: 'params',
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -14,226 +14,29 @@
limitations under the License.
*/
import { WebParser } from '@lowdefy/operators';
import event_log from './event_log.js';
const arrayIndices = [1];
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
const context = {
_internal: {
lowdefy: {
inputs: { id: true },
lowdefyGlobal: { global: true },
menus: [{ menus: true }],
urlQuery: { urlQuery: true },
user: { user: true },
},
},
eventLog: [{ eventLog: true }],
id: 'id',
requests: [{ requests: true }],
state: { state: true },
};
console.error = () => {};
test('_event_log in array', async () => {
const input = { a: { _event_log: '1.blockId' } };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({
a: 'block_b',
test('request_details calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
event_log({
eventLog: [{ eventName: 'test' }],
arrayIndices: [0],
location: 'location',
params: 'params',
});
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log full state', async () => {
const input = { _event_log: true };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual([
{
blockId: 'block_a',
actionName: 'name_a',
response: [{ data: ['a', 'b'] }],
ts: new Date(0),
status: 'success',
},
{
blockId: 'block_b',
actionName: 'name_b',
ts: new Date(1),
error: [{ error: 'error', message: 'broken', name: 'e' }],
},
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{
arrayIndices: [0],
location: 'location',
object: [{ eventName: 'test' }],
operator: '_event_log',
params: 'params',
},
],
]);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log null', async () => {
const input = { _event_log: null };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toBe(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _event_log params must be of type string, integer, boolean or object. Received: null at locationId.],
]
`);
});
test('_event_log param object key', async () => {
const input = {
_event_log: {
key: '0.actionName',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual('name_a');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object all', async () => {
const input = {
_event_log: {
all: true,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual([
{
blockId: 'block_a',
actionName: 'name_a',
response: [{ data: ['a', 'b'] }],
ts: new Date(0),
status: 'success',
},
{
blockId: 'block_b',
actionName: 'name_b',
ts: new Date(1),
error: [{ error: 'error', message: 'broken', name: 'e' }],
},
]);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object all and key', async () => {
const input = {
_event_log: {
all: true,
key: 'string',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual([
{
blockId: 'block_a',
actionName: 'name_a',
response: [{ data: ['a', 'b'] }],
ts: new Date(0),
status: 'success',
},
{
blockId: 'block_b',
actionName: 'name_b',
ts: new Date(1),
error: [{ error: 'error', message: 'broken', name: 'e' }],
},
]);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object invalid', async () => {
const input = {
_event_log: {
other: true,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _event_log.key must be of type string or integer. Received: {"other":true} at locationId.],
]
`);
});
test('_event_log param array', async () => {
const input = {
_event_log: ['string'],
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _event_log params must be of type string, integer, boolean or object. Received: ["string"] at locationId.],
]
`);
});
test('_event_log param object with string default', async () => {
const input = {
_event_log: {
key: 'notFound',
default: 'defaultValue',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual('defaultValue');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object with zero default', async () => {
const input = {
_event_log: {
key: 'notFound',
default: 0,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(0);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object with false default', async () => {
const input = {
_event_log: {
key: 'notFound',
default: false,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(false);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_event_log param object with no default', async () => {
const input = {
_event_log: {
key: 'notFound',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});

View File

@ -13,26 +13,20 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import _global from './global.js';
jest.mock('@lowdefy/operators');
let lowdefyOperators;
let global;
const input = {
arrayIndices: [0],
location: 'location',
lowdefyGlobal: { lowdefyGlobal: true },
params: 'params',
};
beforeEach(async () => {
lowdefyOperators = await import('@lowdefy/operators');
global = (await import('./global.js')).default;
});
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('global calls getFromObject', async () => {
global(input);
const lowdefyOperators = await import('@lowdefy/operators');
_global({
arrayIndices: [0],
location: 'location',
params: 'params',
lowdefyGlobal: { lowdefyGlobal: true },
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,18 +15,19 @@
*/
import input from './input.js';
jest.mock('@lowdefy/operators');
const inputParams = {
arrayIndices: [0],
input: { input: true },
location: 'location',
params: 'params',
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('input calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
input(inputParams);
test('input calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
input({
arrayIndices: [0],
input: { input: true },
location: 'location',
params: 'params',
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -31,6 +31,7 @@ const validProperties = [
'hash',
];
// TODO: Fix with new router and link
function _location({ arrayIndices, context, location, params }) {
if (!window || !window.location) {
throw new Error(

View File

@ -15,7 +15,10 @@
*/
import location from './location.js';
jest.mock('@lowdefy/operators');
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
beforeEach(() => {
Object.defineProperty(window, 'location', {
@ -43,7 +46,7 @@ const input = {
params: 'origin',
};
test('location calls getFromObject', () => {
test('location calls getFromObject', async () => {
const lowdefyOperators = import('@lowdefy/operators');
location(input);
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([

View File

@ -14,182 +14,41 @@
limitations under the License.
*/
/* eslint-disable max-classes-per-file */
import { WebParser } from '@lowdefy/operators';
import request_details from './request_details.js';
const arrayIndices = [1];
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
const context = {
_internal: {
lowdefy: {
inputs: { id: true },
lowdefyGlobal: { global: true },
menus: [{ menus: true }],
urlQuery: { urlQuery: true },
user: { user: true },
test('request_details calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
request_details({
requests: {
request_id: {
response: 'returned from action',
loading: false,
error: [],
},
},
},
eventLog: [{ eventLog: true }],
id: 'id',
requests: [{ requests: true }],
state: { state: true },
};
console.error = () => {};
test('_request_details in object', async () => {
const input = { _request_details: 'string' };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({ loading: false, response: 'request String' });
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details all requests', async () => {
const input = { _request_details: true };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({
not_loaded: { loading: true, response: 'fail' },
string: { loading: false, response: 'request String' },
number: { loading: false, response: 500 },
arr: { loading: false, response: [{ a: 'request a1' }, { a: 'request a2' }] },
returnsNull: { loading: false, response: null },
arrayIndices: [0],
location: 'location',
params: 'params',
});
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details null', async () => {
const input = { _request_details: null };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toBe(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _request_details params must be of type string, integer, boolean or object. Received: null at locationId.],
]
`);
});
test('_request_details nested', async () => {
const input = { _request_details: 'string.response' };
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual('request String');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details param object key', async () => {
const input = {
_request_details: {
key: 'string',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({ loading: false, response: 'request String' });
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details param object all', async () => {
const input = {
_request_details: {
all: true,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({
not_loaded: { loading: true, response: 'fail' },
string: { loading: false, response: 'request String' },
number: { loading: false, response: 500 },
arr: { loading: false, response: [{ a: 'request a1' }, { a: 'request a2' }] },
returnsNull: { loading: false, response: null },
});
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details param object all and key', async () => {
const input = {
_request_details: {
all: true,
key: 'string',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual({
not_loaded: { loading: true, response: 'fail' },
string: { loading: false, response: 'request String' },
number: { loading: false, response: 500 },
arr: { loading: false, response: [{ a: 'request a1' }, { a: 'request a2' }] },
returnsNull: { loading: false, response: null },
});
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details param object invalid', async () => {
const input = {
_request_details: {
other: true,
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _request_details.key must be of type string or integer. Received: {"other":true} at locationId.],
]
`);
});
test('_request_details param array', async () => {
const input = {
_request_details: ['string'],
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`
Array [
[Error: Operator Error: _request_details params must be of type string, integer, boolean or object. Received: ["string"] at locationId.],
]
`);
});
test('_request_details param object with string default', async () => {
const input = {
_request_details: {
key: 'notFound',
default: 'defaultValue',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual('defaultValue');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('_request_details param object with no default', async () => {
const input = {
_request_details: {
key: 'notFound',
},
};
const parser = new WebParser({ context });
await parser.init();
const res = parser.parse({ input, location: 'locationId', arrayIndices });
expect(res.output).toEqual(null);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{
arrayIndices: [0],
location: 'location',
object: {
request_id: {
response: 'returned from action',
loading: false,
error: [],
},
},
operator: '_request_details',
params: 'params',
},
],
]);
});

View File

@ -15,18 +15,19 @@
*/
import state from './state.js';
jest.mock('@lowdefy/operators');
const input = {
arrayIndices: [0],
location: 'location',
params: 'params',
state: { state: true },
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('state calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
state(input);
test('state calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
state({
arrayIndices: [0],
location: 'location',
params: 'params',
state: { state: true },
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,19 +15,21 @@
*/
import url_query from './url_query.js';
jest.mock('@lowdefy/operators');
const input = {
arrayIndices: [0],
location: 'location',
params: 'params',
secrets: { secrets: true },
urlQuery: { urlQuery: true },
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('url_query calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
url_query(input);
const input = {};
test('url_query calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
url_query({
arrayIndices: [0],
location: 'location',
params: 'params',
urlQuery: { urlQuery: true },
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,17 +15,18 @@
*/
import payload from './payload.js';
jest.mock('@lowdefy/operators');
const input = {
location: 'location',
params: 'params',
payload: { payload: true },
};
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('payload calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
payload(input);
test('payload calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
payload({
location: 'location',
params: 'params',
payload: { payload: true },
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -15,12 +15,15 @@
*/
import secret from './secret.js';
jest.mock('@lowdefy/operators');
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
console.error = () => {};
test('secret calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
test('secret calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
secret({
arrayIndices: [0],
location: 'location',
@ -41,8 +44,8 @@ test('secret calls getFromObject', () => {
]);
});
test('secret default value', () => {
const lowdefyOperators = import('@lowdefy/operators');
test('secret default value', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
secret({
arrayIndices: [0],
location: 'location',
@ -72,8 +75,8 @@ test('secret get all is not allowed', () => {
);
});
test('secret OpenID Connect and JSON web token secrets are filtered out', () => {
const lowdefyOperators = import('@lowdefy/operators');
test('secret OpenID Connect and JSON web token secrets are filtered out', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
secret({
arrayIndices: [0],
location: 'location',

View File

@ -13,7 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
jest.mock('@lowdefy/operators');
import args from './args.js';
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
const input = {
args: [{ args: true }],
@ -23,9 +27,13 @@ const input = {
};
test('args calls getFromObject', async () => {
const args = await import('./args.js');
const lowdefyOperators = await import('@lowdefy/operators');
args.default(input);
args({
args: [{ args: true }],
arrayIndices: [0],
location: 'location',
params: 'params',
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -14,19 +14,21 @@
limitations under the License.
*/
import get from './get.js';
jest.mock('@lowdefy/operators');
test('_get calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
const input = {
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
test('_get calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
get({
arrayIndices: [0],
location: 'location',
params: {
from: { a: 1 },
key: 'a',
},
};
get.default(input);
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{
@ -52,7 +54,6 @@ test('_get returns null if from is null', () => {
key: 'a',
},
};
get(input);
expect(get(input)).toBe(null);
});
@ -66,7 +67,6 @@ test('_get returns default value if from is null', () => {
default: 'default',
},
};
get(input);
expect(get(input)).toBe('default');
});

View File

@ -15,7 +15,9 @@
*/
import user from './user.js';
jest.mock('@lowdefy/operators');
jest.mock('@lowdefy/operators', () => ({
getFromObject: jest.fn(),
}));
const input = {
arrayIndices: [0],
@ -24,9 +26,14 @@ const input = {
user: { name: 'first name' },
};
test('user calls getFromObject', () => {
const lowdefyOperators = import('@lowdefy/operators');
user(input);
test('user calls getFromObject', async () => {
const lowdefyOperators = await import('@lowdefy/operators');
user({
arrayIndices: [0],
location: 'location',
params: 'params',
user: { name: 'first name' },
});
expect(lowdefyOperators.getFromObject.mock.calls).toEqual([
[
{

View File

@ -14,10 +14,10 @@
limitations under the License.
*/
function cachedPromises(getter) {
function createCachedPromises(getter) {
const cache = new Map();
function getCachedPromise(key) {
function cachedPromises(key) {
if (cache.has(key)) {
return Promise.resolve(cache.get(key));
}
@ -26,7 +26,7 @@ function cachedPromises(getter) {
return Promise.resolve(promise);
}
return getCachedPromise;
return cachedPromises;
}
export default cachedPromises;
export default createCachedPromises;

View File

@ -0,0 +1,52 @@
/*
Copyright 2020-2021 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import createCachedPromises from './cachedPromises.js';
import wait from './wait.js';
test('cachedPromises calls getter with key', async () => {
const getter = jest.fn(() => Promise.resolve('value'));
const cachedGetter = createCachedPromises(getter);
const promise = cachedGetter('key');
expect(`${promise}`).toEqual('[object Promise]');
const result = await promise;
expect(result).toEqual('value');
expect(getter.mock.calls).toEqual([['key']]);
});
test('cachedPromises only calls getter once', async () => {
const getter = jest.fn(() => Promise.resolve('value'));
const cachedGetter = createCachedPromises(getter);
const result1 = await cachedGetter('key');
expect(result1).toEqual('value');
const result2 = await cachedGetter('key');
expect(result2).toEqual('value');
expect(getter.mock.calls).toEqual([['key']]);
});
test('getter is called once if first call has not yet resolved', async () => {
const getter = jest.fn(async () => {
await wait(10);
return 'value';
});
const cachedGetter = createCachedPromises(getter);
const promise1 = cachedGetter('key');
const promise2 = cachedGetter('key');
expect(getter.mock.calls).toEqual([['key']]);
await promise1;
await promise2;
expect(getter.mock.calls).toEqual([['key']]);
});

View File

@ -2347,6 +2347,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@lowdefy/docs@workspace:packages/docs"
dependencies:
"@swc/core": 1.2.135
"@swc/jest": 0.2.17
jest: 27.4.7
languageName: unknown
linkType: soft