@mojotech/prismatest
Advanced tools
Comparing version 0.1.4 to 0.2.0
@@ -1,34 +0,50 @@ | ||
interface MaterializedTestView<E, A> { | ||
actions: MaterializedActions<E, A & DefaultActions<E>>; | ||
} | ||
interface TestView<S, E, A> { | ||
materialize(e: E): MaterializedTestView<E, A>; | ||
selector: S; | ||
actions: A; | ||
<NA extends { | ||
[k: string]: Action<E>; | ||
}>(nextView: TestView<S, E, NA>): TestView<S, E, NA>; | ||
} | ||
export interface TestViewConstructor<S, E> { | ||
<A extends { | ||
[k: string]: Action<E>; | ||
}>(selector: S, actions?: A): TestView<S, E, A>; | ||
defaultViews: MaterializedDefaultViews<S, E>; | ||
} | ||
declare type AParameters<AType extends (...args: any[]) => any> = Tail<Parameters<AType>>; | ||
declare type Aggregate<E> = (e: E[], ...args: any[]) => any; | ||
declare type AggregateMap<E> = { | ||
[k: string]: Aggregate<E>; | ||
}; | ||
declare type DefaultAggregates = {}; | ||
declare type MaterializedAggregate<E, A extends Aggregate<E>> = (...args: AParameters<A>) => ReturnType<A>; | ||
declare type MaterializedAggregateMap<E, AggregateMap extends { | ||
[k: string]: Aggregate<E>; | ||
}> = { | ||
[K in keyof AggregateMap]: MaterializedAggregate<E, AggregateMap[K]>; | ||
}; | ||
declare type Action<E> = (e: E, ...args: any[]) => any; | ||
declare type ActionParameters<E, A extends Action<E>> = AParameters<A>; | ||
declare type ActionMap<E> = { | ||
[k: string]: Action<E>; | ||
}; | ||
declare type DefaultActions<E> = { | ||
get: (e: E) => E; | ||
}; | ||
declare type Tail<T extends any[]> = ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : never; | ||
declare type Action<E> = (e: E, ...args: any[]) => any; | ||
declare type ActionParameters<E, F extends Action<E>> = Tail<Parameters<F>>; | ||
interface MaterializedAction<E, A extends Action<E>> { | ||
declare type MaterializedAction<E, A extends Action<E>> = { | ||
(...args: ActionParameters<E, A>): ReturnType<A>[]; | ||
one(...args: ActionParameters<E, A>): ReturnType<A>; | ||
at(n: number, ...args: ActionParameters<E, A>): ReturnType<A>; | ||
} | ||
declare type MaterializedActions<E, A extends { | ||
}; | ||
declare type MaterializedActionMap<E, ActionMap extends { | ||
[k: string]: Action<E>; | ||
}> = { | ||
[K in keyof A]: MaterializedAction<E, A[K]>; | ||
[K in keyof ActionMap]: MaterializedAction<E, ActionMap[K]>; | ||
}; | ||
declare type MaterializedTestView<E, A, B> = MaterializedActionMap<E, A & DefaultActions<E>> & MaterializedAggregateMap<E, B & DefaultAggregates> & { | ||
actions: MaterializedActionMap<E, A & DefaultActions<E>>; | ||
aggregates: MaterializedAggregateMap<E, B & DefaultAggregates>; | ||
}; | ||
declare type ParameterizedSelectorDiscriminator<S> = ((...args: any[]) => S) | S; | ||
declare type ParameterizedSelectorArgs<S, F> = F extends (...args: infer Args) => S ? Args : []; | ||
declare type ParameterizedSelector<S, F> = F extends (...args: any[]) => S ? F : S; | ||
interface TestView<S, E, A, B, F> { | ||
materialize: <MA extends ParameterizedSelectorArgs<S, F>>(e: E, ...selectorArgs: MA) => MaterializedTestView<E, A, B>; | ||
selector: ParameterizedSelector<S, F>; | ||
actions: A; | ||
aggregates: B; | ||
<NA extends ActionMap<E>, NB extends AggregateMap<E>>(nextView: TestView<S, E, NA, NB, S>): TestView<S, E, NA, NB, F>; | ||
} | ||
export interface TestViewConstructor<S, E> { | ||
<A extends ActionMap<E>, B extends AggregateMap<E>, F extends ParameterizedSelectorDiscriminator<S>>(selector: ParameterizedSelector<S, F>, actions?: A, aggregates?: B): TestView<S, E, A, B, F>; | ||
defaultViews: MaterializedDefaultViews<S, E>; | ||
} | ||
declare type Tail<T extends any[]> = ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : never; | ||
export declare class MultipleSelectedElementsError<S, E> extends Error { | ||
@@ -54,7 +70,6 @@ selector: S; | ||
export declare const makeAdapter: <S, E, EG>(composeSelectors: ComposeSelectors<S>, runSelector: RunSelector<S, E, EG>, iterateSelector: IterateSelector<E, EG>, defaultViews: DefaultViews<S, E>) => TestViewConstructor<S, E>; | ||
export interface DefaultView<S, E, A extends { | ||
[k: string]: Action<E>; | ||
}> { | ||
selector: S; | ||
export interface DefaultView<S, E, A extends ActionMap<E>, B extends AggregateMap<E>> { | ||
selector: ParameterizedSelector<S, S>; | ||
actions: A; | ||
aggregate: B; | ||
} | ||
@@ -66,27 +81,27 @@ export interface DefaultViews<S, E> { | ||
getValue: (e: E) => string; | ||
}>; | ||
}, {}>; | ||
radio: DefaultView<S, E, { | ||
select: (e: E) => void; | ||
getSelectedValue: (e: E) => string | null; | ||
}>; | ||
}, {}>; | ||
textInput: DefaultView<S, E, { | ||
enterText: (e: E, text: string) => void; | ||
getText: (e: E) => string; | ||
}>; | ||
}, {}>; | ||
singleSelect: DefaultView<S, E, { | ||
select: (e: E, value: string) => void; | ||
getSelection: (e: E) => string; | ||
}>; | ||
}, {}>; | ||
multiSelect: DefaultView<S, E, { | ||
select: (e: E, value: string[]) => void; | ||
getSelection: (e: E) => string[]; | ||
}>; | ||
}, {}>; | ||
form: DefaultView<S, E, { | ||
submit: (e: E) => void; | ||
}>; | ||
}, {}>; | ||
button: DefaultView<S, E, { | ||
click: (e: E) => void; | ||
}>; | ||
}, {}>; | ||
} | ||
declare type MaterializedDefaultView<D> = D extends DefaultView<infer S, infer E, infer A> ? TestView<S, E, A> : never; | ||
declare type MaterializedDefaultView<D> = D extends DefaultView<infer S, infer E, infer A, infer B> ? TestView<S, E, A, B, S> : never; | ||
declare type MaterializedDefaultViews<S, E> = { | ||
@@ -93,0 +108,0 @@ [K in keyof DefaultViews<S, E>]: MaterializedDefaultView<(DefaultViews<S, E>)[K]>; |
@@ -42,3 +42,3 @@ "use strict"; | ||
// less efficient. | ||
var makeTestViewConstructor = function (composeSelectors, actionRealizer, defaultViews) { | ||
var makeTestViewConstructor = function (composeSelectors, actionRealizer, aggregateRealizer, defaultViews) { | ||
// Once an adapter is plugged in, test views are created by supplying a | ||
@@ -51,22 +51,44 @@ // selector and a dictionary of actions. Views are functions, and are chained | ||
// always present to return the node(s) selected. | ||
var testView = function (selector, actionsOpt) { | ||
var testView = function (selector, actionsOpt, aggregatesOpt) { | ||
var actions = actionsOpt || {}; | ||
var aggregate = aggregatesOpt || {}; | ||
var view = function (nextView) { | ||
return testView(composeSelectors(selector, nextView.selector), nextView.actions); | ||
if (selector instanceof Function) { | ||
return testView((function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return composeSelectors(selector.apply(void 0, args), nextView.selector); | ||
}), nextView.actions, nextView.aggregates); | ||
} | ||
else { | ||
return testView(composeSelectors(selector, nextView.selector), nextView.actions, nextView.aggregates); | ||
} | ||
}; | ||
view.actions = actions; | ||
view.aggregates = aggregate; | ||
view.selector = selector; | ||
view.materialize = function (root) { | ||
var selectorArgs = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
selectorArgs[_i - 1] = arguments[_i]; | ||
} | ||
var renderedSelector = selector instanceof Function ? selector.apply(void 0, selectorArgs) : selector; | ||
var defaultActions = { | ||
get: actionRealizer(selector, function (e) { return e; }, root) | ||
get: actionRealizer(renderedSelector, function (e) { return e; }, root) | ||
}; | ||
var materializedActions = {}; | ||
var materializedActions = __assign({}, defaultActions); | ||
for (var action in actions) { | ||
if (actions.hasOwnProperty(action)) { | ||
materializedActions[action] = actionRealizer(selector, actions[action], root); | ||
materializedActions[action] = actionRealizer(renderedSelector, actions[action], root); | ||
} | ||
} | ||
return { | ||
actions: __assign({}, defaultActions, materializedActions) | ||
}; | ||
var materializedAggregate = {}; | ||
for (var agg in aggregate) { | ||
if (aggregate.hasOwnProperty(agg)) { | ||
materializedAggregate[agg] = aggregateRealizer(renderedSelector, aggregate[agg], root); | ||
} | ||
} | ||
return __assign({}, materializedActions, materializedAggregate, { actions: materializedActions, aggregates: materializedAggregate }); | ||
}; | ||
@@ -182,4 +204,11 @@ return view; | ||
}; }; | ||
var makeAggregateRealizer = function (runSelector, forEachElement) { return function (selector, aggregate, root) { return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return aggregate.apply(void 0, [forEachElement(runSelector(selector, root), function (e) { return e; })].concat(args)); | ||
}; }; }; | ||
exports.makeAdapter = function (composeSelectors, runSelector, iterateSelector, defaultViews) { | ||
return makeTestViewConstructor(composeSelectors, makeActionMaterializer(runSelector, iterateSelector), defaultViews); | ||
return makeTestViewConstructor(composeSelectors, makeActionMaterializer(runSelector, iterateSelector), makeAggregateRealizer(runSelector, iterateSelector), defaultViews); | ||
}; |
{ | ||
"name": "@mojotech/prismatest", | ||
"version": "0.1.4", | ||
"version": "0.2.0", | ||
"description": "Use test views to decouple tests from implementation details", | ||
@@ -10,4 +10,8 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@types/jest": "^24.0.17", | ||
"jest": "^24.9.0", | ||
"prettier": "^1.17.1", | ||
"typescript": "^3.5.1" | ||
"ts-jest": "^24.0.2", | ||
"typescript": "^3.5.1", | ||
"dtslint": "^0.9.1" | ||
}, | ||
@@ -19,3 +23,4 @@ "scripts": { | ||
"format": "prettier --write index.ts", | ||
"test": "echo 'No tests!'" | ||
"test": "yarn dtslint && jest", | ||
"dtslint": "tsc -d --emitDeclarationOnly --outDir ./types && dtslint --expectOnly --localTs node_modules/typescript/lib types && rm ./types/index.d.ts" | ||
}, | ||
@@ -22,0 +27,0 @@ "files": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
19166
319
2
6