Skip to content

Commit

Permalink
Change/clean up sequence type signatures, make sequences global
Browse files Browse the repository at this point in the history
  • Loading branch information
Noah Bogart committed Jan 27, 2021
1 parent dd7b34e commit 660e243
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 43 deletions.
2 changes: 2 additions & 0 deletions .projections.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"docs/*.md": {"type": "doc"},
"README.md": {"type": "doc"},
"lib/*.ts": {
"alternate": ["test/acceptance/{}.ts","test/unit/{}.ts"],
"type": "source"
Expand Down
2 changes: 1 addition & 1 deletion docs/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ explanatory comments.
import {fr, ObjectionAdapter} from "fixture-riveter";
import {User} from "./models/user";

// Each adapter can specify ORM-specific build, save, associate, and set functions
// Each adapter can specify ORM-specific build, save, associate, and set functions.
// A given adapter can be set on a specific fixture as well, allowing for
// fixture-specific build and save functionality.
fr.setAdapter(new ObjectionAdapter());
Expand Down
23 changes: 21 additions & 2 deletions lib/definition-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,28 @@ export class DefinitionProxy<T> {
this.definition.declareAttribute(association);
}

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

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

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

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

sequence(name: string, ...rest: any[]): Sequence {
Expand Down
6 changes: 4 additions & 2 deletions lib/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export class Definition<T> {
block?: BlockFunction<T>;
callbackHandler: CallbackHandler;

sequenceHandler: SequenceHandler;
declarationHandler: DeclarationHandler;

traits: Record<string, Trait<T>>;
Expand All @@ -38,13 +37,16 @@ export class Definition<T> {
this.additionalTraits = [];
this.compiled = false;

this.sequenceHandler = new SequenceHandler();
this.declarationHandler = new DeclarationHandler(name);
this.callbackHandler = new CallbackHandler(fixtureRiveter);

this.traits = {};
}

get sequenceHandler(): SequenceHandler {
return this.fixtureRiveter.sequenceHandler;
}

names(): string[] {
return [this.name, ...this.aliases];
}
Expand Down
31 changes: 23 additions & 8 deletions lib/fixture-riveter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ export class FixtureRiveter {

registerFixture<T>(fixture: Fixture<T>): void {
for (const name of fixture.names()) {
if (this.fixtures[name]) {
throw new Error(`Can't define ${name} fixture twice`);
}
this.fixtures[name] = fixture;
}
}
Expand Down Expand Up @@ -171,16 +174,28 @@ export class FixtureRiveter {
this.traits[trait.name] = trait;
}

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

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

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

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

sequence(name: string, ...rest: any[]): Sequence {
Expand Down
45 changes: 22 additions & 23 deletions lib/sequence-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,49 @@ import {
isString,
} from "lodash";

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

export class SequenceHandler {
sequences: Sequence[];
sequences: Record<string, Sequence>;

constructor() {
this.sequences = [];
this.sequences = {};
}

registerSequence(
name: string,
initial?: string | number,
options?: {aliases: string[]},
callback?: SequenceCallback,
): Sequence;

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

for (const name of newSequence.names()) {
if (this.sequences[name]) {
throw new Error(`Can't define ${name} sequence twice`);
}
this.sequences[name] = newSequence;
}

this.sequences.push(newSequence);
return newSequence;
}

resetSequences(): void {
this.sequences.forEach((seq) => seq.reset());
Object.values(this.sequences).forEach((seq) => seq.reset());
}

findSequence(name: string): Sequence | undefined {
return this.sequences.find((s: Sequence) => s.name === name);
return this.sequences[name];
}
}

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

type Initial = string | number;
type Options = {aliases: string[]};

export function optionsParser(
initial?: Initial | Options | SequenceCallback,
options?: Initial | Options | SequenceCallback,
callback?: Initial | Options | SequenceCallback,
initial?: Initial | Options | SequenceCallback<any>,
options?: Initial | Options | SequenceCallback<any>,
callback?: Initial | Options | SequenceCallback<any>,
): SequenceOptions;

export function optionsParser(...args: any[]): SequenceOptions {
Expand Down
4 changes: 2 additions & 2 deletions lib/sequences/sequence.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export type SequenceCallback = (result: string | number) => any;
export type SequenceCallback<I extends number | string> = (result: I) => any;

export abstract class Sequence {
name: string;
aliases: string[];
callback: SequenceCallback;
callback: SequenceCallback<any>;

constructor(name: string, options?: any) {
this.name = name;
Expand Down
126 changes: 126 additions & 0 deletions test/acceptance/sequences/sequence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {Model} from "../../test-fixtures/model";
import {FixtureRiveter} from "../../../lib/fixture-riveter";

import {expect} from "chai";

describe("Sequences", function() {
let fr: FixtureRiveter;

class User extends Model {
id: number;
email: string;
}

beforeEach(async function() {
fr = new FixtureRiveter();
});

describe("type checking", function() {
describe("top level", function() {
specify("1 arg", function() {
fr.sequence("email");
expect(fr.generate("email")).to.equal(1);
});

specify("2 args", function() {
fr.sequence("email1", 2);
expect(fr.generate("email1")).to.equal(2);

fr.sequence("email2", "b");
expect(fr.generate("email2")).to.equal("b");

fr.sequence("email3", {aliases: ["alias3"]});
expect(fr.generate("alias3")).to.equal(1);

fr.sequence("email4", (n) => `test${n}@gmail.com`);
expect(fr.generate("email4")).to.equal("test1@gmail.com");
});

specify("3 args", function() {
fr.sequence("email1", 1, {aliases: ["alias1"]});
expect(fr.generate("email1")).to.equal(1);
expect(fr.generate("alias1")).to.equal(2);

fr.sequence("email2", 1, (n) => `test${n}@gmail.com`);
expect(fr.generate("email2")).to.equal("test1@gmail.com");

fr.sequence("email3", "a", {aliases: ["alias3"]});
expect(fr.generate("email3")).to.equal("a");
expect(fr.generate("alias3")).to.equal("b");

fr.sequence("email4", "a", (n) => `test${n}@gmail.com`);
expect(fr.generate("email4")).to.equal("testa@gmail.com");

fr.sequence("email5", {aliases: ["alias5"]}, (n) => `test${n}@gmail.com`);
expect(fr.generate("email5")).to.equal("test1@gmail.com");
expect(fr.generate("alias5")).to.equal("test2@gmail.com");
});

specify("4 args", function() {
fr.sequence("email1", 1, {aliases: ["alias1"]}, (n) => `test${n}@gmail.com`);
expect(fr.generate("email1")).to.equal("test1@gmail.com");
expect(fr.generate("alias1")).to.equal("test2@gmail.com");

fr.sequence("email2", "a", {aliases: ["alias2"]}, (n) => `test${n}@gmail.com`);
expect(fr.generate("email2")).to.equal("testa@gmail.com");
expect(fr.generate("alias2")).to.equal("testb@gmail.com");
});
});

describe("inside a fixture", function() {
specify("1 arg", async function() {
fr.fixture("user", User, (f) => {
f.sequence("email");
});
const user = await fr.build("user");
expect(user.email).to.equal(1);
});

specify("2 args", async function() {
fr.fixture("user", User, (f) => {
f.sequence("email1", 1);
f.sequence("email2", "a");
f.sequence("email3", {aliases: ["alias3"]});
f.sequence("email4", (n) => `test${n}@gmail.com`);
});
const user = await fr.build("user");
expect(user.email1).to.equal(1);
expect(user.email2).to.equal("a");
expect(user.email3).to.equal(1);
expect(fr.generate("alias3")).to.equal(2);
expect(user.email4).to.equal("test1@gmail.com");
});

specify("3 args", async function() {
fr.fixture("user", User, (f) => {
f.sequence("email1", 1, {aliases: ["alias1"]});
f.sequence("email2", 1, (n) => `test${n}@gmail.com`);
f.sequence("email3", "a", {aliases: ["alias3"]});
f.sequence("email4", "a", (n) => `test${n}@gmail.com`);
f.sequence("email5", {aliases: ["alias5"]}, (n) => `test${n}@gmail.com`);
});
const user = await fr.build("user");
expect(user.email1).to.equal(1);
expect(fr.generate("alias1")).to.equal(2);
expect(user.email2).to.equal("test1@gmail.com");
expect(user.email3).to.equal("a");
expect(fr.generate("alias3")).to.equal("b");
expect(user.email4).to.equal("testa@gmail.com");
expect(user.email5).to.equal("test1@gmail.com");
expect(fr.generate("alias5")).to.equal("test2@gmail.com");
});

specify("4 args", async function() {
fr.fixture("user", User, (f) => {
f.sequence("email1", 1, {aliases: ["alias1"]}, (n) => `test${n}@gmail.com`);
f.sequence("email2", "a", {aliases: ["alias2"]}, (n) => `test${n}@gmail.com`);
});
const user = await fr.build("user");
expect(user.email1).to.equal("test1@gmail.com");
expect(fr.generate("alias1")).to.equal("test2@gmail.com");
expect(user.email2).to.equal("testa@gmail.com");
expect(fr.generate("alias2")).to.equal("testb@gmail.com");
});
});
});
});
4 changes: 2 additions & 2 deletions test/unit/fixture-riveter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ describe("FixtureRiveter", function() {
const fr = new FixtureRiveter();
const name = "email";
fr.sequence(name);
expect(fr.sequenceHandler.sequences).to.be.length(1);
expect(fr.sequenceHandler.sequences[0].name).to.equal(name);
expect(Object.keys(fr.sequenceHandler.sequences)).to.deep.equal([name]);
expect(fr.sequenceHandler.sequences[name]).to.be.an.instanceof(Sequence);
});
});

Expand Down
5 changes: 2 additions & 3 deletions test/unit/sequence-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ describe("SequenceHandler", function() {
const name = "email";
seq.registerSequence(name);

expect(seq.sequences).to.be.length(1);
expect(seq.sequences[0]).to.be.an.instanceof(Sequence);
expect(seq.sequences[0].name).to.equal(name);
expect(Object.keys(seq.sequences)).to.deep.equal([name]);
expect(seq.sequences[name]).to.be.an.instanceof(Sequence);
});

it("returns the new sequence", function() {
Expand Down

0 comments on commit 660e243

Please sign in to comment.