Skip to content

Commit

Permalink
init browser state (#5552)
Browse files Browse the repository at this point in the history
* init browser state

* get tab index

* rm
  • Loading branch information
skylarbarrera authored Mar 25, 2024
1 parent c0f41c7 commit d6e35e4
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
95 changes: 95 additions & 0 deletions src/state/browserState/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useBrowserStateStore } from '.';

describe('BrowserStateStore', () => {
beforeEach(() => {
// Reset the store to its initial state before each test
useBrowserStateStore.setState(
{
tabs: [],
},
true
); // The second argument 'true' is to replace the state instead of merging
});

test('should be able to add a tab', () => {
const { addTab, tabs } = useBrowserStateStore.getState();
expect(tabs.length).toBe(0);
addTab({
name: 'Test Tab',
isActive: true,
screenshot: 'test_screenshot.png',
history: [
{
name: 'Test Site',
url: 'https://test.com',
image: 'test_image.png',
timestamp: Date.now(),
},
],
});
expect(useBrowserStateStore.getState().tabs.length).toBe(1);
});

test('should place new tabs at the end', () => {
const { addTab } = useBrowserStateStore.getState();
addTab({ name: 'First Tab', screenshot: '', history: [], isActive: false });
addTab({ name: 'Second Tab', screenshot: '', history: [], isActive: false });
const tabs = useBrowserStateStore.getState().tabs;
expect(tabs[tabs.length - 1].name).toBe('Second Tab');
});

test('should be able to delete a tab', () => {
const { addTab, deleteTab, tabs } = useBrowserStateStore.getState();
addTab({ name: 'Tab to Delete', screenshot: '', history: [], isActive: false });
expect(tabs.length).toBe(1);
deleteTab(0);
expect(useBrowserStateStore.getState().tabs.length).toBe(0);
});

test('should handle deleting the active tab', () => {
const { addTab, deleteTab, setActiveTab, getActiveTab } = useBrowserStateStore.getState();
addTab({ name: 'Active Tab', screenshot: '', history: [], isActive: false });
addTab({ name: 'Next Tab', screenshot: '', history: [], isActive: false });
setActiveTab(0);
expect(getActiveTab()?.name).toBe('Active Tab');
deleteTab(0);
expect(getActiveTab()?.name).toBe('Next Tab');
});

test('should be able to edit a tab', () => {
const { addTab, editTab, tabs } = useBrowserStateStore.getState();
addTab({ name: 'Tab to Edit', screenshot: '', history: [], isActive: false });
editTab(0, { name: 'Edited Tab' });
expect(tabs[0].name).toBe('Edited Tab');
});

test('editing a non-existent tab should do nothing', () => {
const { editTab, tabs } = useBrowserStateStore.getState();
editTab(999, { name: 'Ghost Tab' }); // Assuming there's no tab at index 999
expect(tabs.length).toBe(0); // No tabs should have been added or modified
});

test('should be able to set and get the active tab', () => {
const { addTab, setActiveTab, getActiveTab } = useBrowserStateStore.getState();
addTab({ name: 'First Tab', screenshot: '', history: [], isActive: false });
addTab({ name: 'Second Tab', screenshot: '', history: [], isActive: false });
setActiveTab(1);
expect(getActiveTab()?.name).toBe('Second Tab');
});

test('setting an active tab should deactivate others', () => {
const { addTab, setActiveTab, tabs } = useBrowserStateStore.getState();
addTab({ name: 'First Tab', screenshot: '', history: [], isActive: true });
addTab({ name: 'Second Tab', screenshot: '', history: [], isActive: false });
setActiveTab(1);
expect(tabs[0].isActive).toBe(false);
expect(tabs[1].isActive).toBe(true);
});

test('deleting the only tab should result in no active tabs', () => {
const { addTab, deleteTab, tabs } = useBrowserStateStore.getState();
addTab({ name: 'Lonely Tab', screenshot: '', history: [], isActive: true });
deleteTab(0);
expect(tabs.find(tab => tab.isActive)).toBe(undefined);
});
});
67 changes: 67 additions & 0 deletions src/state/browserState/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import create from 'zustand';

export interface Site {
name: string;
url: string;
image: string;
timestamp: number; // Assuming timestamp is a Unix timestamp for simplicity
}

export interface Tab {
history: Site[];
name: string;
screenshot: string; // Assuming this is a URL or base64 encoded image
isActive: boolean;
}

interface BrowserState {
tabs: Tab[];
addTab: (tab: Tab) => void;
deleteTab: (tabIndex: number) => void;
editTab: (tabIndex: number, newTabData: Partial<Tab>) => void;
setActiveTab: (tabIndex: number) => void;
getActiveTab: () => Tab | undefined;
getActiveTabIndex: () => number;
}

export const useBrowserStateStore = create<BrowserState>((set, get) => ({
tabs: [], // Initial state of tabs is an empty array for now

addTab: tab =>
set(state => ({
tabs: [...state.tabs, { ...tab, isActive: false }],
})),

deleteTab: tabIndex =>
set(state => {
const newTabs = state.tabs.filter((_, index) => index !== tabIndex);
// If the deleted tab was active, set the next tab as active, or the previous one if it was the last tab
if (state.tabs[tabIndex].isActive) {
if (newTabs.length > 0) {
if (tabIndex === 0 || tabIndex < newTabs.length) {
newTabs[tabIndex].isActive = true;
} else {
newTabs[tabIndex - 1].isActive = true;
}
}
}
return { tabs: newTabs };
}),

editTab: (tabIndex, newTabData) => {
set(state => ({
tabs: state.tabs.map((tab, index) => (index === tabIndex ? { ...tab, ...newTabData, timestamp: Date.now() } : tab)),
}));
},

setActiveTab: tabIndex =>
set(state => ({
tabs: state.tabs.map((tab, index) => ({
...tab,
isActive: index === tabIndex,
})),
})),

getActiveTab: () => get().tabs.find(tab => tab.isActive),
getActiveTabIndex: () => get().tabs.findIndex(tab => tab.isActive),
}));

0 comments on commit d6e35e4

Please sign in to comment.