Skip to content

Commit

Permalink
refactor: remove react functionality from dictionary store
Browse files Browse the repository at this point in the history
  • Loading branch information
Rue-pro committed Apr 8, 2024
1 parent a03b221 commit a5f5bc6
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 60 deletions.
53 changes: 27 additions & 26 deletions src/entities/dictionary/model/__tests__/store.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { allTasks, cleanStores, keepMount } from 'nanostores'
import { afterEach, describe, expect, test, vi } from 'vitest'

import { $errors } from '@entities/error/model/store'

import { chromeMockClearListeners } from '@shared/browser/__mocks__/chrome'
import { Result } from '@shared/libs/operationResult'
import { getErrorToastMock } from '@shared/ui/Toast/helpers/__mock__/getErrorToast'
import { addToastMock } from '@shared/ui/Toast/model/__mock__/store'

import { waitFor } from '@tests/testUtils'

import { DICTIONARIES } from '../dictionaries'
import { DICTIONARIES } from '..'
import { $dictionaries, DictionaryStorage, selectVariant } from '../store'
import { TDictionaries } from '../types'

Expand All @@ -21,6 +22,8 @@ describe('dictionary store', () => {
await chrome.storage.local.clear()
cleanStores($dictionaries)
$dictionaries.set(DICTIONARIES)
$errors.set([])
chromeMockClearListeners()
vi.clearAllMocks()
})

Expand All @@ -36,10 +39,10 @@ describe('dictionary store', () => {
await allTasks()

expect($dictionaries.get()).toEqual(newDictionaries)
expect(getErrorToastMock).toBeCalledTimes(0)
expect($errors.get().length).toEqual(0)
})

test('should set empty array and show toast with error when DictionaryStorage returns error', async () => {
test('should set empty array and set error when can not get data from DictionaryStorage', async () => {
vi.spyOn(DictionaryStorage, 'get').mockResolvedValueOnce(
Result.Error(error),
)
Expand All @@ -48,54 +51,55 @@ describe('dictionary store', () => {
await allTasks()

expect($dictionaries.get()).toEqual(DICTIONARIES)
expect(getErrorToastMock).toBeCalledWith(error)
expect($errors.get().length).toEqual(1)
})
})

describe('selectVariant', () => {
const dictionaryId = 'en_CambridgeDictionary'

test('should set selected variants to DictionaryStorage and show operation success information', async () => {
test('should set selected variants to DictionaryStorage and return operation success information', async () => {
keepMount($dictionaries)
await allTasks()

await waitFor(async () => {
await selectVariant('en', dictionaryId, 'us')
const result = await selectVariant('en', dictionaryId, 'us')

const call = addToastMock.mock.calls[0]
expect(call[0].type).toBe('success')
expect(call[0].title).toBeDefined()
expect(getErrorToastMock).toBeCalledTimes(0)
expect(result.data).toBeDefined()
expect(result.error).toBeNull()

const dictionary = $dictionaries
.get()
.en.dictionaries.find((dictionary) => {
dictionary.id === dictionaryId
})
.en.dictionaries.find((dictionary) => dictionary.id === dictionaryId)

if (dictionary && 'variants' in dictionary) {
expect(dictionary.activeVariant).toBe('us')
} else {
throw Error(
`Dictionary with id ${dictionaryId} and variants option not found`,
)
}
})
})

test('should show error if can not set to DictionaryStorage and keep previous variant', async () => {
test('should return error if can not set to DictionaryStorage and keep previous variant', async () => {
vi.spyOn(DictionaryStorage, 'set').mockResolvedValue(Result.Error(error))

keepMount($dictionaries)
await allTasks()

await waitFor(async () => {
await selectVariant('en', dictionaryId, 'us')
const result = await selectVariant('en', dictionaryId, 'us')

expect(getErrorToastMock).toBeCalledWith(error)
expect(result.data).toBeNull()
expect(result.error).toEqual(error)

const dictionary = $dictionaries
.get()
.en.dictionaries.find((dictionary) => dictionary.id === dictionaryId)

if (dictionary && 'variants' in dictionary) {
expect(dictionary.activeVariant).toEqual('uk')
expect(dictionary?.activeVariant).toEqual('uk')
} else {
throw Error(
`Dictionary with id ${dictionaryId} and variants option not found`,
Expand All @@ -104,18 +108,15 @@ describe('dictionary store', () => {
})
})

test('should show error if dictionary not found', async () => {
test('should return error if dictionary not found', async () => {
keepMount($dictionaries)
await allTasks()

await waitFor(async () => {
await selectVariant('en', 'NOT_EXISTING_ID', 'us')
const result = await selectVariant('en', 'NOT_EXISTING_ID', 'us')

const call = getErrorToastMock.mock.calls[0]
expect(call[0].type).toBe(
'ERROR_CAN_NOT_FIND_DICTIONARY_TO_SELECT_VARIANT',
)
expect(call[0].error).toBeDefined()
expect(result.data).toBeNull()
expect(result.error).toBeDefined()
})
})
})
Expand Down
52 changes: 25 additions & 27 deletions src/entities/dictionary/model/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { TLanguageCode } from '@entities/language'
import { getStorage } from '@entities/storage'

import { browser } from '@shared/browser'
import { Result } from '@shared/libs/operationResult'
import { addToast, getErrorToast } from '@shared/ui/Toast'
import { Result, TResult } from '@shared/libs/operationResult'

import { DICTIONARIES } from './dictionaries'
import { TDictionaries } from './types'
Expand All @@ -22,19 +21,23 @@ export const $dictionaries = atom<StorageValue>(DICTIONARIES)
onMount($dictionaries, () => {
task(async () => {
const getResult = await DictionaryStorage.get()
if (getResult.data) {
$dictionaries.set(getResult.data)
} else {
addToast(getErrorToast(getResult.error))
}
getResult.data && $dictionaries.set(getResult.data)
})

const listener = DictionaryStorage.onChanged.addListener((changes) => {
changes.data && $dictionaries.set(changes.data.newValue)
})

return () => {
DictionaryStorage.onChanged.removeListener(listener)
}
})

export const selectVariant = async (
languageCode: TLanguageCode,
dictionaryId: string,
variant: string,
) => {
): Promise<TResult> => {
const dictionaries = $dictionaries.get()

const dictionary = dictionaries[languageCode].dictionaries.find(
Expand All @@ -57,25 +60,20 @@ export const selectVariant = async (
),
},
}

const setResult = await DictionaryStorage.set(newDictionaries)
if (setResult.data) {
$dictionaries.set(newDictionaries)
addToast({
type: 'success',
title: browser.i18n.getMessage('SELECT_DICTIONARY_VARIANT_SAVED'),
})
} else {
addToast(getErrorToast(setResult.error))
}
} else {
const resultError = Result.Error({
type: 'ERROR_CAN_NOT_FIND_DICTIONARY_TO_SELECT_VARIANT',
error: new Error(
`Dictionary with id ${dictionaryId} and variants option not found, available dictionaries: /n ${JSON.stringify(dictionaries)}`,
),
})
if (resultError.error) {
addToast(getErrorToast(resultError.error))
}

return setResult.data
? Result.Success(
browser.i18n.getMessage('SELECT_DICTIONARY_VARIANT_SAVED'),
)
: setResult
}

return Result.Error({
type: 'ERROR_CAN_NOT_FIND_DICTIONARY_TO_SELECT_VARIANT',
error: new Error(
`Dictionary with id ${dictionaryId} and variants option not found, available dictionaries: /n ${JSON.stringify(dictionaries)}`,
),
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@entities/dictionary'

import { Button } from '@shared/ui/Button'
import { addToast } from '@shared/ui/Toast'

import styles from './styles.module.scss'

Expand All @@ -13,6 +14,16 @@ interface GroupProps {
}

export const SelectDictionaryVariant = ({ dictionary }: GroupProps) => {
const onSelectVariant = async (variant: string) => {
const result = await dictionaryStore.selectVariant(
'en',
dictionary.id,
variant,
)

result.error && addToast({ title: result.error.type, type: 'error' })
}

return (
<ul className={`${styles.variants}`}>
{dictionary.variants.map((variant) => {
Expand All @@ -25,13 +36,7 @@ export const SelectDictionaryVariant = ({ dictionary }: GroupProps) => {
actions={
<Button
disabled={isActive}
onClick={() =>
dictionaryStore.selectVariant(
'en',
dictionary.id,
variant.value,
)
}
onClick={() => onSelectVariant(variant.value)}
>
{isActive
? `${variant.label} version is used`
Expand Down

0 comments on commit a5f5bc6

Please sign in to comment.