Skip to content

Commit

Permalink
🚚 move specs into own files, limit max workers to 25%, cut test time …
Browse files Browse the repository at this point in the history
…from >8s to ~4.5s
  • Loading branch information
fluffynuts committed Jul 7, 2021
1 parent efb2c57 commit b0fbdee
Show file tree
Hide file tree
Showing 10 changed files with 1,199 additions and 1,091 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Expand Up @@ -59,6 +59,7 @@ module.exports = {

// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
maxWorkers: "25%",

// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
Expand Down
26 changes: 22 additions & 4 deletions src/index.ts
Expand Up @@ -26,6 +26,7 @@ declare global {
// mocks & spies
toHaveBeenCalledOnce(): void;
toHaveBeenCalledOnceWith(...args: any[]): void;
toHaveBeenCalledOnceWithNoArgs(): void;

// promises
toBeCompleted(): Promise<void>;
Expand Down Expand Up @@ -331,11 +332,28 @@ beforeAll(() => {
toHaveBeenCalledOnce(actual: Mock) {
return runAssertions(this, () => {
expect(actual).toHaveBeenCalledTimes(1);
return () => `Expected${ notFor(this) }to have been called once`;
return () => `expected${ notFor(this) }to have been called once`;
});
},
toHaveBeenCalledOnceWithNoArgs(actual: Mock | jasmine.Spy) {
return runAssertions(this, () => {
const receivedArgs = fetchSpyOrMockArgs(actual);
const matching = receivedArgs.filter(r => r.length === 0);
assert(
matching.length === 1,
`expected${ notFor(this) }to find exactly 1 call with no arguments, but found ${ matching.length }`
);
return () => `expected${ notFor(this) }to have found exactly 1 call with no arguments`;
});
},
toHaveBeenCalledOnceWith(actual: Mock | jasmine.Spy, ...args: any[]) {
return runAssertions(this, () => {
if (args.length === 0) {
console.warn(`
'toHaveBeenCalledOnceWith' was invoked with no arguments.
If this is by design, rather use 'toHaveBeenCalledOnceWithNoArgs()'.`.trim()
);
}
const receivedArgs = fetchSpyOrMockArgs(actual);
const matching = receivedArgs.filter(
received => {
Expand All @@ -357,9 +375,9 @@ beforeAll(() => {
});
assert(
matching.length === 1,
`Should have found exactly one matching call, but found ${ matching.length }`
`expected${ notFor(this) }to have found exactly one matching call, but found ${ matching.length }`
);
return () => `Expected${ notFor(this) }to have been called once with ${ args }`;
return () => `expected${ notFor(this) }to have been called once with ${ args }`;
});
},
async toBeCompleted(actual: Promise<any>) {
Expand Down Expand Up @@ -441,7 +459,7 @@ beforeAll(() => {
},
toExist(actual: any) {
return runAssertions(this, () => {
const msg = () => `Expected ${ actual }${ notFor(this) }to exist`;
const msg = () => `expected ${ actual }${ notFor(this) }to exist`;
assert(actual !== null && actual !== undefined, msg);
return msg;
});
Expand Down
215 changes: 215 additions & 0 deletions tests/collections.spec.ts
@@ -0,0 +1,215 @@
import "../src/index";
import faker from "faker";

describe(`collections`, () => {
describe(`toBeEquivalentTo`, () => {
it(`should not throw when same collections just out of order`, async () => {
// Arrange
const
a = [ 1, 2, 3 ],
b = [ 3, 2, 1 ],
c = [ 1, 3, 2 ];
// Act
expect(a)
.toBeEquivalentTo(b);
expect(a)
.toBeEquivalentTo(c);
expect(b)
.toBeEquivalentTo(c);
// Assert
});

it(`should fail on totally different collections`, async () => {
// Arrange
const
a = [ 1, 2, 3 ],
shorter = [ 1, 2 ],
longer = [ 1, 2, 3, 4 ],
different = [ 2, 5, 6 ];
// Act
expect(a)
.not.toBeEquivalentTo(shorter);
expect(a)
.not.toBeEquivalentTo(longer);
expect(a)
.not.toBeEquivalentTo(different);
// Assert
});
});
describe(`toHaveKey`, () => {
it(`should fail when object does not exist`, async () => {
// Arrange
const obj = faker.random.arrayElement([ null, undefined ]);
// Act
expect(() =>
expect(obj)
.toHaveKey(faker.random.alphaNumeric(1))
).toThrow();
// Assert
});

it(`should pass when object has key`, async () => {
// Arrange
const
obj = {} as any,
key = faker.random.alphaNumeric(10),
value = faker.random.alphaNumeric(10);
obj[key] = value;
// Act
expect(obj)
.toHaveKey(key);
// Assert
});

it(`should fail when object does not have key`, async () => {
// Arrange
const
obj = {} as any,
key = faker.random.alphaNumeric(10),
otherKey = faker.random.alphaNumeric(10),
value = faker.random.alphaNumeric(10);
obj[key] = value;
// Act
expect(() => {
expect(obj)
.toHaveKey(otherKey)
}).toThrow();
expect(obj)
.not.toHaveKey(otherKey);
// Assert
});
});
describe(`toHaveKeys`, () => {
it(`should fail when object does not exist`, async () => {
// Arrange
const obj = faker.random.arrayElement([ null, undefined ]);
// Act
expect(() =>
expect(obj)
.toHaveKeys(faker.random.alphaNumeric(1))
).toThrow();
// Assert
});

it(`should pass when object has key`, async () => {
// Arrange
const
obj = {} as any,
key = faker.random.alphaNumeric(10),
value = faker.random.alphaNumeric(10);
obj[key] = value;
// Act
expect(obj)
.toHaveKeys(key);
// Assert
});

it(`should fail when object does not have key`, async () => {
// Arrange
const
obj = {} as any,
key = faker.random.alphaNumeric(10),
otherKey = faker.random.alphaNumeric(10),
value = faker.random.alphaNumeric(10);
obj[key] = value;
// Act
expect(() => {
expect(obj)
.toHaveKeys(otherKey)
}).toThrow();
expect(obj)
.not.toHaveKeys(otherKey);
// Assert
});

it(`should pass when all keys found`, async () => {
// Arrange
const
obj = {} as any,
key = faker.random.alphaNumeric(10),
otherKey = faker.random.alphaNumeric(10),
value = faker.random.alphaNumeric(10);
obj[key] = value;
obj[otherKey] = value;
// Act
expect(obj)
.toHaveKeys(key, otherKey);
// Assert
});
});

describe(`toAllMatch`, () => {
it(`should fail if collection is empty`, async () => {
// Arrange
const a: number[] = [];
// Act
expect(() => expect(a).toAllMatch(i => i > 0))
.toThrow();
// Assert
});
it(`should fail if even one element does not match`, async () => {
// Arrange
const
b = [ 4, 5, 6 ];
// Act
expect(b)
.not.toAllMatch(i => i < 6);
// Assert
});
it(`should pass if all elements match`, async () => {
// Arrange
const
a = [ 1, 2, 3 ];
// Act
expect(a)
.toAllMatch(i => i < 4);
// Assert
});
});

describe(`toContainElementLike`, () => {
it(`should find the single element`, async () => {
// Arrange
const array = [ { foo: "foo", bar: "bar" } ];
// Act
expect(array)
.toContainElementLike({ foo: "foo" });
// Assert
});

it(`should throw when it can't find a match`, async () => {
// Arrange
const array = [ { foo: "foo", bar: "bar" } ];
// Act
expect(() =>
expect(array)
.toContainElementLike({ foo: "foo1" })
).toThrow();
// Assert
});

it(`should not throw when negated and it can't find a match`, async () => {
// Arrange
const array = [ { foo: "foo", bar: "bar" } ];
// Act
expect(() =>
expect(array)
.not.toContainElementLike({ foo: "foo1" })
).not.toThrow();
// Assert
});

it(`should throw when negated and can find the single element`, async () => {
// Arrange
const array = [ { foo: "foo", bar: "bar" } ];
// Act
expect(() => {
expect(array)
.not.toContainElementLike({ foo: "foo" });
}).toThrow();
// Assert
}
);
});
});

47 changes: 47 additions & 0 deletions tests/dom-nodes.spec.ts
@@ -0,0 +1,47 @@
import "../src/index";

describe(`dom nodes`, () => {
it(`should assert that a node has a given attribute with string value`, async () => {
// Arrange
const node = document.createElement("div");
node.setAttribute("foo", "bar");
// Act
expect(() =>
expect(node)
.toHaveAttribute("foo", "bar")
).not.toThrow();
expect(() =>
expect(node).not.toHaveAttribute("foo", "bar")
).toThrow("Expected not to find attribute 'foo' with value 'bar'");
// Assert
});

it(`should assert that the attribute is not the unexpected value`, async () => {
// Arrange
const node = document.createElement("div");
node.setAttribute("foo", "quux");
// Act
expect(() =>
expect(node)
.not.toHaveAttribute("foo", "bar")
).not.toThrow();
expect(() => expect(node).not.toHaveAttribute("foo", "quux"))
.toThrow();
// Assert
});

it(`should assert the attribute exists at all`, async () => {
// Arrange
const node = document.createElement("div");
node.setAttribute("foo", "bar");
// Act
expect(() =>
expect(node)
.toHaveAttribute("foo")
).not.toThrow();
expect(() => expect(node).toHaveAttribute("wibbly"))
.toThrow();
// Assert
});
});

58 changes: 58 additions & 0 deletions tests/errors.spec.ts
@@ -0,0 +1,58 @@
import "../src/index";

describe(`errors`, () => {
describe(`toBeError`, () => {
it(`should match an error with string message`, async () => {
// Arrange
const
message = "le error",
error = new Error(message);
// Act
expect(error)
.toBeError(message);
// Assert
});

it(`should match an error with regex for message`, async () => {
// Arrange
const
message = "le Error",
error = new Error(message);
// Act
expect(error)
.toBeError(/err/i);
// Assert
});

it(`should not match !error`, async () => {
// Arrange
const notAnError = { message: "not an error" };
// Act
expect(notAnError)
.not.toBeError();
expect(notAnError)
.not.toBeError(/error/);
// Assert
});
it(`should not match error with incorrect message`, async () => {
// Arrange
const
message = "le Error",
error = new Error(message);
// Act
expect(error)
.not.toBeError("le error");
// Assert
});
it(`should not match error with incorrect regex`, async () => {
// Arrange
const
message = "le Error",
error = new Error(message);
// Act
expect(error)
.not.toBeError(/le error/);
// Assert
});
});
});

0 comments on commit b0fbdee

Please sign in to comment.