Skip to content

Commit

Permalink
Merge pull request #39 from Mearman/add-date-format-testing
Browse files Browse the repository at this point in the history
Add date format testing
  • Loading branch information
sywhb committed Apr 13, 2023
2 parents e6a0aba + 6649531 commit f2a9d18
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 64 deletions.
51 changes: 51 additions & 0 deletions src/DEFAULT_SETTINGS.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { OmnivoreSettings } from "./main";

export const DEFAULT_SETTINGS: OmnivoreSettings = {
dateHighlightedFormat: "yyyy-MM-dd HH:mm:ss",
dateSavedFormat: "yyyy-MM-dd HH:mm:ss",
apiKey: "",
filter: "HIGHLIGHTS",
syncAt: "",
customQuery: "",
template: `---
id: {{{id}}}
title: {{{title}}}
{{#author}}
author: {{{author}}}
{{/author}}
{{#labels.length}}
tags:
{{#labels}} - {{{name}}}
{{/labels}}
{{/labels.length}}
date_saved: {{{dateSaved}}}
{{#datePublished}}
date_published: {{{datePublished}}}
{{/datePublished}}
---
# {{{title}}}
#Omnivore
[Read on Omnivore]({{{omnivoreUrl}}})
[Read Original]({{{originalUrl}}})
{{#highlights.length}}
## Highlights
{{#highlights}}
> {{{text}}} [⤴️]({{{highlightUrl}}}) {{#labels}} #{{name}} {{/labels}}
{{#note}}
{{{note}}}
{{/note}}
{{/highlights}}
{{/highlights.length}}`,
highlightOrder: "LOCATION",
syncing: false,
folder: "Omnivore/{{date}}",
folderDateFormat: "yyyy-MM-dd",
endpoint: "https://api-prod.omnivore.app/api/graphql",
filename: "{{{title}}}"
};
134 changes: 134 additions & 0 deletions src/__tests__/formatDate.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { DEFAULT_SETTINGS } from "../DEFAULT_SETTINGS";
import { formatDate } from "../util";

const jsDate = new Date("2023-02-18 13:02:08.169");
const apiDate = jsDate.toISOString(); // API returns ISO 8601 date strings

type testCase = {
format: string,
date: string
expected: string
}


const luxonHierarchicalFormatWithTime = {
date: apiDate,
expected: "2023/2023-02/2023-02-18/130208",
format: "yyyy/yyyy-MM/yyyy-MM-dd/HHmmss"
};
const luxonHierarchicalFormat = {
date: apiDate,
expected: "2023/2023-02/2023-02-18",
format: "yyyy/yyyy-MM/yyyy-MM-dd"
};
const defaultDateHighlightedFormatTestCase: testCase = {
date: apiDate,
expected: "2023-02-18 13:02:08",
format: DEFAULT_SETTINGS.dateHighlightedFormat
};
const defaultDateSavedFormatTestCase: testCase = {
date: apiDate,
expected: "2023-02-18 13:02:08",
format: DEFAULT_SETTINGS.dateSavedFormat
};
const defaultFolderDateFormatTestCase: testCase = {
date: apiDate,
expected: "2023-02-18",
format: DEFAULT_SETTINGS.folderDateFormat
};
const testCases: testCase[] = [
defaultDateHighlightedFormatTestCase,
defaultDateSavedFormatTestCase,
defaultFolderDateFormatTestCase,
luxonHierarchicalFormat,
luxonHierarchicalFormatWithTime
];
describe("ensure default formats are as expected", () => {
test("dateHighlightedFormat", () => {
expect(DEFAULT_SETTINGS.dateHighlightedFormat).toBe("yyyy-MM-dd HH:mm:ss");
});
test("dateSavedFormat", () => {
expect(DEFAULT_SETTINGS.dateSavedFormat).toBe("yyyy-MM-dd HH:mm:ss");
});
test("folderDateFormat", () => {
expect(DEFAULT_SETTINGS.folderDateFormat).toBe("yyyy-MM-dd");
});
});

describe("formatDate on known formats", () => {
test.each(testCases)("should correctly format %s", (testCase) => {
const result = formatDate(testCase.date, testCase.format);
expect(result).toBe(testCase.expected);
});
});

const { DateTime } = require("luxon");

function generateRandomISODateStrings(quantity: number) {
const randomISODateStrings = [];
const timeZones: any[] = Intl.DateTimeFormat().resolvedOptions().timeZone.split(",");

for (let i = 0; i < quantity; i++) {
let date = new Date(
Date.UTC(
Math.floor(Math.random() * (2038 - 1970) + 1970),
Math.floor(Math.random() * 12),
Math.floor(Math.random() * 28),
Math.floor(Math.random() * 24),
Math.floor(Math.random() * 60),
Math.floor(Math.random() * 60),
Math.floor(Math.random() * 1000)
)
);

// Randomly select a timezone from the available time zones
const randomTimeZone = timeZones[Math.floor(Math.random() * timeZones.length)];

// Convert the generated date to the randomly selected timezone
// const dateTimeWithZone = DateTime.fromJSDate(date, { zone: randomTimeZone }).toUTC();
const jsDateTimeWithZone = new Date(date.toLocaleString("en-US", { timeZone: randomTimeZone }));
const luxonDate = DateTime.fromJSDate(jsDateTimeWithZone);
randomISODateStrings.push(luxonDate.toISO());
}

return randomISODateStrings;
}

describe("formatDate on random dates", () => {
test.each(generateRandomISODateStrings(100))("should correctly format %s", (date) => {
const result = formatDate(date, "yyyy-MM-dd HH:mm:ss");
// test with regex to ensure the format is correct
expect(result).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
});
});

function getCasesWithRandomDates(testFormats: string[], quantity = 10) {
return testFormats.flatMap(luxonFormat =>
generateRandomISODateStrings(quantity).map(date => ({ date, luxonFormat }))
);
}

describe("round trip on random dates", () => {
const testFormats = [
defaultDateHighlightedFormatTestCase.format,
defaultDateSavedFormatTestCase.format,
defaultFolderDateFormatTestCase.format
];
// generate permutations of testCases.formats and 10 generated each
const casesWithRandomDates = getCasesWithRandomDates(testFormats);
test.each(casesWithRandomDates)("should be unchanged after round trip %s", (testCase) => {
const result = formatDate(testCase.date, testCase.luxonFormat);
const result2 = formatDate(result, testCase.luxonFormat);
expect(result2).toBe(result);
});

const atypicalFormats = [
luxonHierarchicalFormat.format,
luxonHierarchicalFormatWithTime.format
];
test.each(getCasesWithRandomDates(atypicalFormats))("should be unchanged after round trip with atypical format %s", (testCase) => {
const formattedDate = formatDate(testCase.date, testCase.luxonFormat);
const parsedDate = DateTime.fromFormat(formattedDate, testCase.luxonFormat);
expect(parsedDate.isValid).toBe(true);
});
});
64 changes: 3 additions & 61 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
parseDateTime,
replaceIllegalChars,
} from "./util";
import { DEFAULT_SETTINGS } from "./DEFAULT_SETTINGS";

enum Filter {
ALL = "import all my articles",
Expand All @@ -38,7 +39,7 @@ enum HighlightOrder {
TIME = "the time that highlights are updated",
}

interface Settings {
export interface OmnivoreSettings {
apiKey: string;
filter: string;
syncAt: string;
Expand All @@ -54,68 +55,9 @@ interface Settings {
filename: string;
attachmentFolder: string;
}
const DEFAULT_SETTINGS: Settings = {
dateHighlightedFormat: "yyyy-MM-dd HH:mm:ss",
dateSavedFormat: "yyyy-MM-dd HH:mm:ss",
apiKey: "",
filter: "HIGHLIGHTS",
syncAt: "",
customQuery: "",
template: `---
id: {{id}}
title: "{{{title}}}"
{{#author}}
author: "{{{author}}}"
{{/author}}
{{#labels.length}}
tags:
{{#labels}} - "{{{name}}}"
{{/labels}}
{{/labels.length}}
date_saved: "{{{dateSaved}}}"
{{#datePublished}}
date_published: "{{{datePublished}}}"
{{/datePublished}}
---
# {{{title}}}
#Omnivore
[Read on Omnivore]({{{omnivoreUrl}}})
[Read Original]({{{originalUrl}}})
{{#note}}
## Note
{{{note}}}
{{/note}}
{{#pdfAttachment}}
![[{{{pdfAttachment}}}]]
{{/pdfAttachment}}
{{#highlights.length}}
## Highlights
{{#highlights}}
> {{{text}}} [⤴️]({{{highlightUrl}}}) {{#labels}} #{{{name}}} {{/labels}}
{{#note}}
{{{note}}}
{{/note}}
{{/highlights}}
{{/highlights.length}}`,
highlightOrder: "LOCATION",
syncing: false,
folder: "Omnivore/{{{date}}}",
folderDateFormat: "yyyy-MM-dd",
endpoint: "https://api-prod.omnivore.app/api/graphql",
filename: "{{{title}}}",
attachmentFolder: "Omnivore/attachments",
};

export default class OmnivorePlugin extends Plugin {
settings: Settings;
settings: OmnivoreSettings;

async onload() {
await this.loadSettings();
Expand Down
10 changes: 7 additions & 3 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,10 @@ export const replaceIllegalChars = (str: string): string => {
return str.replace(ILLEGAL_CHAR_REGEX, REPLACEMENT_CHAR);
};

export const formatDate = (date: string, format: string): string => {
return DateTime.fromISO(date).toFormat(format);
};
export function formatDate(date: string, format: string): string {
if (isNaN(Date.parse(date))) {
throw new Error(`Invalid date: ${date}`);
}
return DateTime.fromJSDate(new Date(date)).toFormat(format);
}

0 comments on commit f2a9d18

Please sign in to comment.