Skip to content

Commit 2d655c1

Browse files
committed
refactor(browser): HawkStorage abstraction added
1 parent 607adfe commit 2d655c1

12 files changed

Lines changed: 263 additions & 7 deletions

File tree

.github/workflows/main.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ jobs:
2222
CI_JOB_NUMBER: 2
2323
steps:
2424
- uses: actions/checkout@v1
25+
with:
26+
fetch-depth: 0
2527
- name: Use Node.js from .nvmrc
2628
uses: actions/setup-node@v6
2729
with:
2830
node-version-file: '.nvmrc'
2931
- run: corepack enable
3032
- run: yarn install
31-
- run: yarn workspace @hawk.so/javascript test
33+
- run: yarn test:modified origin/${{ github.event.pull_request.base.ref }}
3234

3335
build:
3436
runs-on: ubuntu-latest

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"dev": "yarn workspace @hawk.so/javascript dev",
1616
"build:all": "yarn workspaces foreach -Apt run build",
1717
"build:modified": "yarn workspaces foreach --since=\"$@\" -Rpt run build",
18+
"test:all": "yarn workspaces foreach -Apt run test",
19+
"test:modified": "yarn workspaces foreach --since=\"$@\" -Rpt run test",
1820
"stats": "yarn workspace @hawk.so/javascript stats",
1921
"lint": "eslint -c ./.eslintrc.cjs packages/*/src --ext .ts,.js --fix",
2022
"lint-test": "eslint -c ./.eslintrc.cjs packages/*/src --ext .ts,.js"

packages/browser/package.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
}
1818
},
1919
"scripts": {
20-
"build": "vite build"
20+
"build": "vite build",
21+
"test": "vitest run",
22+
"test:coverage": "vitest run --coverage",
23+
"lint": "eslint --fix \"src/**/*.{js,ts}\""
2124
},
2225
"repository": {
2326
"type": "git",
@@ -33,8 +36,14 @@
3336
"url": "https://github.com/codex-team/hawk.javascript/issues"
3437
},
3538
"homepage": "https://github.com/codex-team/hawk.javascript#readme",
39+
"dependencies": {
40+
"@hawk.so/core": "workspace:^"
41+
},
3642
"devDependencies": {
43+
"@vitest/coverage-v8": "^4.0.18",
44+
"jsdom": "^28.0.0",
3745
"vite": "^7.3.1",
38-
"vite-plugin-dts": "^4.2.4"
46+
"vite-plugin-dts": "^4.2.4",
47+
"vitest": "^4.0.18"
3948
}
4049
}

packages/browser/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { HawkLocalStorage } from './storages/hawk-local-storage';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { HawkStorage } from '@hawk.so/core';
2+
3+
/**
4+
* {@link HawkStorage} implementation backed by the browser's {@linkcode localStorage}.
5+
*/
6+
export class HawkLocalStorage implements HawkStorage {
7+
/** @inheritDoc */
8+
public getItem(key: string): string | null {
9+
return localStorage.getItem(key);
10+
}
11+
12+
/** @inheritDoc */
13+
public setItem(key: string, value: string): void {
14+
localStorage.setItem(key, value);
15+
}
16+
17+
/** @inheritDoc */
18+
public removeItem(key: string): void {
19+
localStorage.removeItem(key);
20+
}
21+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { beforeEach, afterEach, describe, it, expect, vi, Mock } from "vitest";
2+
import { HawkLocalStorage } from "../src";
3+
4+
describe('HawkLocalStorage', () => {
5+
let getItemSpy: Mock<(key: string) => string | null>;
6+
let setItemSpy: Mock<(key: string, value: string) => void>;
7+
let removeItemSpy: Mock<(key: string) => void>;
8+
let storage: HawkLocalStorage;
9+
10+
beforeEach(() => {
11+
localStorage.clear();
12+
storage = new HawkLocalStorage();
13+
getItemSpy = vi.spyOn(Storage.prototype, 'getItem');
14+
setItemSpy = vi.spyOn(Storage.prototype, 'setItem');
15+
removeItemSpy = vi.spyOn(Storage.prototype, 'removeItem');
16+
});
17+
18+
afterEach(() => {
19+
vi.restoreAllMocks();
20+
});
21+
22+
it('should return null when key does not exist', () => {
23+
expect(storage.getItem('foo')).toBeNull();
24+
expect(getItemSpy).toHaveBeenCalledOnce();
25+
});
26+
27+
it('should return value when key exists in storage', () => {
28+
localStorage.setItem('foo', 'bar');
29+
30+
expect(storage.getItem('foo')).toEqual('bar');
31+
expect(getItemSpy).toHaveBeenCalledWith('foo');
32+
});
33+
34+
it('should persist item via setItem()', () => {
35+
storage.setItem('foo', 'bar');
36+
37+
expect(setItemSpy).toHaveBeenCalledWith('foo', 'bar');
38+
expect(localStorage.getItem('foo')).toEqual('bar');
39+
});
40+
41+
it('should remove item via removeItem()', () => {
42+
localStorage.setItem('foo', 'bar');
43+
storage.removeItem('foo');
44+
45+
expect(removeItemSpy).toHaveBeenCalledWith('foo');
46+
expect(localStorage.getItem('foo')).toBeNull();
47+
});
48+
49+
it('should not affect other keys when removing', () => {
50+
localStorage.setItem('foo', 'bar');
51+
storage.removeItem('baz');
52+
53+
expect(removeItemSpy).toHaveBeenCalledWith('baz');
54+
expect(localStorage.getItem('foo')).toEqual('bar');
55+
});
56+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": null,
5+
"declaration": false,
6+
"types": ["vitest/globals"]
7+
},
8+
"include": [
9+
"src/**/*",
10+
"tests/**/*",
11+
"vitest.config.ts"
12+
]
13+
}

packages/browser/vitest.config.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineConfig } from 'vitest/config';
2+
3+
export default defineConfig({
4+
test: {
5+
globals: true,
6+
environment: 'jsdom',
7+
include: ['tests/**/*.test.ts'],
8+
typecheck: {
9+
tsconfig: './tsconfig.test.json',
10+
},
11+
coverage: {
12+
provider: 'v8',
13+
include: ['src/**/*.ts'],
14+
},
15+
},
16+
});

packages/core/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
}
1818
},
1919
"scripts": {
20-
"build": "vite build"
20+
"build": "vite build",
21+
"lint": "eslint --fix \"src/**/*.{js,ts}\""
2122
},
2223
"repository": {
2324
"type": "git",

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type { HawkStorage } from './storages/hawk-storage';

0 commit comments

Comments
 (0)