Skip to content

Commit

Permalink
Fully rewrite Sequences to use generators
Browse files Browse the repository at this point in the history
Sequences were originally written as complex classes with internal logic. This
worked well enough but failed to handle the ability to extend them. To handle
this need, I've switched to a single Sequence class that holds a Generator
Function[0], moving all options parsing into the Sequence class.

[0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

To handle passing in strings or numbers, I've written two default generators
(well, wrote one, borrowed one): numberGen and stringGen. numberGen is a simple
incrementing counter, and stringGen is an implementation of Ruby's `String#succ`
method.

Other changes:

* options parsing has been made more strict: the options must be in order.
* Sequence constructor is fully typed
* SequenceHandler.registerSequence is fully typed
* FixtureRiveter.sequence is fully typed
* Wrote a bunch of tests, idk if they're good or not, tests are hard
  • Loading branch information
Noah Bogart committed Jan 28, 2021
1 parent 7fb980b commit a0af35d
Show file tree
Hide file tree
Showing 17 changed files with 576 additions and 797 deletions.
2 changes: 1 addition & 1 deletion lib/attributes/sequence-attribute.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Attribute} from "./attribute";
import {Sequence} from "../sequences/sequence";
import {Sequence} from "../sequence";

export class SequenceAttribute extends Attribute {
sequence: Sequence;
Expand Down
29 changes: 13 additions & 16 deletions lib/definition-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import {
} from "./types";
import {CallbackFunction} from "./callback";
import {FixtureRiveter, nameGuard} from "./fixture-riveter";
import {
Sequence,
SequenceCallback,
} from "./sequences/sequence";
import {Sequence, SequenceCallback} from "./sequence";
import {SequenceHandler} from "./sequence-handler";

import {isFunction, last} from "lodash";
Expand Down Expand Up @@ -121,28 +118,28 @@ export class DefinitionProxy<T> {
this.definition.declareAttribute(association);
}

sequence<I extends number | string>(
sequence(
name: string,
options?: I | {aliases: string[]} | SequenceCallback<I>,
options?: string | number | Generator<any, any, any> | string[] | SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
initial: I,
aliasesOrCallback?: {aliases: string[]} | SequenceCallback<I>,
initial: string | number | Generator<any, any, any>,
aliasesOrCallback?: string[] | SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
aliases: {aliases: string[]},
callback?: SequenceCallback<I>,
initialOrAliases: string | number | Generator<any, any, any> | string[],
callback?: SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
initial: I,
aliases: {aliases: string[]},
callback: SequenceCallback<I>,
initial: string | number | Generator<any, any, any>,
aliases: string[],
callback?: SequenceCallback,
): Sequence;

sequence(name: string, ...rest: any[]): Sequence {
Expand Down
44 changes: 18 additions & 26 deletions lib/fixture-riveter.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import {Adapter} from "./adapters/adapter";
import {AdapterHandler, FixtureNames} from "./adapter-handler";
import {Adapter} from "./adapters/adapter";
import {CallbackFunction, Callback} from "./callback";
import {CallbackHandler} from "./callback-handler";
import {DefinitionProxy} from "./definition-proxy";
import {Fixture} from "./fixture";
import {
fixtureOptionsParser,
} from "./fixture-options-parser";
import {
Sequence,
SequenceCallback,
} from "./sequences/sequence";
import {Sequence, SequenceCallback} from "./sequence";
import {SequenceHandler} from "./sequence-handler";
import {Trait} from "./trait";
import {
CallbackFunction,
Callback,
} from "./callback";
import {CallbackHandler} from "./callback-handler";
import {StrategyHandler} from "./strategy-handler";
import {Strategy} from "./strategies/strategy";
import {Trait} from "./trait";
import {fixtureOptionsParser} from "./fixture-options-parser";

import {
Pojo,
Expand Down Expand Up @@ -175,28 +167,28 @@ export class FixtureRiveter {
this.traits[trait.name] = trait;
}

sequence<I extends number | string>(
sequence(
name: string,
options?: I | {aliases: string[]} | SequenceCallback<I>,
options?: string | number | Generator<any, any, any> | string[] | SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
initial: I,
aliasesOrCallback?: {aliases: string[]} | SequenceCallback<I>,
initial: string | number | Generator<any, any, any>,
aliasesOrCallback?: string[] | SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
aliases: {aliases: string[]},
callback?: SequenceCallback<I>,
initialOrAliases: string | number | Generator<any, any, any> | string[],
callback?: SequenceCallback,
): Sequence;

sequence<I extends number | string>(
sequence(
name: string,
initial: I,
aliases: {aliases: string[]},
callback: SequenceCallback<I>,
initial: string | number | Generator<any, any, any>,
aliases: string[],
callback?: SequenceCallback,
): Sequence;

sequence(name: string, ...rest: any[]): Sequence {
Expand Down
71 changes: 26 additions & 45 deletions lib/sequence-handler.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
import {
Sequence,
SequenceCallback,
} from "./sequences/sequence";
import {IntegerSequence} from "./sequences/integer-sequence";
import {StringSequence} from "./sequences/string-sequence";

import {
isFunction,
isNumber,
isPlainObject,
isString,
} from "lodash";
import {Sequence, SequenceCallback} from "./sequence";

export class SequenceHandler {
sequences: Record<string, Sequence>;
Expand All @@ -19,9 +7,32 @@ export class SequenceHandler {
this.sequences = {};
}

registerSequence(
sequenceName: string,
options?: string | number | Generator<any, any, any> | string[] | SequenceCallback,
): Sequence;

registerSequence(
sequenceName: string,
initial: string | number | Generator<any, any, any>,
aliasesOrCallback?: string[] | SequenceCallback,
): Sequence;

registerSequence(
sequenceName: string,
initialOrAliases: string | number | Generator<any, any, any> | string[],
callback?: SequenceCallback,
): Sequence;

registerSequence(
sequenceName: string,
initial: string | number | Generator<any, any, any>,
aliases: string[],
callback?: SequenceCallback,
): Sequence;

registerSequence(sequenceName: string, ...rest: any[]): Sequence {
const options = optionsParser(...rest);
const newSequence = sequenceChooser(sequenceName, options);
const newSequence = new Sequence(sequenceName, ...rest);

for (const name of newSequence.names()) {
if (this.sequences[name]) {
Expand All @@ -41,33 +52,3 @@ export class SequenceHandler {
return this.sequences[name];
}
}

interface SequenceOptions {
initial?: string | number;
aliases?: string[];
callback?: SequenceCallback<any>;
}

export function optionsParser(...args: any[]): SequenceOptions {
const options = {} as SequenceOptions;
for (const arg of args) {
if ((isNumber(arg) || isString(arg)) && !options.initial) {
options.initial = arg;
} else if ((isPlainObject(arg) && arg.aliases) && !options.aliases) {
options.aliases = [...arg.aliases];
} else if (isFunction(arg) && !options.callback) {
options.callback = arg;
}
}
return options;
}

export function sequenceChooser(name: string, options: SequenceOptions): Sequence {
let newSequence: Sequence;
if (isString(options.initial)) {
newSequence = new StringSequence(name, options);
} else {
newSequence = new IntegerSequence(name, options);
}
return newSequence;
}

0 comments on commit a0af35d

Please sign in to comment.