-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from gardusig/feat/tests
Feat/tests
- Loading branch information
Showing
13 changed files
with
4,240 additions
and
813 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = { | ||
preset: "ts-jest", | ||
testEnvironment: "node", | ||
transform: { | ||
"^.+\\.ts$": "ts-jest", | ||
}, | ||
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], | ||
}; |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
namespace Constants { | ||
export namespace Constants { | ||
export const folderPrefix = "self-management/death-note"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
export namespace Cupid.DateService { | ||
/** | ||
* Enum representing days of the week. | ||
*/ | ||
export enum DayOfWeek { | ||
SUNDAY = 0, | ||
MONDAY = 1, | ||
TUESDAY = 2, | ||
WEDNESDAY = 3, | ||
THURSDAY = 4, | ||
FRIDAY = 5, | ||
SATURDAY = 6, | ||
} | ||
|
||
/** | ||
* Calculates the week number of the current date based on the given base day. If the year starts after the base year, that is week 0. Week 1 starts after the first baseDay of the year. | ||
* @param baseDay - The base day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday). | ||
* @returns {number} - The week number. | ||
*/ | ||
export function getWeekNumber(baseDay: DayOfWeek = DayOfWeek.MONDAY): number { | ||
const daysSinceFirstBaseDay: number = getDaysSinceFirstBaseDay(baseDay); | ||
return Math.floor(daysSinceFirstBaseDay / 7) + 1; | ||
} | ||
|
||
/** | ||
* Retrieves the current date formatted as a string in "yyyy-MM-dd" format, | ||
* adjusted to the script's time zone. | ||
* @returns {string} The formatted date string. | ||
*/ | ||
export function getFormattedDate(): string { | ||
return Utilities.formatDate( | ||
new Date(), | ||
Session.getScriptTimeZone(), | ||
"yyyy-MM-dd", | ||
); | ||
} | ||
|
||
function getFirstBaseDayOfYear(year: number, baseDay: DayOfWeek): Date { | ||
const date = new Date(year, 0, 1); | ||
while (date.getDay() !== baseDay) { | ||
date.setDate(date.getDate() - 1); | ||
} | ||
return date; | ||
} | ||
|
||
function getDaysSinceFirstBaseDay(baseDay: DayOfWeek): number { | ||
const now: Date = new Date(); | ||
const year: number = now.getFullYear(); | ||
const firstBaseDay: Date = getFirstBaseDayOfYear(year, baseDay); | ||
const dayDuration = 1000 * 3600 * 24; | ||
return Math.floor((now.getTime() - firstBaseDay.getTime()) / dayDuration); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
namespace Journal { | ||
import { Constants } from "../constants"; | ||
import { Cupid } from "../cupid/dateservice"; | ||
|
||
export namespace Journal { | ||
export function getFolderPath(): string { | ||
const weekNumber = DateUtil.getWeekNumber(); | ||
const weekNumber = Cupid.DateService.getWeekNumber(); | ||
return `${Constants.folderPrefix}/week-${weekNumber}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import { Cupid } from "./cupid/dateservice"; | ||
import { Journal } from "./journal/journal"; | ||
|
||
export function createDailyJournalDoc(): void { | ||
const docName = DateUtil.getFormattedDate(); | ||
const docName = Cupid.DateService.getFormattedDate(); | ||
const folderPath = Journal.getFolderPath(); | ||
ToiletPaper.Tissuer.createRoll(docName, folderPath); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { Cupid } from "../../src/cupid/dateservice"; | ||
import { TestRunner } from "../testrunner"; | ||
|
||
TestRunner.runTestSuiteWithMock( | ||
"Cupid.DateService", | ||
weekNumberTestSuiteGenerator, | ||
formattedDateTestSuiteGenerator, | ||
); | ||
|
||
function weekNumberTestSuiteGenerator(): TestRunner.TestSuite { | ||
const testCases = []; | ||
const startDate = new Date("2024-06-03T00:00:00-03:00"); // Monday | ||
for (let weekCounter = 0; weekCounter < 3; weekCounter++) { | ||
for (let weekDay = 0; weekDay < 7; weekDay++) { | ||
const date = new Date(startDate); | ||
date.setDate(date.getDate() + weekCounter * 7 + weekDay); | ||
const expectedWeekNumber = 23 + weekCounter; | ||
const todayMockedDate = date.toISOString(); | ||
testCases.push( | ||
createWeekNumberTestCase(expectedWeekNumber, todayMockedDate), | ||
); | ||
} | ||
} | ||
return { | ||
testName: "getWeekNumber", | ||
testCases: testCases, | ||
}; | ||
} | ||
|
||
function formattedDateTestSuiteGenerator(): TestRunner.TestSuite { | ||
const testCases = []; | ||
for (let day = 1; day < 31; day += 1) { | ||
const date = new Date( | ||
`2024-06-${String(day).padStart(2, "0")}T00:00:00-03:00`, | ||
); | ||
const expectedFormattedDate = date.toISOString().split("T")[0]; | ||
testCases.push( | ||
createFormattedDateTestCase(expectedFormattedDate, date.toISOString()), | ||
); | ||
} | ||
return { | ||
testName: "getFormattedDate", | ||
testCases: testCases, | ||
}; | ||
} | ||
|
||
function createWeekNumberTestCase( | ||
expectedWeekNumber: number, | ||
mockedDate: string, | ||
): TestRunner.TestCase { | ||
return { | ||
mockSettings: { todayDate: mockedDate }, | ||
testCaseName: `should produce week number '${expectedWeekNumber}' given date '${mockedDate}'`, | ||
testFunction: () => { | ||
const result = Cupid.DateService.getWeekNumber(); | ||
expect(result).toBe(expectedWeekNumber); | ||
}, | ||
}; | ||
} | ||
|
||
function createFormattedDateTestCase( | ||
expectedFormattedDate: string, | ||
mockedDate: string, | ||
): TestRunner.TestCase { | ||
return { | ||
mockSettings: { todayDate: mockedDate }, | ||
testCaseName: `should produce formatted date '${expectedFormattedDate}' given date '${mockedDate}'`, | ||
testFunction: () => { | ||
const formattedDate = Cupid.DateService.getFormattedDate(); | ||
expect(formattedDate).toBe(expectedFormattedDate); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
export namespace TestMock { | ||
export interface Settings { | ||
todayDate: string; | ||
} | ||
|
||
export function setupMocks(settings: Settings): void { | ||
setupDateMock(settings.todayDate); | ||
setupSessionMock(); | ||
setupUtilitiesMock(); | ||
} | ||
|
||
export function cleanupMocks(): void { | ||
global.Date = OriginalDate; | ||
global.Utilities = OriginalUtilities; | ||
global.Session = OriginalSession; | ||
} | ||
|
||
function setupDateMock(todayDateMock: string): void { | ||
global.Date = class extends Date { | ||
constructor(...args: any[]) { | ||
if (args.length === 0) { | ||
super(todayDateMock); | ||
} else { | ||
super(...(args as ConstructorParameters<typeof Date>)); | ||
} | ||
} | ||
} as typeof Date; | ||
} | ||
|
||
function setupUtilitiesMock(): void { | ||
global.Utilities = { | ||
...OriginalUtilities, | ||
formatDate: formatDateMock, | ||
} as GoogleAppsScript.Utilities.Utilities; | ||
} | ||
|
||
function setupSessionMock(): void { | ||
global.Session = { | ||
...OriginalSession, | ||
getScriptTimeZone: getScriptTimeZoneMock, | ||
} as GoogleAppsScript.Base.Session; | ||
} | ||
|
||
const formatDateMock = jest.fn((date, _timeZone, _format) => { | ||
const pad = (n: number) => (n < 10 ? "0" + n : n); | ||
const yyyy = date.getFullYear(); | ||
const mm = pad(date.getMonth() + 1); | ||
const dd = pad(date.getDate()); | ||
return `${yyyy}-${mm}-${dd}`; | ||
}); | ||
|
||
const getScriptTimeZoneMock = jest.fn(() => "GMT-3"); | ||
|
||
const OriginalDate = global.Date; | ||
const OriginalUtilities = global.Utilities; | ||
const OriginalSession = global.Session; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { TestMock } from "./testmock"; | ||
|
||
export namespace TestRunner { | ||
export function runTestSuiteWithMock( | ||
testSuiteName: string, | ||
...testSuiteGenerators: TestSuiteGenerator[] | ||
): void { | ||
describe(testSuiteName, () => { | ||
for (const testSuiteGenerator of testSuiteGenerators) { | ||
const testSuite = testSuiteGenerator(); | ||
describe(testSuite.testName, () => { | ||
runTestCaseWithMock(...shuffleArray(testSuite.testCases)); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
export function runTestCaseWithMock(...testCases: TestCase[]): void { | ||
testCases.forEach((testCase) => { | ||
it(testCase.testCaseName, () => { | ||
TestMock.setupMocks(testCase.mockSettings); | ||
try { | ||
testCase.testFunction(); | ||
} finally { | ||
TestMock.cleanupMocks(); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
export interface TestSuite { | ||
testName: string; | ||
testCases: TestCase[]; | ||
} | ||
|
||
export interface TestCase { | ||
mockSettings: TestMock.Settings; | ||
testFunction: () => void; | ||
testCaseName: string; | ||
} | ||
|
||
type TestSuiteGenerator = () => TestSuite; | ||
|
||
function shuffleArray<T>(array: T[]): T[] { | ||
for (let i = array.length - 1; i > 0; i--) { | ||
const j = Math.floor(Math.random() * (i + 1)); | ||
[array[i], array[j]] = [array[j], array[i]]; | ||
} | ||
return array; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters