Skip to content

Commit

Permalink
Add ITestPlan, ITestSuite, and ITestCase interfaces (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
crookse authored Jun 22, 2020
2 parents 41d98de + fbaaa59 commit e10954f
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 117 deletions.
92 changes: 8 additions & 84 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,7 @@
import { asserts } from "./deps.ts";
import { MockServerRequest } from "./src/mocks/server_request.ts";
import { TestCase } from "./src/test_case.ts";

/**
* Example:
*
* {
* suites: {
* "My Suite": {
* cases: [
* {
* name: "My Case",
* new_name: this.formatTestCaseName(name),
* testFn: Function
* },
* ...
* ],
* after_all_case_hook: Function,
* after_each_case_hook: Function,
* before_all_case_hook: Function,
* before_each_case_hook: Function
* },
* ... // More suites allowed
* },
* after_all_suite_hook: Function;
* after_each_suite_hook: Function;
* before_all_suite_hook: Function;
* before_each_suite_hook: Function;
* }
*
* or:
*
* {
suites: {
run(): {
cases: [Array],
after_all_case_hook: [Function],
before_all_case_hook: [Function],
before_each_case_hook: [Function],
after_each_case_hook: [Function]
},
close(): {
cases: [Array],
after_all_case_hook: [Function],
before_all_case_hook: [Function],
before_each_case_hook: [Function],
after_each_case_hook: [Function]
}
},
before_each_suite_hook: [Function],
after_each_suite_hook: [Function],
after_all_suite_hook: [Function],
before_all_suite_hook: [Function]
* }
*/
interface Plan {
[key: string]: { // Plan name
suites?: {
[key: string]: { // suite names
cases?: Array<{
name: string;
new_name: string;
testFn: Function;
}>;
after_all_case_hook?: Function;
after_each_case_hook?: Function;
before_all_case_hook?: Function;
before_each_case_hook?: Function;
};
};
after_all_suite_hook?: Function;
after_each_suite_hook?: Function;
before_all_suite_hook?: Function;
before_each_suite_hook?: Function;
};
}
import { ITestPlan, ITestSuite, ITestCase } from "./src/interfaces.ts";

/**
* @description
Expand Down Expand Up @@ -131,7 +58,7 @@ export class RhumRunner {
protected passed_in_test_suite: string = "";
protected test_plan_in_progress: string = "";
protected test_suite_in_progress: string = "";
protected plan: any = {}; // TODO(ebebbington) Needs a type, use Plan interface but fix the TS errors it gives
protected plan: ITestPlan = { suites: {} };

// FILE MARKER - METHODS - CONSTRUCTOR ///////////////////////////////////////

Expand Down Expand Up @@ -159,7 +86,7 @@ export class RhumRunner {
// Check if the hook is for test cases inside of a suite
if (this.passed_in_test_plan && this.passed_in_test_suite) {
// is a before each inside a suite for every test case
this.plan.suites[this.passed_in_test_suite].before_each_case_hook = cb;
this.plan.suites![this.passed_in_test_suite].before_each_case_hook = cb;
} else if (this.passed_in_test_plan && !this.passed_in_test_suite) {
// before each hooks for the suites
this.plan.before_each_suite_hook = cb;
Expand All @@ -180,7 +107,7 @@ export class RhumRunner {
// Check if the hook is for test cases inside of a suite
if (this.passed_in_test_plan && this.passed_in_test_suite) {
// is a after each inside a suite for every test case
this.plan.suites[this.passed_in_test_suite].after_each_case_hook = cb;
this.plan.suites![this.passed_in_test_suite].after_each_case_hook = cb;
} else if (this.passed_in_test_plan && !this.passed_in_test_suite) {
// after each hooks for the suites
this.plan.after_each_suite_hook = cb;
Expand All @@ -201,7 +128,7 @@ export class RhumRunner {
// Check if the hook is for test cases inside of a suite
if (this.passed_in_test_plan && this.passed_in_test_suite) {
// is a before all inside a suite for every test case
this.plan.suites[this.passed_in_test_suite].after_all_case_hook = cb;
this.plan.suites![this.passed_in_test_suite].after_all_case_hook = cb;
} else if (this.passed_in_test_plan && !this.passed_in_test_suite) {
// before all hooks for the suites
this.plan.after_all_suite_hook = cb;
Expand All @@ -222,7 +149,7 @@ export class RhumRunner {
// Check if the hook is for test cases inside of a suite
if (this.passed_in_test_plan && this.passed_in_test_suite) {
// is a before all inside a suite for every test case
this.plan.suites[this.passed_in_test_suite].before_all_case_hook = cb;
this.plan.suites![this.passed_in_test_suite].before_all_case_hook = cb;
} else if (this.passed_in_test_plan && !this.passed_in_test_suite) {
// before all hooks for the suites
this.plan.before_all_suite_hook = cb;
Expand Down Expand Up @@ -268,7 +195,7 @@ export class RhumRunner {
* @return void
*/
public testCase(name: string, testFn: Function): void {
this.plan.suites[this.passed_in_test_suite].cases.push({
this.plan.suites[this.passed_in_test_suite].cases!.push({
name,
new_name: this.formatTestCaseName(name),
testFn,
Expand All @@ -289,9 +216,6 @@ export class RhumRunner {
public testPlan(name: string, testSuites: Function): void {
this.passed_in_test_suite = ""; // New plan
this.passed_in_test_plan = name;
this.plan = {
suites: {},
};
testSuites();
}

Expand All @@ -308,7 +232,7 @@ export class RhumRunner {
*/
public testSuite(name: string, testCases: Function): void {
this.passed_in_test_suite = name;
this.plan.suites[name] = { cases: [] };
this.plan.suites![name] = { cases: [] };
testCases();
}

Expand Down
126 changes: 126 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* @description
*
* suites
* An object of objects matching the ITestSuite interface.
*
* after_all_suite_hook?
* A callback function to execute after all test suites.
*
* after_each_suite_hook?
* A callback function to execute after each test suite.
*
* before_all_suite_hook?
* A callback function to execute before all test suites.
*
* before_each_suite_hook?
* A callback function to execute before each test suite.
*
*
* Example below ...
*
* {
* suites: {
* "My Suite": {
* cases: [
* {
* name: "My Case",
* new_name: this.formatTestCaseName(name),
* testFn: Function
* },
* ...
* ],
* after_all_case_hook: Function,
* after_each_case_hook: Function,
* before_all_case_hook: Function,
* before_each_case_hook: Function
* },
* ... // More suites allowed
* },
* after_all_suite_hook: Function;
* after_each_suite_hook: Function;
* before_all_suite_hook: Function;
* before_each_suite_hook: Function;
* }
*
* ... or ...
*
* {
* suites: {
* run(): {
* cases: [Array],
* after_all_case_hook: [Function],
* before_all_case_hook: [Function],
* before_each_case_hook: [Function],
* after_each_case_hook: [Function]
* },
* close(): {
* cases: [Array],
* after_all_case_hook: [Function],
* before_all_case_hook: [Function],
* before_each_case_hook: [Function],
* after_each_case_hook: [Function]
* }
* },
* before_each_suite_hook: [Function],
* after_each_suite_hook: [Function],
* after_all_suite_hook: [Function],
* before_all_suite_hook: [Function]
* }
*/
export interface ITestPlan {
suites: {
[key: string]: ITestSuite; // "key" is the suite name
};
after_all_suite_hook?: Function;
after_each_suite_hook?: Function;
before_all_suite_hook?: Function;
before_each_suite_hook?: Function;
}

/**
* @description
* cases?
* An array of objects matching the ITestCase interface.
*
* after_all_case_hook?
* A callback function to execute after all test cases.
*
* after_each_case_hook?
* A callback function to execute after each test case.
*
* before_all_case_hook?
* A callback function to execute before all test cases.
*
* before_each_case_hook?
* A callback function to execute before each test case.
*/
export interface ITestSuite {
cases?: ITestCase[];
after_all_case_hook?: Function;
after_each_case_hook?: Function;
before_all_case_hook?: Function;
before_each_case_hook?: Function;
}

/**
* @description
* name
* The name of the test case.
*
* new_name
* The new name of the test. This is strictly for outputting purposes.
* Deno's test runner outputs "test name of test" and we want to
* overwrite that text. This new_name string helps us do that. See
* formatTestCaseName() in mod.ts for more information.
*
* testFn
* The test function. Ultimately, this gets passed as the second
* argument of Deno.test().
*/
export interface ITestCase {
name: string;
new_name: string;
testFn: Function;
}

15 changes: 8 additions & 7 deletions src/test_case.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const encoder = new TextEncoder();
import { ITestPlan, ITestCase } from "./interfaces.ts";

/**
* A class to help create uniform test case objects.
*/
export class TestCase {
protected plan: any; // TODO(ebebbington) Use Plan interface
protected plan: ITestPlan;

constructor(plan: any) { // TODO(ebebbington) Use Plan interface
constructor(plan: ITestPlan) {
this.plan = plan;
}

Expand All @@ -16,7 +17,7 @@ export class TestCase {
}
Object.keys(this.plan.suites).forEach((suiteName) => {
// Run cases
this.plan.suites[suiteName].cases.forEach(async (c: any) => {
this.plan!.suites[suiteName].cases!.forEach(async (c: ITestCase) => {
// Run the case - required to run like this because the
// hooks need to be ran inside the Deno.test call. Deno.test seems to queue
// the tests, meaning all hooks are ran, and **then** the tests are ran
Expand All @@ -28,17 +29,17 @@ export class TestCase {
this.plan.before_each_suite_hook();
}
if (this.plan.suites[suiteName].before_all_case_hook) {
this.plan.suites[suiteName].before_all_case_hook();
this.plan.suites[suiteName].before_all_case_hook!();
}
if (this.plan.suites[suiteName].before_each_case_hook) {
this.plan.suites[suiteName].before_each_case_hook();
this.plan.suites[suiteName].before_each_case_hook!();
}
await c.testFn();
if (this.plan.suites[suiteName].after_each_case_hook) {
this.plan.suites[suiteName].after_each_case_hook();
this.plan.suites[suiteName].after_each_case_hook!();
}
if (this.plan.suites[suiteName].after_all_case_hook) {
this.plan.suites[suiteName].after_all_case_hook();
this.plan.suites[suiteName].after_all_case_hook!();
}
if (this.plan.after_each_suite_hook) {
this.plan.after_each_suite_hook();
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/hooks/after_all_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ Rhum.testPlan("app_test.ts", () => {
});
Rhum.testCase("Returns false", () => {
// Assert the value has changes as the hook should have ran
Rhum.asserts.assertEquals(case_val, 2)
})
Rhum.asserts.assertEquals(case_val, 2);
});
});

// Run the second test suite
Expand All @@ -45,4 +45,4 @@ Rhum.testPlan("app_test.ts", () => {
});
});

Rhum.run();
Rhum.run();
6 changes: 3 additions & 3 deletions tests/integration/hooks/after_each_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ Rhum.testPlan("app_test.ts", () => {
});
Rhum.testCase("Returns false", () => {
// Assert the value has changes as the hook should have ran
Rhum.asserts.assertEquals(case_val, 2)
})
Rhum.asserts.assertEquals(case_val, 2);
});
});

// Run the second test suite
Expand All @@ -45,4 +45,4 @@ Rhum.testPlan("app_test.ts", () => {
});
});

Rhum.run();
Rhum.run();
8 changes: 4 additions & 4 deletions tests/integration/hooks/before_all_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ Rhum.testPlan("app_test.ts", () => {
suite_val = "Ed";
// Assert the value has changed from 22 to 2
Rhum.asserts.assertEquals(case_val, 2);
case_val = 22
case_val = 22;
});
Rhum.testCase("Returns false", () => {
// Assert the value has changed from 22 to 2 (after setting it to 22 in the above case)
Rhum.asserts.assertEquals(case_val, 2)
})
Rhum.asserts.assertEquals(case_val, 2);
});
});

// Run the second test suite
Expand All @@ -45,4 +45,4 @@ Rhum.testPlan("app_test.ts", () => {
});
});

Rhum.run();
Rhum.run();
Loading

0 comments on commit e10954f

Please sign in to comment.