From 05ce98495abff0fa781ccfc0648a4722e48a7447 Mon Sep 17 00:00:00 2001 From: Roger Floriano <31597636+petruki@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:00:09 -0700 Subject: [PATCH] Fixed major code smells (#10) * Fixed major code smells * Fixes fetch using file:/// urls * Fixed Deno version typo * Replaced deprecated test deps --- .github/workflows/master.yml | 4 +- deno.jsonc | 6 +- deno.lock | 36 ++++++++- example/app.ts | 23 +++--- mod.ts | 9 +-- sonar-project.properties | 2 +- src/lib/cache.ts | 25 ++---- src/lib/exceptions.ts | 4 +- src/lib/utils.ts | 53 +++++------- src/skimming.ts | 21 ++--- test/cache_test.ts | 151 +++++++++++++++++----------------- test/deps.ts | 6 +- test/fixtures/README.md | 12 +-- test/mod_test.ts | 153 ++++++++++++++--------------------- test/utils_test.ts | 36 +++++---- 15 files changed, 243 insertions(+), 298 deletions(-) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 4ddf8ca..0838f7b 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -18,10 +18,10 @@ jobs: with: fetch-depth: 0 - - name: Setup Deno v1.33.4 + - name: Setup Deno v1.37.0 uses: denoland/setup-deno@v1 with: - deno-version: v1.33.4 + deno-version: v1.37.0 - name: Setup LCOV run: sudo apt install -y lcov diff --git a/deno.jsonc b/deno.jsonc index 52c94ab..e462ce0 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -1,9 +1,11 @@ { "tasks": { - "fmt": "deno fmt mod.ts src/ --check", + "fmt": "deno fmt mod.ts src/ --options-single-quote --options-line-width=120 --check", + "fmt:fix": "deno fmt mod.ts test/ src/ example/ --options-single-quote --options-line-width=120", "test": "deno test --unstable --allow-read --allow-net --coverage=coverage", "lcov": "deno coverage coverage --lcov --output=coverage/report.lcov", "cover": "deno task clean && deno task test && deno task lcov && genhtml -o coverage/html coverage/report.lcov", - "clean": "rm -rf ./npm ./coverage" + "clean": "rm -rf ./npm ./coverage", + "cache-reload": "deno cache --reload --lock=deno.lock --lock-write mod.ts test/deps.ts" } } diff --git a/deno.lock b/deno.lock index 61edcb4..8fbad30 100644 --- a/deno.lock +++ b/deno.lock @@ -1,9 +1,37 @@ { "version": "2", "remote": { - "https://deno.land/std@0.188.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e", - "https://deno.land/std@0.188.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", - "https://deno.land/std@0.188.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", - "https://deno.land/std@0.188.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f" + "https://deno.land/std@0.203.0/assert/_constants.ts": "8a9da298c26750b28b326b297316cdde860bc237533b07e1337c021379e6b2a9", + "https://deno.land/std@0.203.0/assert/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", + "https://deno.land/std@0.203.0/assert/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", + "https://deno.land/std@0.203.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee", + "https://deno.land/std@0.203.0/assert/assert_almost_equals.ts": "e15ca1f34d0d5e0afae63b3f5d975cbd18335a132e42b0c747d282f62ad2cd6c", + "https://deno.land/std@0.203.0/assert/assert_array_includes.ts": "6856d7f2c3544bc6e62fb4646dfefa3d1df5ff14744d1bca19f0cbaf3b0d66c9", + "https://deno.land/std@0.203.0/assert/assert_equals.ts": "d8ec8a22447fbaf2fc9d7c3ed2e66790fdb74beae3e482855d75782218d68227", + "https://deno.land/std@0.203.0/assert/assert_exists.ts": "407cb6b9fb23a835cd8d5ad804e2e2edbbbf3870e322d53f79e1c7a512e2efd7", + "https://deno.land/std@0.203.0/assert/assert_false.ts": "0ccbcaae910f52c857192ff16ea08bda40fdc79de80846c206bfc061e8c851c6", + "https://deno.land/std@0.203.0/assert/assert_greater.ts": "ae2158a2d19313bf675bf7251d31c6dc52973edb12ac64ac8fc7064152af3e63", + "https://deno.land/std@0.203.0/assert/assert_greater_or_equal.ts": "1439da5ebbe20855446cac50097ac78b9742abe8e9a43e7de1ce1426d556e89c", + "https://deno.land/std@0.203.0/assert/assert_instance_of.ts": "3aedb3d8186e120812d2b3a5dea66a6e42bf8c57a8bd927645770bd21eea554c", + "https://deno.land/std@0.203.0/assert/assert_is_error.ts": "c21113094a51a296ffaf036767d616a78a2ae5f9f7bbd464cd0197476498b94b", + "https://deno.land/std@0.203.0/assert/assert_less.ts": "aec695db57db42ec3e2b62e97e1e93db0063f5a6ec133326cc290ff4b71b47e4", + "https://deno.land/std@0.203.0/assert/assert_less_or_equal.ts": "5fa8b6a3ffa20fd0a05032fe7257bf985d207b85685fdbcd23651b70f928c848", + "https://deno.land/std@0.203.0/assert/assert_match.ts": "c4083f80600bc190309903c95e397a7c9257ff8b5ae5c7ef91e834704e672e9b", + "https://deno.land/std@0.203.0/assert/assert_not_equals.ts": "9f1acab95bd1f5fc9a1b17b8027d894509a745d91bac1718fdab51dc76831754", + "https://deno.land/std@0.203.0/assert/assert_not_instance_of.ts": "0c14d3dfd9ab7a5276ed8ed0b18c703d79a3d106102077ec437bfe7ed912bd22", + "https://deno.land/std@0.203.0/assert/assert_not_match.ts": "3796a5b0c57a1ce6c1c57883dd4286be13a26f715ea662318ab43a8491a13ab0", + "https://deno.land/std@0.203.0/assert/assert_not_strict_equals.ts": "ca6c6d645e95fbc873d25320efeb8c4c6089a9a5e09f92d7c1c4b6e935c2a6ad", + "https://deno.land/std@0.203.0/assert/assert_object_match.ts": "d8fc2867cfd92eeacf9cea621e10336b666de1874a6767b5ec48988838370b54", + "https://deno.land/std@0.203.0/assert/assert_rejects.ts": "45c59724de2701e3b1f67c391d6c71c392363635aad3f68a1b3408f9efca0057", + "https://deno.land/std@0.203.0/assert/assert_strict_equals.ts": "b1f538a7ea5f8348aeca261d4f9ca603127c665e0f2bbfeb91fa272787c87265", + "https://deno.land/std@0.203.0/assert/assert_string_includes.ts": "b821d39ebf5cb0200a348863c86d8c4c4b398e02012ce74ad15666fc4b631b0c", + "https://deno.land/std@0.203.0/assert/assert_throws.ts": "63784e951475cb7bdfd59878cd25a0931e18f6dc32a6077c454b2cd94f4f4bcd", + "https://deno.land/std@0.203.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56", + "https://deno.land/std@0.203.0/assert/equal.ts": "9f1a46d5993966d2596c44e5858eec821859b45f783a5ee2f7a695dfc12d8ece", + "https://deno.land/std@0.203.0/assert/fail.ts": "c36353d7ae6e1f7933d45f8ea51e358c8c4b67d7e7502028598fe1fea062e278", + "https://deno.land/std@0.203.0/assert/mod.ts": "37c49a26aae2b254bbe25723434dc28cd7532e444cf0b481a97c045d110ec085", + "https://deno.land/std@0.203.0/assert/unimplemented.ts": "d56fbeecb1f108331a380f72e3e010a1f161baa6956fd0f7cf3e095ae1a4c75a", + "https://deno.land/std@0.203.0/assert/unreachable.ts": "4600dc0baf7d9c15a7f7d234f00c23bca8f3eba8b140286aaca7aa998cf9a536", + "https://deno.land/std@0.203.0/fmt/colors.ts": "c51c4642678eb690dcf5ffee5918b675bf01a33fba82acf303701ae1a4f8c8d9" } } diff --git a/example/app.ts b/example/app.ts index 45fdcaf..1411853 100644 --- a/example/app.ts +++ b/example/app.ts @@ -1,10 +1,8 @@ -import { Context, Output, Skimming } from "../mod.ts"; +import { Context, Output, Skimming } from '../mod.ts'; function printResult(entries: Output[]) { entries.forEach((output) => { - console.log( - `- File: ${output.file} - Found: ${output.found} - Cache: ${output.cache}`, - ); + console.log(`- File: ${output.file} - Found: ${output.found} - Cache: ${output.cache}`); output.segment.forEach((data, index) => { console.log( `\n- Output #${index} -----------------------------\n${data}`, @@ -14,32 +12,31 @@ function printResult(entries: Output[]) { } async function main() { - const files = ["README.md"]; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: `file:///${Deno.cwd()}/../test/fixtures/`, files, }; const skimmer = new Skimming({ expireDuration: 2, size: 10 }); skimmer.setContext(context); - console.log("##############################################"); - let output = await skimmer.skim("Skimming({", { + console.log('##############################################'); + let output = await skimmer.skim('Skimming({', { previewLength: 100, trimContent: true, }); printResult(output); - console.log("##############################################"); - output = await skimmer.skim("Skimming({", { + console.log('##############################################'); + output = await skimmer.skim('Skimming({', { previewLength: -1, trimContent: true, }); printResult(output); - console.log("##############################################"); - output = await skimmer.skim("#{3}", { previewLength: -1, regex: true }); + console.log('##############################################'); + output = await skimmer.skim('#{3}', { previewLength: -1, regex: true }); printResult(output); } diff --git a/mod.ts b/mod.ts index ffed737..be4c91d 100644 --- a/mod.ts +++ b/mod.ts @@ -1,7 +1,2 @@ -export { Skimming } from "./src/skimming.ts"; -export type { - CacheOptions, - Context, - FetchOptions, - Output, -} from "./src/lib/types.ts"; +export { Skimming } from './src/skimming.ts'; +export type { CacheOptions, Context, FetchOptions, Output } from './src/lib/types.ts'; diff --git a/sonar-project.properties b/sonar-project.properties index 058c31e..9554fae 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.projectKey=petruki_skimming sonar.projectName=skimming sonar.organization=petruki -sonar.projectVersion=1.0.9 +sonar.projectVersion=1.0.10 sonar.javascript.lcov.reportPaths=coverage/report.lcov diff --git a/src/lib/cache.ts b/src/lib/cache.ts index b7cc452..98c4434 100644 --- a/src/lib/cache.ts +++ b/src/lib/cache.ts @@ -1,9 +1,5 @@ -import { Cache, CacheOptions, FetchOptions, Output } from "./types.ts"; -import { - DEFAULT_IGNORE_CASE, - DEFAULT_PREVIEW_LENGTH, - DEFAULT_TRIM, -} from "../skimming.ts"; +import { Cache, CacheOptions, FetchOptions, Output } from './types.ts'; +import { DEFAULT_IGNORE_CASE, DEFAULT_PREVIEW_LENGTH, DEFAULT_TRIM } from '../skimming.ts'; const DEFAULT_CACHE_SIZE = 60; const DEFAULT_CACHE_DURATION = 60; // 1 min @@ -70,9 +66,7 @@ export default class CacheHandler { const cachedData = this.cache.filter((cache) => cache.query === query); if (cachedData.length) { - cachedData[0].output = cachedData[0].output.filter((cachedOutput) => - cachedOutput.file != output.file - ); + cachedData[0].output = cachedData[0].output.filter((cachedOutput) => cachedOutput.file != output.file); cachedData[0].output.push(output); cachedData[0].exp = Date.now() + (1000 * this.cacheExpireDuration); cachedData[0].previewLength = previewLength; @@ -142,12 +136,9 @@ export default class CacheHandler { storedData: Cache, { previewLength, ignoreCase, trimContent }: FetchOptions, ): boolean { - return storedData.previewLength != - (previewLength != undefined ? previewLength : DEFAULT_PREVIEW_LENGTH) || - storedData.ignoreCase != - (ignoreCase != undefined ? ignoreCase : DEFAULT_IGNORE_CASE) || - storedData.trimContent != - (trimContent != undefined ? trimContent : DEFAULT_TRIM); + return storedData.previewLength !== (previewLength ?? DEFAULT_PREVIEW_LENGTH) || + storedData.ignoreCase !== (ignoreCase ?? DEFAULT_IGNORE_CASE) || + storedData.trimContent !== (trimContent ?? DEFAULT_TRIM); } /** @@ -156,8 +147,6 @@ export default class CacheHandler { private updateCache(): void { this.cache = this.cache.filter((storedData) => storedData.exp > Date.now()); - this.cache = this.cache.sort((cachea: Cache, cacheb: Cache) => - cachea.exp > cacheb.exp ? 1 : -1 - ); + this.cache.sort((cachea: Cache, cacheb: Cache) => cachea.exp > cacheb.exp ? 1 : -1); } } diff --git a/src/lib/exceptions.ts b/src/lib/exceptions.ts index 7cf4a83..f3bafe6 100644 --- a/src/lib/exceptions.ts +++ b/src/lib/exceptions.ts @@ -1,4 +1,4 @@ -import { FetchOptions } from "./types.ts"; +import { FetchOptions } from './types.ts'; export class InvalidQuery extends Error { constructor(cause: string) { @@ -26,7 +26,7 @@ export class NonMappedInstruction extends Error { constructor(query: string, options: FetchOptions) { super( - `Request exit to prevent crashing - query: ${query} - options: ${options}`, + `Request exit to prevent crashing - query: ${query} - options: ${String(options)}`, ); this.name = this.constructor.name; } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index c13dfd4..8af016a 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,19 +1,14 @@ -import { Context } from "./types.ts"; -import { InvalidContext, InvalidQuery } from "./exceptions.ts"; -import { - DEFAULT_NEXT, - DEFAULT_PREVIEW_LENGTH, - DEFAULT_REGEX, - DEFAULT_TRIM, -} from "../skimming.ts"; +import { Context } from './types.ts'; +import { InvalidContext, InvalidQuery } from './exceptions.ts'; +import { DEFAULT_NEXT, DEFAULT_PREVIEW_LENGTH, DEFAULT_REGEX, DEFAULT_TRIM } from '../skimming.ts'; -export const LINE_BREAK = "\n"; -export const LAST_LINE = "$"; +export const LINE_BREAK = '\n'; +export const LAST_LINE = '$'; export const REGEX_ESCAPE = /[.*+?^${}()|[\]\\]/g; export function validateQuery(query: string, limit?: number): void { if (!query.length) { - throw new InvalidQuery("it is empty"); + throw new InvalidQuery('it is empty'); } if (limit && query.length > limit) { @@ -24,19 +19,13 @@ export function validateQuery(query: string, limit?: number): void { export function validateContext(context: Context): void { if (!context?.url.length) { throw new InvalidContext( - "context is not defined properly - use setContext() to define the context", + 'context is not defined properly - use setContext() to define the context', ); } context.files.forEach((file) => { if (!file.length) { - throw new InvalidContext("file name is empty"); - } else { - if (!context.url.endsWith("/") && !file.startsWith("/")) { - throw new InvalidContext( - `this enpoint might not work: ${context.url}${file}`, - ); - } + throw new InvalidContext('file name is empty'); } }); } @@ -63,18 +52,16 @@ export function extractSegment( 0, lastPos > 0 ? lastPos + 1 : from.search(LAST_LINE), ); + } else if (trimContent) { + offset = from.trimStart().substring( + 0, + from.trimStart().indexOf(LINE_BREAK) + previewLength, + ); } else { - if (trimContent) { - offset = from.trimStart().substring( - 0, - from.trimStart().indexOf(LINE_BREAK) + previewLength, - ); - } else { - offset = from.trimStart().substring( - 0, - previewLength === 0 ? query.length : previewLength, - ); - } + offset = from.trimStart().substring( + 0, + previewLength === 0 ? query.length : previewLength, + ); } // Find the last line position in a multiline content @@ -104,14 +91,12 @@ export function findFirstPos( regex: boolean = DEFAULT_REGEX, next: boolean = DEFAULT_NEXT, ): number { - const foundIndex = regex - ? contentToFetch.search(query) - : contentToFetch.search(query.replace(REGEX_ESCAPE, "\\$&")); + const foundIndex = regex ? contentToFetch.search(query) : contentToFetch.search(query.replace(REGEX_ESCAPE, '\\$&')); if (trimContent && foundIndex != -1) { let firstPos = next ? foundIndex : 0; for (let index = foundIndex; index >= 0; index--) { - if (contentToFetch.charAt(index) == "\n") { + if (contentToFetch.charAt(index) == '\n') { firstPos = index; break; } diff --git a/src/skimming.ts b/src/skimming.ts index 0e9f609..1a54164 100644 --- a/src/skimming.ts +++ b/src/skimming.ts @@ -1,16 +1,7 @@ -import { CacheOptions, Context, FetchOptions, Output } from "./lib/types.ts"; -import { - extractSegment, - findFirstPos, - validateContext, - validateQuery, -} from "./lib/utils.ts"; -import { - InvalidQuery, - NonMappedInstruction, - NotContentFound, -} from "./lib/exceptions.ts"; -import CacheHandler from "./lib/cache.ts"; +import { CacheOptions, Context, FetchOptions, Output } from './lib/types.ts'; +import { extractSegment, findFirstPos, validateContext, validateQuery } from './lib/utils.ts'; +import { InvalidQuery, NonMappedInstruction, NotContentFound } from './lib/exceptions.ts'; +import CacheHandler from './lib/cache.ts'; export const DEFAULT_PREVIEW_LENGTH = 200; export const DEFAULT_TRIM = true; @@ -125,7 +116,7 @@ export class Skimming { const from = content.substring(foundIndex); const segment = extractSegment(from, query, previewLength, trimContent); segments.push(segment); - content = content.replace(segment, ""); + content = content.replace(segment, ''); contentToFetch = ignoreCase ? content.toLowerCase() : content; foundIndex = findFirstPos( contentToFetch, @@ -153,7 +144,7 @@ export class Skimming { * Fetch document online located at the provided url */ private async readDocument(url: string, doc: string): Promise { - const result = await fetch(`${url}${doc}`); + const result = await fetch(`${url}/${doc}`); if (result?.body != null) { if (result.status === 200) { return await result.text().then((data: string) => { diff --git a/test/cache_test.ts b/test/cache_test.ts index c5eb6f6..927c623 100644 --- a/test/cache_test.ts +++ b/test/cache_test.ts @@ -1,6 +1,6 @@ -import { assertEquals } from "./deps.ts"; -import CacheHandler from "../src/lib/cache.ts"; -import { DEFAULT_IGNORE_CASE, DEFAULT_PREVIEW_LENGTH } from "../src/skimming.ts"; +import { assertEquals } from './deps.ts'; +import CacheHandler from '../src/lib/cache.ts'; +import { DEFAULT_IGNORE_CASE, DEFAULT_PREVIEW_LENGTH } from '../src/skimming.ts'; const { test } = Deno; @@ -9,17 +9,17 @@ function sleep(ms: number) { } test({ - name: "CACHE - Should store data into cache", + name: 'CACHE - Should store data into cache', fn(): void { // given const cacheHandler = new CacheHandler({ size: 1, expireDuration: 10 }); - + // test cacheHandler.store( - "my search", + 'my search', { - file: "filename.md", - segment: ["my search begins somewhere here"], + file: 'filename.md', + segment: ['my search begins somewhere here'], found: 1, cache: true, }, @@ -29,17 +29,17 @@ test({ }); test({ - name: "CACHE - Should limit cache size by 2", + name: 'CACHE - Should limit cache size by 2', async fn(): Promise { // given const cacheHandler = new CacheHandler({ size: 2, expireDuration: 10 }); // test cacheHandler.store( - "my search", + 'my search', { - file: "filename.md", - segment: ["my search begins somewhere here"], + file: 'filename.md', + segment: ['my search begins somewhere here'], found: 1, cache: true, }, @@ -47,10 +47,10 @@ test({ await sleep(500); cacheHandler.store( - "another search", + 'another search', { - file: "filename2.md", - segment: ["another search begins somewhere here"], + file: 'filename2.md', + segment: ['another search begins somewhere here'], found: 1, cache: true, }, @@ -59,10 +59,10 @@ test({ await sleep(500); cacheHandler.store( - "Is there any space", + 'Is there any space', { - file: "filename3.md", - segment: ["Is there any space to store me?"], + file: 'filename3.md', + segment: ['Is there any space to store me?'], found: 1, cache: true, }, @@ -72,17 +72,17 @@ test({ }); test({ - name: "CACHE - Should update exp time after accessing cached query", + name: 'CACHE - Should update exp time after accessing cached query', async fn(): Promise { // given const cacheHandler = new CacheHandler({ size: 2, expireDuration: 10 }); // test cacheHandler.store( - "my search", + 'my search', { - file: "filename.md", - segment: ["my search begins somewhere here"], + file: 'filename.md', + segment: ['my search begins somewhere here'], found: 1, cache: true, }, @@ -90,10 +90,10 @@ test({ await sleep(500); cacheHandler.store( - "another search", + 'another search', { - file: "filename2.md", - segment: ["another search begins somewhere here"], + file: 'filename2.md', + segment: ['another search begins somewhere here'], found: 1, cache: true, }, @@ -101,150 +101,149 @@ test({ assertEquals(cacheHandler.cache[0].exp < cacheHandler.cache[1].exp, true); - cacheHandler.fetch("my search"); + cacheHandler.fetch('my search'); assertEquals(cacheHandler.cache[0].exp < cacheHandler.cache[1].exp, false); }, }); test({ - name: "CACHE - Should fetch from cache when ignore case enabled", + name: 'CACHE - Should fetch from cache when ignore case enabled', fn(): void { // given const cacheHandler = new CacheHandler({ size: 2, expireDuration: 10 }); cacheHandler.store( - "My Search", + 'My Search', { - file: "filename.md", - segment: ["My Search begins somewhere here"], + file: 'filename.md', + segment: ['My Search begins somewhere here'], found: 1, cache: true, }, ); // test - const output = cacheHandler.fetch("my search", { ignoreCase: true }); + const output = cacheHandler.fetch('my search', { ignoreCase: true }); assertEquals(output.length, 1); - assertEquals(cacheHandler.cache[0].query, "my search"); + assertEquals(cacheHandler.cache[0].query, 'my search'); }, }); test({ - name: "CACHE - Should fetch from source once FetchOptions (previewLength) has changed", + name: 'CACHE - Should fetch from source once FetchOptions (previewLength) has changed', fn(): void { // given const cacheHandler = new CacheHandler({ size: 2, expireDuration: 10 }); const previewLength = 10; cacheHandler.store( - "My Search", + 'My Search', { - file: "filename.md", - segment: ["My Search begins somewhere here"], + file: 'filename.md', + segment: ['My Search begins somewhere here'], found: 1, cache: true, }, - previewLength + previewLength, ); // test - const output = cacheHandler.fetch("My Search", { previewLength: 5 }); + const output = cacheHandler.fetch('My Search', { previewLength: 5 }); assertEquals(output.length, 0); }, }); test({ - name: "CACHE - Should fetch from source once FetchOptions (trimContent) has changed", + name: 'CACHE - Should fetch from source once FetchOptions (trimContent) has changed', fn(): void { // given const cacheHandler = new CacheHandler({ size: 2, expireDuration: 10 }); const trimContent = true; cacheHandler.store( - "My Search", + 'My Search', { - file: "filename.md", - segment: ["My Search begins somewhere here"], + file: 'filename.md', + segment: ['My Search begins somewhere here'], found: 1, cache: true, }, DEFAULT_PREVIEW_LENGTH, DEFAULT_IGNORE_CASE, - trimContent + trimContent, ); // test - const output = cacheHandler.fetch("My Search", { trimContent: false }); + const output = cacheHandler.fetch('My Search', { trimContent: false }); assertEquals(output.length, 0); }, }); test({ - name: - "CACHE - Should reorder after one element has been accessed and then another query has been added", + name: 'CACHE - Should reorder after one element has been accessed and then another query has been added', async fn(): Promise { // given const cacheHandler = new CacheHandler({ size: 3, expireDuration: 10 }); // test cacheHandler.store( - "my search", + 'my search', { - file: "filename.md", - segment: ["my search begins somewhere here"], + file: 'filename.md', + segment: ['my search begins somewhere here'], found: 1, cache: true, }, ); await sleep(500); cacheHandler.store( - "another search", + 'another search', { - file: "filename2.md", - segment: ["another search begins somewhere here"], + file: 'filename2.md', + segment: ['another search begins somewhere here'], found: 1, cache: true, }, ); - assertEquals(cacheHandler.cache[0].query, "my search"); - assertEquals(cacheHandler.cache[1].query, "another search"); + assertEquals(cacheHandler.cache[0].query, 'my search'); + assertEquals(cacheHandler.cache[1].query, 'another search'); - cacheHandler.fetch("my search"); + cacheHandler.fetch('my search'); // It remains the same order because fetch does not reorder - assertEquals(cacheHandler.cache[0].query, "my search"); - assertEquals(cacheHandler.cache[1].query, "another search"); + assertEquals(cacheHandler.cache[0].query, 'my search'); + assertEquals(cacheHandler.cache[1].query, 'another search'); await sleep(500); cacheHandler.store( - "Is there any space", + 'Is there any space', { - file: "filename3.md", - segment: ["Is there any space to store me?"], + file: 'filename3.md', + segment: ['Is there any space to store me?'], found: 1, cache: true, }, ); - assertEquals(cacheHandler.cache[0].query, "another search"); - assertEquals(cacheHandler.cache[1].query, "my search"); - assertEquals(cacheHandler.cache[2].query, "Is there any space"); + assertEquals(cacheHandler.cache[0].query, 'another search'); + assertEquals(cacheHandler.cache[1].query, 'my search'); + assertEquals(cacheHandler.cache[2].query, 'Is there any space'); }, }); test({ - name: "CACHE - Should remove expired data from the cache", + name: 'CACHE - Should remove expired data from the cache', async fn(): Promise { // given const cacheHandler = new CacheHandler({ size: 10, expireDuration: 1 }); // test cacheHandler.store( - "my search", + 'my search', { - file: "filename.md", - segment: ["my search begins somewhere here"], + file: 'filename.md', + segment: ['my search begins somewhere here'], found: 1, cache: true, }, @@ -252,28 +251,28 @@ test({ await sleep(1000); cacheHandler.store( - "another search", + 'another search', { - file: "filename2.md", - segment: ["another search begins somewhere here"], + file: 'filename2.md', + segment: ['another search begins somewhere here'], found: 1, cache: true, }, ); - + await sleep(500); cacheHandler.store( - "Is there any space", + 'Is there any space', { - file: "filename3.md", - segment: ["Is there any space to store me?"], + file: 'filename3.md', + segment: ['Is there any space to store me?'], found: 1, cache: true, }, ); - assertEquals(cacheHandler.cache[0].query, "another search"); - assertEquals(cacheHandler.cache[1].query, "Is there any space"); + assertEquals(cacheHandler.cache[0].query, 'another search'); + assertEquals(cacheHandler.cache[1].query, 'Is there any space'); assertEquals(cacheHandler.cache.length, 2); }, }); diff --git a/test/deps.ts b/test/deps.ts index 2c5275a..bdf7016 100644 --- a/test/deps.ts +++ b/test/deps.ts @@ -1,5 +1 @@ -export { - assertEquals, - assertNotEquals, - assertThrows, - } from "https://deno.land/std@0.188.0/testing/asserts.ts"; \ No newline at end of file +export { assertEquals, assertNotEquals, assertThrows } from 'https://deno.land/std@0.203.0/assert/mod.ts'; diff --git a/test/fixtures/README.md b/test/fixtures/README.md index 6fb8605..f3c3ba6 100644 --- a/test/fixtures/README.md +++ b/test/fixtures/README.md @@ -3,8 +3,7 @@ # `skimming` -Skimming is a data fetcher for Deno. The idea is to provide a simple and -efficient module to fetch content. +Skimming is a data fetcher for Deno. The idea is to provide a simple and efficient module to fetch content. - Fetch documents online `skim()` or local `skimContent()` - Customizable cache @@ -28,8 +27,7 @@ skimmer.setContext(context); const results = await skimmer.skim(query, { previewLength: 200 }); ``` -- Where `previewLength` is the number of characters after the found occurrence - which will be displayed (default: 200) +- Where `previewLength` is the number of characters after the found occurrence which will be displayed (default: 200) - Add `ignoreCase` option for whether ignore case or not (default: false) ### Using cache @@ -45,10 +43,8 @@ skimmer.setContext(context); const results = await skimmer.skim(query, { previewLength: 200 }); ``` -- Where `expireDuration` the time in seconds that the cached value will expire - (default: 1min) -- Where `size` is the number of stored queries and its results in cache - (default: 60) +- Where `expireDuration` the time in seconds that the cached value will expire (default: 1min) +- Where `size` is the number of stored queries and its results in cache (default: 60) ### Testing diff --git a/test/mod_test.ts b/test/mod_test.ts index ed6567c..2c528d8 100644 --- a/test/mod_test.ts +++ b/test/mod_test.ts @@ -1,10 +1,6 @@ -import { - assertEquals, - assertNotEquals, - assertThrows, -} from "./deps.ts"; -import { Context, Skimming } from "../mod.ts"; -import { InvalidContext } from "../src/lib/exceptions.ts"; +import { assertEquals, assertNotEquals, assertThrows } from './deps.ts'; +import { Context, Skimming } from '../mod.ts'; +import { InvalidContext } from '../src/lib/exceptions.ts'; const { test } = Deno; @@ -19,14 +15,13 @@ const content = ` It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.`; test({ - name: "MOD - Should return one valid entry", + name: 'MOD - Should return one valid entry', async fn(): Promise { // given - const query = "Skimming"; - const files = ["README.md"]; + const query = 'Skimming'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -40,14 +35,13 @@ test({ }); test({ - name: "MOD - Should NOT return - Exception: document not found", + name: 'MOD - Should NOT return - Exception: document not found', async fn(): Promise { // given - const query = "query"; - const files = ["NOT_EXIST.md"]; + const query = 'query'; + const files = ['NOT_EXIST.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -56,7 +50,7 @@ test({ // test await skimmer.skim(query).catch((error) => { - assertEquals(error.name, "NotContentFound"); + assertEquals(error.name, 'NotContentFound'); assertEquals( error.message, `No content found at https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/${files[0]}.`, @@ -66,14 +60,13 @@ test({ }); test({ - name: "MOD - Should NOT return - Exception: empty query", + name: 'MOD - Should NOT return - Exception: empty query', fn(): void { // given - const query = ""; - const files = ["README.md"]; + const query = ''; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -82,20 +75,20 @@ test({ // test skimmer.skim(query).catch((error) => { - assertEquals(error.name, "InvalidQuery"); + assertEquals(error.name, 'InvalidQuery'); assertEquals( error.message, - `Invalid query input. Cause: ${"it is empty"}.`, + `Invalid query input. Cause: ${'it is empty'}.`, ); }); }, }); test({ - name: "MOD - Should return content found not trimmed", + name: 'MOD - Should return content found not trimmed', fn(): void { // given - const query = "Lorem"; + const query = 'Lorem'; const skimmer = new Skimming(); // test @@ -108,10 +101,10 @@ test({ }); test({ - name: "MOD - Should return content found trimmed", + name: 'MOD - Should return content found trimmed', fn(): void { // given - const query = "Lorem"; + const query = 'Lorem'; const skimmer = new Skimming(); // test @@ -121,10 +114,10 @@ test({ }); test({ - name: "MOD - Should return two results - not ignore case", + name: 'MOD - Should return two results - not ignore case', fn(): void { // given - const query = "Lorem"; + const query = 'Lorem'; const skimmer = new Skimming(); // test @@ -134,10 +127,10 @@ test({ }); test({ - name: "MOD - Should return three results - ignore case", + name: 'MOD - Should return three results - ignore case', fn(): void { // given - const query = "Lorem"; + const query = 'Lorem'; const skimmer = new Skimming(); // test @@ -150,12 +143,12 @@ test({ }); test({ - name: "MOD - Should NOT return - Exception: url is empty", + name: 'MOD - Should NOT return - Exception: url is empty', fn(): void { // given - const files = ["README.md"]; + const files = ['README.md']; const context: Context = { - url: "", + url: '', files, }; @@ -165,19 +158,18 @@ test({ assertThrows( () => skimmer.setContext(context), InvalidContext, - `Invalid context. Cause: ${"context is not defined properly - use setContext() to define the context"}.`, + `Invalid context. Cause: ${'context is not defined properly - use setContext() to define the context'}.`, ); }, }); test({ - name: "MOD - Should NOT return - Exception: file name is empty", + name: 'MOD - Should NOT return - Exception: file name is empty', fn(): void { // given - const files = [""]; + const files = ['']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -187,41 +179,19 @@ test({ assertThrows( () => skimmer.setContext(context), InvalidContext, - `Invalid context. Cause: ${"file name is empty"}.`, + `Invalid context. Cause: ${'file name is empty'}.`, ); }, }); test({ - name: "MOD - Should NOT return - Exception: endpoint might not work", - fn(): void { - // given - const files = ["README.md"]; - const context: Context = { - url: "https://raw.githubusercontent.com/petruki/skimming/master", // Here, it is missing a slash in the end - files, - }; - - const skimmer = new Skimming(); - - // test - assertThrows( - () => skimmer.setContext(context), - InvalidContext, - `Invalid context. Cause: this enpoint might not work: ${context.url}${"README.md"}.`, - ); - }, -}); - -test({ - name: "MOD - Should return value from the cache", + name: 'MOD - Should return value from the cache', async fn(): Promise { // given - const query = "Skimming"; - const files = ["README.md"]; + const query = 'Skimming'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -244,14 +214,13 @@ test({ }); test({ - name: "MOD - Should return value from the cache with new preview length", + name: 'MOD - Should return value from the cache with new preview length', async fn(): Promise { // given - const query = "Skimming({"; - const files = ["README.md"]; + const query = 'Skimming({'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -278,15 +247,14 @@ test({ }); test({ - name: "MOD - Should return value from the cache with ignore case", + name: 'MOD - Should return value from the cache with ignore case', async fn(): Promise { // given - const query1 = "Skimming"; - const query2 = "skimming"; - const files = ["README.md"]; + const query1 = 'Skimming'; + const query2 = 'skimming'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -305,7 +273,7 @@ test({ output = await skimmer.skim(query2, { previewLength: 20, trimContent: false, - ignoreCase: true + ignoreCase: true, }); assertEquals(output.length, 1); @@ -314,15 +282,13 @@ test({ }); test({ - name: - "MOD - Should return value from the source with new preview length", + name: 'MOD - Should return value from the source with new preview length', async fn(): Promise { // given - const query = "Skimming({"; - const files = ["README.md"]; + const query = 'Skimming({'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -356,14 +322,13 @@ test({ }); test({ - name: "MOD - Should return value using regular expression", + name: 'MOD - Should return value using regular expression', async fn(): Promise { // given - const query = "#{3}"; - const files = ["README.md"]; + const query = '#{3}'; + const files = ['README.md']; const context: Context = { - url: - "https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/", + url: 'https://raw.githubusercontent.com/petruki/skimming/master/test/fixtures/', files, }; @@ -377,8 +342,8 @@ test({ }); assertEquals(output.length, 1); - assertEquals(output[0].segment[0], "### No cache"); - assertEquals(output[0].segment[1], "### Using cache"); - assertEquals(output[0].segment[2], "### Testing"); + assertEquals(output[0].segment[0], '### No cache'); + assertEquals(output[0].segment[1], '### Using cache'); + assertEquals(output[0].segment[2], '### Testing'); }, }); diff --git a/test/utils_test.ts b/test/utils_test.ts index b56f235..7e0b9c0 100644 --- a/test/utils_test.ts +++ b/test/utils_test.ts @@ -1,39 +1,41 @@ -import { assertEquals, assertThrows } from "./deps.ts"; -import { extractSegment, validateQuery } from "../src/lib/utils.ts"; -import { InvalidQuery } from "../src/lib/exceptions.ts"; +import { assertEquals, assertThrows } from './deps.ts'; +import { extractSegment, validateQuery } from '../src/lib/utils.ts'; +import { InvalidQuery } from '../src/lib/exceptions.ts'; const { test } = Deno; -const content = "What is Lorem Ipsum?"; +const content = 'What is Lorem Ipsum?'; test({ - name: "UTILS - Should return error when limit exceeded", + name: 'UTILS - Should return error when limit exceeded', fn(): void { - assertThrows(() => validateQuery("query", 3), - InvalidQuery, "Invalid query input. Cause: it exceeds the limit of 3."); + assertThrows( + () => validateQuery('query', 3), + InvalidQuery, + 'Invalid query input. Cause: it exceeds the limit of 3.', + ); }, }); test({ - name: "UTILS - Should return error when query is empty", + name: 'UTILS - Should return error when query is empty', fn(): void { - assertThrows(() => validateQuery(""), - InvalidQuery, "Invalid query input. Cause: it is empty."); + assertThrows(() => validateQuery(''), InvalidQuery, 'Invalid query input. Cause: it is empty.'); }, }); test({ - name: "UTILS - Should extract segment full line", + name: 'UTILS - Should extract segment full line', fn(): void { - const segment = extractSegment(content, "What", -1); - assertEquals(segment, "What is Lorem Ipsum?") + const segment = extractSegment(content, 'What', -1); + assertEquals(segment, 'What is Lorem Ipsum?'); }, }); test({ - name: "UTILS - Should extract segment from query lenght", + name: 'UTILS - Should extract segment from query lenght', fn(): void { - const segment = extractSegment(content, "What", 0, false); - assertEquals(segment, "What") + const segment = extractSegment(content, 'What', 0, false); + assertEquals(segment, 'What'); }, -}); \ No newline at end of file +});