Skip to content

Commit

Permalink
Add tests for getBytes and getDeepLApiBaseUrl
Browse files Browse the repository at this point in the history
(#31)
  • Loading branch information
ttsukagoshi committed Mar 22, 2023
1 parent 730ca16 commit 2d9e729
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 33 deletions.
20 changes: 20 additions & 0 deletions __tests__/getBytes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getBlobBytes } from '../src/sheetsl';

Utilities.newBlob = jest.fn((text: string) => ({
getBytes: jest.fn(() => ({
length: text.length,
})),
})) as any;

const patterns = [
{
input: 'test string',
expectedOutput: 11,
},
];

describe.each(patterns)('getBlobBytes', ({ input, expectedOutput }) => {
test(`getBlobBytes test: ${input}`, () => {
expect(getBlobBytes(input)).toBe(expectedOutput);
});
});
27 changes: 27 additions & 0 deletions __tests__/getDeepLApiBaseUrl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
DEEPL_API_BASE_URL_FREE,
DEEPL_API_BASE_URL_PRO,
getDeepLApiBaseUrl,
} from '../src/sheetsl';

const patterns = [
{
title: 'DeepL API Free account',
input: 'xxxxxxxxxxx:fx',
expectedOutput: DEEPL_API_BASE_URL_FREE,
},
{
title: 'DeepL API Pro account',
input: 'xxxxxxxxxxx',
expectedOutput: DEEPL_API_BASE_URL_PRO,
},
];

describe.each(patterns)(
'getDeepLApiBaseUrl',
({ title, input, expectedOutput }) => {
test(`getDeepLApiBaseUrl test: ${title}`, () => {
expect(getDeepLApiBaseUrl(input)).toBe(expectedOutput);
});
}
);
54 changes: 21 additions & 33 deletions src/sheetsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
limitations under the License.
*/

const ADDON_NAME = 'SheetsL';
export const ADDON_NAME = 'SheetsL';
const UP_KEY_DEEPL_API_KEY = 'deeplApiKey'; // User property key for saving the DeepL API key
const UP_KEY_SOURCE_LOCALE = 'sourceLocale'; // User property key for saving the source language for DeepL
const UP_KEY_TARGET_LOCALE = 'targetLocale'; // User property key for saving the target language for DeepL
const DEEPL_API_VERSION = 'v2'; // DeepL API version
const DEEPL_API_BASE_URL_FREE = `https://api-free.deepl.com/${DEEPL_API_VERSION}/`;
const DEEPL_API_BASE_URL_PRO = `https://api.deepl.com/${DEEPL_API_VERSION}/`;
export const DEEPL_API_BASE_URL_FREE = `https://api-free.deepl.com/${DEEPL_API_VERSION}/`;
export const DEEPL_API_BASE_URL_PRO = `https://api.deepl.com/${DEEPL_API_VERSION}/`;
const ROW_SEPARATOR = '|||';

// Threshold value of the length of the text to translate, in bytes. See https://developers.google.com/apps-script/guides/services/quotas#current_limitations
Expand All @@ -30,29 +30,29 @@ const THRESHOLD_BYTES = 1900;
* GET request on /v2/languages returns an array of this object.
* @see https://www.deepl.com/docs-api/general/get-languages/
*/
interface DeepLSupportedLanguages {
type DeepLSupportedLanguages = {
language: string;
name: string;
supports_formality: boolean;
}
};

/**
* The response from the DeepL API for POST /v2/translate.
* @see https://www.deepl.com/docs-api/translate-text/
*/
interface DeepLTranslationResponse {
type DeepLTranslationResponse = {
translations: DeepLTranslationObj[];
}
};

/**
* The individual translated text object in the translated response
* from DeepL API.
* @see https://www.deepl.com/docs-api/translate-text/
*/
interface DeepLTranslationObj {
type DeepLTranslationObj = {
detected_source_language: string;
text: string;
}
};

/**
* Create add-on menu on opening spreadsheet file.
Expand All @@ -76,14 +76,14 @@ function onOpen(): void {
/**
* Create add-on menu on installation of add-on.
*/
function onInstall(): void {
export function onInstall(): void {
onOpen();
}

/**
* Store DeepL API authentication key in user property.
*/
function setDeeplAuthKey(): void {
export function setDeeplAuthKey(): void {
const ui = SpreadsheetApp.getUi();
try {
const promptResponse = ui.prompt(
Expand Down Expand Up @@ -117,7 +117,7 @@ function setDeeplAuthKey(): void {
/**
* Delete the stored DeepL API authentication key in user property.
*/
function deleteDeeplAuthKey(): void {
export function deleteDeeplAuthKey(): void {
const ui = SpreadsheetApp.getUi();
try {
PropertiesService.getUserProperties().deleteProperty(UP_KEY_DEEPL_API_KEY);
Expand All @@ -133,7 +133,7 @@ function deleteDeeplAuthKey(): void {
/**
* Set source and target languages for translation.
*/
function setLanguage(): void {
export function setLanguage(): void {
const ui = SpreadsheetApp.getUi();
try {
const up = PropertiesService.getUserProperties();
Expand Down Expand Up @@ -227,7 +227,7 @@ function setLanguage(): void {
* Translate the selected cell range using DeepL API
* and paste the result in the adjacent range.
*/
function translateRange(): void {
export function translateRange(): void {
const ui = SpreadsheetApp.getUi();
const activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const selectedRange = activeSheet.getActiveRange();
Expand Down Expand Up @@ -265,12 +265,12 @@ function translateRange(): void {

const translatedText = sourceTextArr.map((row) => {
const joinedRowText = row.join(ROW_SEPARATOR);
if (getBytes(encodeURIComponent(joinedRowText)) > THRESHOLD_BYTES) {
if (getBlobBytes(encodeURIComponent(joinedRowText)) > THRESHOLD_BYTES) {
console.info(
`[${ADDON_NAME}] ${joinedRowText} is longer than ${THRESHOLD_BYTES} bytes. Switching to per cell translation.`
);
return row.map((cellValue: string | number | boolean) => {
if (getBytes(encodeURIComponent(cellValue)) > THRESHOLD_BYTES) {
if (getBlobBytes(encodeURIComponent(cellValue)) > THRESHOLD_BYTES) {
throw new Error(
`[${ADDON_NAME}] Cell content is too long. Please consider splitting the content into multiple cells:\n${cellValue}`
);
Expand Down Expand Up @@ -314,9 +314,9 @@ function translateRange(): void {
* @returns Array of translated texts.
* @see https://www.deepl.com/docs-api/translate-text/
*/
function deepLTranslate(
export function deepLTranslate(
sourceText: string | string[],
sourceLocale: string,
sourceLocale: string | null | undefined,
targetLocale: string
): string[] {
const endpoint = 'translate';
Expand Down Expand Up @@ -356,8 +356,6 @@ function deepLTranslate(
// Handle error codes
// See https://www.deepl.com/docs-api/api-access/error-handling/
const responseCode = response.getResponseCode();
// console.log(`responseCode: ${responseCode}`);

if (responseCode === 429) {
throw new Error(
`[${ADDON_NAME}] Too Many Requests: Try again after some time.`
Expand Down Expand Up @@ -390,7 +388,7 @@ function deepLTranslate(
* @returns An array of the supported languages.
* @see https://www.deepl.com/docs-api/general/get-languages/
*/
function deepLGetLanguages(type = 'source'): DeepLSupportedLanguages[] {
export function deepLGetLanguages(type = 'source'): DeepLSupportedLanguages[] {
const endpoint = 'languages';
// API key
const apiKey =
Expand Down Expand Up @@ -418,7 +416,7 @@ function deepLGetLanguages(type = 'source'): DeepLSupportedLanguages[] {
* @returns The relevant base URL for DeepL API
* @see https://support.deepl.com/hc/en-us/articles/360021183620-DeepL-API-Free-vs-DeepL-API-Pro
*/
function getDeepLApiBaseUrl(apiKey: string): string {
export function getDeepLApiBaseUrl(apiKey: string): string {
return apiKey.endsWith(':fx')
? DEEPL_API_BASE_URL_FREE
: DEEPL_API_BASE_URL_PRO;
Expand All @@ -429,16 +427,6 @@ function getDeepLApiBaseUrl(apiKey: string): string {
* @param text The string of which to get the bytes.
* @returns The length of the given text in bytes.
*/
function getBytes(text: string): number {
export function getBlobBytes(text: string): number {
return Utilities.newBlob(text).getBytes().length;
}

if (typeof module === 'object') {
module.exports = {
onInstall,
setDeeplAuthKey,
deleteDeeplAuthKey,
setLanguage,
translateRange,
};
}

0 comments on commit 2d9e729

Please sign in to comment.