From 3023a1579cbf47c77952271534bab37b615c1a2f Mon Sep 17 00:00:00 2001 From: aguestuser <aguestuser@riseup.net> Date: Tue, 19 Nov 2019 23:45:31 -0500 Subject: [PATCH] [75] update EN -> ES translations side-effects: * restructure `strings/messages` JSON structure * add regression test to make sure translations are provided in ES for all EN strings --- app/services/dispatcher/commands/execute.js | 8 +- app/services/dispatcher/commands/index.js | 4 +- app/services/dispatcher/commands/parse.js | 7 +- .../dispatcher/strings/messages/EN.js | 143 +++++++----- .../dispatcher/strings/messages/ES.js | 216 ++++++++++++------ .../dispatcher/commands/execute.spec.js | 32 +-- .../dispatcher/commands/parse.spec.js | 56 ++--- .../unit/services/dispatcher/messages.spec.js | 3 +- .../services/dispatcher/messenger.spec.js | 2 +- test/unit/services/dispatcher/strings.spec.js | 19 ++ 10 files changed, 303 insertions(+), 187 deletions(-) create mode 100644 test/unit/services/dispatcher/strings.spec.js diff --git a/app/services/dispatcher/commands/execute.js b/app/services/dispatcher/commands/execute.js index bafaa8f..c6b9a88 100644 --- a/app/services/dispatcher/commands/execute.js +++ b/app/services/dispatcher/commands/execute.js @@ -52,7 +52,7 @@ const execute = async (executable, dispatchable) => { // ADD const maybeAddPublisher = async (db, channel, sender, phoneNumberInput) => { - const cr = messagesIn(sender.language).commandResponses.publisher.add + const cr = messagesIn(sender.language).commandResponses.add if (!(sender.type === PUBLISHER)) { return Promise.resolve({ status: statuses.UNAUTHORIZED, message: cr.unauthorized }) } @@ -102,7 +102,7 @@ const showInfo = async (db, channel, sender, cr) => ({ // JOIN const maybeAddSubscriber = async (db, channel, sender, language) => { - const cr = messagesIn(language).commandResponses.subscriber.add + const cr = messagesIn(language).commandResponses.join return sender.type === SUBSCRIBER ? Promise.resolve({ status: statuses.NOOP, message: cr.noop }) : addSubscriber(db, channel, sender, language, cr) @@ -117,7 +117,7 @@ const addSubscriber = (db, channel, sender, language, cr) => // LEAVE const maybeRemoveSender = async (db, channel, sender) => { - const cr = messagesIn(sender.language).commandResponses.subscriber.remove + const cr = messagesIn(sender.language).commandResponses.leave return sender.type === NONE ? Promise.resolve({ status: statuses.UNAUTHORIZED, message: cr.unauthorized }) : removeSender(db, channel, sender, cr) @@ -136,7 +136,7 @@ const removeSender = (db, channel, sender, cr) => { // REMOVE const maybeRemovePublisher = async (db, channel, sender, publisherNumber) => { - const cr = messagesIn(sender.language).commandResponses.publisher.remove + const cr = messagesIn(sender.language).commandResponses.remove const { isValid, phoneNumber: validNumber } = validator.parseValidPhoneNumber(publisherNumber) if (!(sender.type === PUBLISHER)) { diff --git a/app/services/dispatcher/commands/index.js b/app/services/dispatcher/commands/index.js index fdbe9ad..3ce17ff 100644 --- a/app/services/dispatcher/commands/index.js +++ b/app/services/dispatcher/commands/index.js @@ -1,8 +1,8 @@ const { execute } = require('./execute') -const { parseCommand } = require('./parse') +const { parseExecutable } = require('./parse') // Dispatchable -> Promise<{dispatchable: Dispatchable, commandResult: CommandResult}> const processCommand = dispatchable => - execute(parseCommand(dispatchable.sdMessage.messageBody), dispatchable) + execute(parseExecutable(dispatchable.sdMessage.messageBody), dispatchable) module.exports = { processCommand } diff --git a/app/services/dispatcher/commands/parse.js b/app/services/dispatcher/commands/parse.js index b38a44d..f42d9cc 100644 --- a/app/services/dispatcher/commands/parse.js +++ b/app/services/dispatcher/commands/parse.js @@ -3,9 +3,8 @@ const { commandsByLanguage } = require('../strings/commands') const { commands } = require('./constants') const { defaultLanguage } = require('../../../config') -// TODO(aguestuser|2019-11-17): rename this parseExecutable // string -> Executable -const parseCommand = msg => { +const parseExecutable = msg => { const { command, language, matches } = _findCommandMatch(msg) || {} return { command: command || commands.NOOP, @@ -14,7 +13,7 @@ const parseCommand = msg => { } } -// string -> {command: string, language: string, matches: Array<string>} +// string -> Array<{command: string, language: string, matches: Array<string>}> const _findCommandMatch = msg => { // attempt to match on every variant of every command in every language // return first variant that matches (along with language and payload capturing group) @@ -33,4 +32,4 @@ const _findCommandMatch = msg => { return find(matchResults, ({ matches }) => !isEmpty(matches)) } -module.exports = { parseCommand } +module.exports = { parseExecutable } diff --git a/app/services/dispatcher/strings/messages/EN.js b/app/services/dispatcher/strings/messages/EN.js index 8a6dc99..119412b 100644 --- a/app/services/dispatcher/strings/messages/EN.js +++ b/app/services/dispatcher/strings/messages/EN.js @@ -10,18 +10,32 @@ const support = ` HOW IT WORKS ---------------------------- --> Signalboost has admins and subscribers. --> Admins send announcements that are broadcast to subscribers. --> People can subscribe by sending HELLO or HOLA to this number. --> Unsubscribe by sending GOODBYE or ADÍOS to this number. --> Send HELP or AYUDA to list commands that make Signalboost do things. --> Learn more: https://signalboost.info +Signalboost numbers have admins and subscribers. + +-> When admins send messages, they are broadcast to all subscribers. +-> If enabled, subscribers can send responses that only admins can read. +-> Subscribers cannot send messages to each other. (No noisy crosstalk!) + +Signalboost numbers understand commands. + +-> Sending HELP lists the commands. +-> People can subscribe by sending HELLO (or HOLA) and unsusbcribe with GOODBYE (or ADIÓS). +-> Sending a language name (for example: ESPAÑOL or ENGLISH) switches languages. + +Signalboost tries to preserve your privacy. + +-> Signalboost users cannot see each other's phone numbers. +-> Signalboost does not read or store anyone's messages. + +Learn more: https://signalboost.info ` const notifications = { publisherAdded: (commandIssuer, addedPublisher) => `New admin ${addedPublisher} added by ${commandIssuer}`, - broadcastResponseSent: channel => `Your message was forwarded to the admins of [${channel.name}]`, + broadcastResponseSent: channel => + `Your message was forwarded to the admins of [${channel.name}]. + Send HELP to see commands I understand! :)`, deauthorization: publisherPhoneNumber => ` ${publisherPhoneNumber} has been removed from this channel because their safety number changed. @@ -36,12 +50,14 @@ ADD ${publisherPhoneNumber} Until then, they will be unable to send messages to or read messages from this channel.`, noop: "Whoops! That's not a command!", unauthorized: "Whoops! I don't understand that.\n Send HELP to see commands I understand!", + welcome: (addingPublisher, channelPhoneNumber) => ` You were just made an admin of this Signalboost channel by ${addingPublisher}. Welcome! People can subscribe to this channel by sending HELLO to ${channelPhoneNumber} and unsubscribe by sending GOODBYE. Reply with HELP for more info.`, + signupRequestReceived: (senderNumber, requestMsg) => `Signup request received from ${senderNumber}:\n ${requestMsg}`, signupRequestResponse: @@ -49,31 +65,35 @@ Reply with HELP for more info.`, } const commandResponses = { - // ADD/REMOVE - publisher: { - add: { - success: num => `${num} added as an admin.`, - unauthorized, - dbError: num => `Whoops! There was an error adding ${num} as an admin. Please try again!`, - invalidNumber, - }, - remove: { - success: num => `${num} removed as an admin.`, - unauthorized, - dbError: num => `Whoops! There was an error trying to remove ${num}. Please try again!`, - invalidNumber, - targetNotPublisher: num => `Whoops! ${num} is not an admin. Can't remove them.`, - }, + // ADD + + add: { + success: num => `${num} added as an admin.`, + unauthorized, + dbError: num => `Whoops! There was an error adding ${num} as an admin. Please try again!`, + invalidNumber, }, + + // REMOVE + + remove: { + success: num => `${num} removed as an admin.`, + unauthorized, + dbError: num => `Whoops! There was an error trying to remove ${num}. Please try again!`, + invalidNumber, + targetNotPublisher: num => `Whoops! ${num} is not an admin. Can't remove them.`, + }, + // HELP + help: { publisher: `[COMMANDS I UNDERSTAND:] -HELP / AYUDA +HELP -> lists commands INFO --> shows stats, explains how signalboost works +-> shows stats, explains how Signalboost works RENAME new name -> renames channel to "new name" @@ -90,24 +110,29 @@ RESPONSES ON RESPONSES OFF -> disables subscribers from sending messages to admins -GOODBYE / ADIOS --> leaves this channel`, +GOODBYE +-> leaves this channel + +ESPAÑOL +-> switches language to Spanish`, + subscriber: `[COMMANDS I UNDERSTAND:] -HELP / AYUDA +HELP -> lists commands INFO -> shows stats, explains how signalboost works -HELLO / HOLA +HELLO -> subscribes you to announcements -GOODBYE / ADIOS +GOODBYE -> unsubscribes you from announcements`, }, // INFO + info: { publisher: channel => ` --------------------------- @@ -121,6 +146,7 @@ admins: ${channel.publications.map(a => a.publisherPhoneNumber).join(', ')} responses: ${channel.responsesEnabled ? 'ON' : 'OFF'} messages sent: ${channel.messageCount.broadcastIn} ${support}`, + subscriber: channel => ` --------------------------- CHANNEL INFO: @@ -130,11 +156,12 @@ name: ${channel.name} phone number: ${channel.phoneNumber} responses: ${channel.responsesEnabled ? 'ON' : 'OFF'} subscribers: ${channel.subscriptions.length} -admins: ${channel.publications.length} ${support}`, unauthorized, }, + // RENAME + rename: { success: (oldName, newName) => `[${newName}]\nChannel renamed from "${oldName}" to "${newName}".`, @@ -142,52 +169,56 @@ ${support}`, `[${oldName}]\nWhoops! There was an error renaming the channel [${oldName}] to [${newName}]. Try again!`, unauthorized, }, - // JOIN/LEAVE - subscriber: { - add: { - success: channel => { - const { name } = channel - return ` + + // JOIN + + join: { + success: channel => { + const { name } = channel + return ` Welcome to Signalboost! You are now subscribed to the [${name}] channel. Reply with HELP to learn more or GOODBYE to unsubscribe.` - }, - dbError: `Whoops! There was an error adding you to the channel. Please try again!`, - noop: `Whoops! You are already a member of the channel.`, - }, - remove: { - success: `You've been removed from the channel! Bye!`, - error: `Whoops! There was an error removing you from the channel. Please try again!`, - unauthorized, }, + dbError: `Whoops! There was an error adding you to the channel. Please try again!`, + noop: `Whoops! You are already a member of the channel.`, + }, + + // LEAVE + + leave: { + success: `You've been removed from the channel! Bye!`, + error: `Whoops! There was an error removing you from the channel. Please try again!`, + unauthorized, }, - // TOGGLE RESPONSES + + // RESPONSES_ON / RESPONSES_OFF + toggleResponses: { success: setting => `Subscriber responses turned ${upperCase(setting)}.`, unauthorized, dbError: setting => `Whoops! There was an error trying to set responses to ${setting}. Please try again!`, - invalidSetting: setting => - `Whoops! ${setting} is not a valid setting. You can set responses to be either ON or OFF.`, }, + + // SET_LANGUAGE + + setLanguage: { + success: 'I will talk to you in English now! \n Send HELP to list commands I understand.', + dbError: 'Whoops! Failed to store your language preference. Please try again!', + }, + + // TRUST + trust: { success: phoneNumber => `Updated safety number for ${phoneNumber}`, error: phoneNumber => `Failed to update safety number for ${phoneNumber}. Try again or contact a maintainer!`, - partialError: (phoneNumber, success, error) => - `Updated safety number for ${success} out of ${success + - error} channels that ${phoneNumber} belongs to.`, invalidNumber, unauthorized, - targetNotMember: phoneNumber => - `Whoops! ${phoneNumber} is not an admin or subscriber on this channel. Cannot reactivate them.`, dbError: phoneNumber => `Whoops! There was an error updating the safety number for ${phoneNumber}. Please try again!`, }, - setLanguage: { - success: 'I will talk to you in English now!', - dbError: 'Failed to store your language preference. Please try again!', - }, } const prefixes = { diff --git a/app/services/dispatcher/strings/messages/ES.js b/app/services/dispatcher/strings/messages/ES.js index 6792445..5e34ec4 100644 --- a/app/services/dispatcher/strings/messages/ES.js +++ b/app/services/dispatcher/strings/messages/ES.js @@ -1,71 +1,110 @@ const { upperCase } = require('lodash') -const unauthorized = 'Whoops! No tiene autorización para hacerlo en este canal.' + +const systemName = 'El administrador del sistema de Signalboost' +const unauthorized = 'Lo siento! No tiene autorización para hacerlo en este canal.' +const invalidNumber = phoneNumber => + `¡Lo siento! "${phoneNumber}" no es un número de teléfono válido. Los números de teléfono deben incluir códigos de país con el prefijo '+'.` const support = ` ---------------------------- CÓMO FUNCIONA ---------------------------- --> Los números de Signalboost tienen administradores y suscriptores. --> Los administradores envían anuncios que se transmiten a los suscriptores. --> Suscríbete a los anuncios enviando "HOLA" a un número. --> Darse de baja enviando "ADIOS" al número. --> Enviar "AYUDA" a un número para enumerar los comandos que hacen que haga cosas. --> Más información: https://0xacab.org/team-friendo/signalboost` +Los números de Signalboost tienen administradores y suscriptores. + +-> Cuando los administradores envían mensajes, se transmiten a todos los suscriptores. +-> Si está habilitado, los suscriptores pueden enviar respuestas que solo los administradores pueden leer. +-> Los suscriptores no pueden enviarse mensajes entre sí. (¡No hay diafonía ruidosa!) + +Los números de Signalboost entienden los comandos. + +-> Las personas pueden suscribirse enviando HOLA y darse de baja con ADIÓS. +-> Enviar un nombre de idioma (por ejemplo: ESPAÑOL o ENGLISH) cambia de idioma. +-> Enviar AYUDA enumera los comandos. + +Signalboost intenta preservar su privacidad. + +-> Los usuarios de Signalboost no pueden ver los números de teléfono de los demás. +-> Signalboost no lee ni almacena los mensajes de nadie. + +Para más información: https://signalboost.info` const notifications = { - broadcastResponseSent: channel => ` -Su mensaje fue enviado a los administradores de [${channel.name}]. -¡Envíe AYUDA para ver los comandos que entiendo! :) -`, - welcome: (channel, addingPublisher) => { - const { name } = channel - return ` -¡Bienvenido a Signalboost! ${addingPublisher} te acaba de hacer un administrador del canal [${name}]. - -Responda con AYUDA para obtener más información o ADIÓS para irse.` - }, - noop: 'Whoops! Eso no es un comando!', + publisherAdded: (commandIssuer, addedPublisher) => + `Nuevo administrador ${addedPublisher} agregado por ${commandIssuer}`, + + broadcastResponseSent: channel => + `Su mensaje fue enviado a los administradores de [${channel.name}]. + ¡Envíe AYUDA para ver los comandos que entiendo! :)`, + + deauthorization: publisherPhoneNumber => ` +${publisherPhoneNumber} se ha eliminado de este canal porque su número de seguridad cambió. + +Esto es casi seguro porque reinstalaron Signal en un nuevo teléfono. + +Sin embargo, existe una pequeña posibilidad de que un atacante haya comprometido su teléfono y esté tratando de hacerse pasar por él. + +Verifique con ${publisherPhoneNumber} para asegurarse de que todavía controlan su teléfono, luego vuelva a autorizarlos con: + + AGREGAR ${publisherPhoneNumber} + + Hasta entonces, no podrán enviar mensajes ni leer mensajes de este canal.`, + + welcome: (addingPublisher, channelPhoneNumber) => ` +Acabas de convertirte en administrador de este canal Signalboost por ${addingPublisher}. ¡Bienvenidos! + +Las personas pueden suscribirse a este canal enviando HOLA a ${channelPhoneNumber} y cancelar la suscripción enviando ADIÓS. + +Responda con AYUDA para más información.`, + + noop: 'Lo siento! Eso no es un comando!', unauthorized: ` -Whoops! No entiendo eso. -¡Envíe AYUDA para ver los comandos que entiendo! :)`, +Lo siento! No entiendo eso. +Envíe AYUDA para ver los comandos que entiendo! :)`, + + signupRequestReceived: (senderNumber, requestMsg) => + `Solicitud de registro recibida de ${senderNumber}: \n {requestMsg}`, + signupRequestResponse: + '¡Gracias por registrarte en Signalboost! \nEn breve recibirás un mensaje de bienvenida en tu nuevo canal...', } const commandResponses = { - // ADD/REMOVE PUBLISHER - publisher: { - add: { - success: num => `${num} agregó como administrador.`, - unauthorized, - dbError: num => - `Whoops! Se produjo un error al agregar ${num} como administrador. ¡Inténtalo de nuevo!`, - invalidNumber: num => - `Whoops! Error al agregar "${num}". Los números de teléfono deben incluir códigos de país con el prefijo '+'`, - }, - remove: { - success: num => `${num} eliminado como administrador.`, - unauthorized, - dbError: num => - `Whoops! Se produjo un error al intentar eliminar ${num}. ¡Inténtalo de nuevo!`, - invalidNumber: num => - `¡Vaya! Error al eliminar "${num}". Los números de teléfono deben incluir códigos de país con el prefijo '+'`, - targetNotPublisher: num => `¡Vaya! ${num} no es un administrador. No puedo eliminarla.`, - }, + // ADD + + add: { + success: num => `${num} agregó como administrador.`, + unauthorized, + dbError: num => + `¡Lo siento! Se produjo un error al agregar ${num} como administrador. ¡Inténtalo de nuevo!`, + invalidNumber: num => + `¡Lo siento! Error al agregar "${num}". Los números de teléfono deben incluir códigos de país con el prefijo '+'`, + }, + + // REMOVE + + remove: { + success: num => `${num} eliminado como administrador.`, + unauthorized, + dbError: num => + `¡Lo siento! Se produjo un error al intentar eliminar ${num}. ¡Inténtalo de nuevo!`, + invalidNumber: num => + `¡Lo siento. Error al eliminar "${num}". Los números de teléfono deben incluir códigos de país con el prefijo '+'`, + targetNotPublisher: num => `Lo siento. ${num} no es un administrador. No puedo eliminarla.`, }, + // HELP + help: { - publisher: ` + publisher: `[COMMANDS I UNDERSTAND:] AYUDA -> listas de comandos -INFORMACIÓN --> muestra estadísticas, explica el refuerzo de señal +INFO +-> muestra estadísticas, explica cómo funciona Signalboost RENOMBRAR nuevo nombre -> cambia el nombre del canal a "nuevo nombre" -RESPUESTAS ACTIVADAS / RESPUESTAS DESACTIVADAS --> activa / desactiva las respuestas del suscriptor AGREGAR + 1-555-555-5555 -> convierte a + 1-555-555-5555 en administrador @@ -73,14 +112,22 @@ AGREGAR + 1-555-555-5555 QUITAR + 1-555-555-5555 -> elimina + 1-555-555-5555 como administrador +RESPUESTAS ACTIVADAS +-> permite a los suscriptores enviar mensajes a los administradores + +RESPUESTAS DESACTIVADAS +-> desactiva a los suscriptores de enviar mensajes a los administradores + ADIÓS -> te quita del canal`, - subscriber: ` + + subscriber: `[COMMANDS I UNDERSTAND:] + AYUDA -> listas de comandos -INFORMACIÓN --> explica el refuerzo de señal +INFO +-> explica explica cómo funciona Signalboost HOLA -> te suscribe a mensajes @@ -90,6 +137,7 @@ ADIÓS }, // INFO + info: { publisher: channel => ` --------------------------- @@ -103,66 +151,86 @@ respuestas: ${channel.responsesEnabled ? 'ACTIVADAS' : 'DESACTIVADAS'} mensajes enviados: ${channel.messageCount.broadcastIn} administradorxs: ${channel.publications.map(a => a.publisherPhoneNumber).join(',')} ${support}`, + subscriber: channel => ` --------------------------- -CHANNEL INFO: +INFO DEL CANAL: --------------------------- nombre: ${channel.name} número de teléfono: ${channel.phoneNumber} respuestas: ${channel.responsesEnabled ? 'ACTIVADAS' : 'DESACTIVADAS'} suscriptorxs: ${channel.subscriptions.length} -administradorxs: ${channel.publications.length} ${support}`, unauthorized, }, + // RENAME + rename: { success: (oldName, newName) => `[${newName}]\nCanal renombrado de "${oldName}" a "${newName}".`, dbError: (oldName, newName) => - `[${oldName}]\nWhoops! Se produjo un error al cambiar el nombre del canal [${oldName}] a [${newName}]. ¡Inténtalo de nuevo!`, + `[${oldName}]\nLo siento! Se produjo un error al cambiar el nombre del canal [${oldName}] a [${newName}]. ¡Inténtalo de nuevo!`, unauthorized, }, - // ADD/REMOVE SUBSCRIBER - subscriber: { - add: { - success: channel => { - const { name } = channel - return ` -¡Bienvenido a Signalboost! Ahora está suscrito al canal [${name}]. + + // JOIN + + join: { + success: channel => { + const { name } = channel + return ` +¡Bienvenido a Signalboost! Ahora estás suscrito al canal [${name}]. Responda con AYUDA para obtener más información o ADIÓS para darse de baja.` - }, - dbError: `Whoops! Se produjo un error al agregarlo al canal. ¡Inténtalo de nuevo!`, - noop: `Whoops! Ya eres miembro del canal.`, - }, - remove: { - success: `¡Has sido eliminado del canal! ¡Adiós!`, - error: `Whoops! Se produjo un error al eliminarlo del canal. ¡Inténtalo de nuevo!`, - unauthorized, }, + dbError: `Lo siento! Se produjo un error al agregarlo al canal. Inténtalo de nuevo!`, + noop: `¡Lo siento! Ya eres miembro del canal.`, }, - // TOGGLE RESPONSES + + // LEAVE + + leave: { + success: `¡Has sido eliminado del canal! ¡Adiós!`, + error: `¡Lo siento! Se produjo un error al eliminarlo del canal. ¡Inténtalo de nuevo!`, + unauthorized, + }, + + // RESPONSES_ON / RESPONSES_OFF + toggleResponses: { success: setting => `Respuestas del suscriptor configurado en ${upperCase(setting)}.`, unauthorized, dbError: setting => - `Whoops! Se produjo un error al intentar establecer respuestas a $ {setting}. ¡Inténtalo de nuevo!`, - invalidSetting: setting => - `Whoops! $ {setting} no es una configuración válida. Puede configurar las respuestas para que estén ACTIVADAS o DESACTIVADAS.`, + `¡Lo siento! Se produjo un error al intentar establecer respuestas a ${setting}. ¡Inténtalo de nuevo!`, }, + + // SET_LANGUAGE + setLanguage: { - success: '¡Hablaré contigo en español ahora!', - dbError: 'Lo ciento. Era un error. ¡Inténtalo de nuevo!', + success: '¡Hablaré contigo en español ahora! \nEnvia AYUDA para comandos que comprendo.', + dbError: '¡Lo siento! No se pudo almacenar su preferencia de idioma. ¡Inténtalo de nuevo!', + }, + + // TRUST + + trust: { + success: phoneNumber => `Número de seguridad actualizado para ${phoneNumber}`, + error: phoneNumber => + `Error al actualizar el número de seguridad para ${phoneNumber}. ¡Inténtalo de nuevo o contacta a un mantenedor!`, + invalidNumber, + unauthorized, + dbError: phoneNumber => + `¡Lo siento! Se produjo un error al actualizar el número de seguridad de ${phoneNumber}. ¡Inténtalo de nuevo!`, }, } const prefixes = { - helpResponse: `COMANDOS QUE ENTIENDO ...`, - broadcastResponse: `RESPUESTA DEL SUSCRIPTOR ...`, + broadcastResponse: `RESPUESTA DEL SUSCRIPTOR:`, } const EN = { + systemName, commandResponses, notifications, prefixes, diff --git a/test/unit/services/dispatcher/commands/execute.spec.js b/test/unit/services/dispatcher/commands/execute.spec.js index 7767942..1c08f6e 100644 --- a/test/unit/services/dispatcher/commands/execute.spec.js +++ b/test/unit/services/dispatcher/commands/execute.spec.js @@ -83,7 +83,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.ADD, status: statuses.SUCCESS, - message: CR.publisher.add.success(publisherPhoneNumber), + message: CR.add.success(publisherPhoneNumber), payload: publisherPhoneNumber, }) }) @@ -96,7 +96,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.ADD, status: statuses.ERROR, - message: CR.publisher.add.dbError(publisherPhoneNumber), + message: CR.add.dbError(publisherPhoneNumber), }) }) }) @@ -115,7 +115,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.ADD, status: statuses.ERROR, - message: CR.publisher.add.invalidNumber('foo'), + message: CR.add.invalidNumber('foo'), }) }) }) @@ -139,7 +139,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.ADD, status: statuses.UNAUTHORIZED, - message: CR.publisher.add.unauthorized, + message: CR.add.unauthorized, }) }) }) @@ -256,7 +256,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.JOIN, status: statuses.SUCCESS, - message: CR.subscriber.add.success(channel), + message: CR.join.success(channel), }) }) }) @@ -268,7 +268,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.JOIN, status: statuses.ERROR, - message: CR.subscriber.add.error, + message: CR.join.error, }) }) }) @@ -288,7 +288,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.JOIN, status: statuses.NOOP, - message: CR.subscriber.add.noop, + message: CR.join.noop, }) }) }) @@ -320,7 +320,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.LEAVE, status: statuses.SUCCESS, - message: CR.subscriber.remove.success, + message: CR.leave.success, }) }) }) @@ -331,7 +331,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.LEAVE, status: statuses.ERROR, - message: CR.subscriber.remove.error, + message: CR.leave.error, }) }) }) @@ -350,7 +350,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.LEAVE, status: statuses.UNAUTHORIZED, - message: CR.subscriber.remove.unauthorized, + message: CR.leave.unauthorized, }) }) }) @@ -379,7 +379,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.LEAVE, status: statuses.SUCCESS, - message: CR.subscriber.remove.success, + message: CR.leave.success, }) }) }) @@ -430,7 +430,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.REMOVE, status: statuses.SUCCESS, - message: CR.publisher.remove.success(publisherPhoneNumber), + message: CR.remove.success(publisherPhoneNumber), }) }) }) @@ -442,7 +442,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.REMOVE, status: statuses.ERROR, - message: CR.publisher.remove.dbError(publisherPhoneNumber), + message: CR.remove.dbError(publisherPhoneNumber), }) }) }) @@ -459,7 +459,7 @@ describe('executing commands', () => { expect(await processCommand(dispatchable)).to.eql({ command: commands.REMOVE, status: statuses.ERROR, - message: CR.publisher.remove.targetNotPublisher(publisherPhoneNumber), + message: CR.remove.targetNotPublisher(publisherPhoneNumber), }) }) }) @@ -479,7 +479,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.REMOVE, status: statuses.ERROR, - message: CR.publisher.remove.invalidNumber('foo'), + message: CR.remove.invalidNumber('foo'), }) }) }) @@ -500,7 +500,7 @@ describe('executing commands', () => { expect(result).to.eql({ command: commands.REMOVE, status: statuses.UNAUTHORIZED, - message: CR.publisher.remove.unauthorized, + message: CR.remove.unauthorized, }) }) }) diff --git a/test/unit/services/dispatcher/commands/parse.spec.js b/test/unit/services/dispatcher/commands/parse.spec.js index 8a88a3f..9e4e8c9 100644 --- a/test/unit/services/dispatcher/commands/parse.spec.js +++ b/test/unit/services/dispatcher/commands/parse.spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import { describe, it } from 'mocha' import { commands } from '../../../../../app/services/dispatcher/commands/constants' -import { parseCommand } from '../../../../../app/services/dispatcher/commands/parse' +import { parseExecutable } from '../../../../../app/services/dispatcher/commands/parse' import { languages } from '../../../../../app/constants' import { defaultLanguage } from '../../../../../app/config' @@ -31,7 +31,7 @@ describe('parsing commands', () => { 'hace ESPAÑOL', ] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.NOOP, language: defaultLanguage, payload: '', @@ -45,7 +45,7 @@ describe('parsing commands', () => { it('parses an ADD command (regardless of case or whitespace)', () => { const msgs = ['ADD', 'add', ' add '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.ADD, language: languages.EN, payload: '', @@ -54,7 +54,7 @@ describe('parsing commands', () => { }) it('parses the payload from an ADD command', () => { - expect(parseCommand('ADD foo')).to.eql({ + expect(parseExecutable('ADD foo')).to.eql({ command: commands.ADD, language: languages.EN, payload: 'foo', @@ -66,7 +66,7 @@ describe('parsing commands', () => { it('parses a HELP command (regardless of case or whitespace)', () => { const msgs = ['HELP', 'help', ' help '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.HELP, language: languages.EN, payload: '', @@ -79,7 +79,7 @@ describe('parsing commands', () => { it('parses an INFO command (regardless of case or whitespace)', () => { const msgs = ['INFO', 'info', ' info '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.INFO, language: languages.EN, payload: '', @@ -92,7 +92,7 @@ describe('parsing commands', () => { it('parses an JOIN command from "hello" or "join" (regardless of case or whitespace)', () => { const msgs = ['HELLO', 'hello', ' hello ', 'JOIN', 'join', ' join '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.JOIN, language: languages.EN, payload: '', @@ -105,7 +105,7 @@ describe('parsing commands', () => { it('parses an LEAVE command from "goodbye" or "leave" (regardless of case or whitespace)', () => { const msgs = ['GOODBYE', 'goodbye', ' goodbye ', 'LEAVE', 'leave', ' leave '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.LEAVE, language: languages.EN, payload: '', @@ -118,7 +118,7 @@ describe('parsing commands', () => { it('parses an REMOVE command (regardless of case or whitespace)', () => { const msgs = ['REMOVE', 'remove', ' remove '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.REMOVE, language: languages.EN, payload: '', @@ -127,7 +127,7 @@ describe('parsing commands', () => { }) it('parses the payload from an REMOVE command', () => { - expect(parseCommand('REMOVE foo')).to.eql({ + expect(parseExecutable('REMOVE foo')).to.eql({ command: commands.REMOVE, language: languages.EN, payload: 'foo', @@ -140,7 +140,7 @@ describe('parsing commands', () => { it('parses an RENAME command (regardless of case or whitespace)', () => { const msgs = ['RENAME', 'rename', ' rename '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RENAME, language: languages.EN, payload: '', @@ -150,7 +150,7 @@ describe('parsing commands', () => { }) it('parses the payload from an RENAME command', () => { - expect(parseCommand('RENAME foo')).to.eql({ + expect(parseExecutable('RENAME foo')).to.eql({ command: commands.RENAME, language: languages.EN, payload: 'foo', @@ -163,7 +163,7 @@ describe('parsing commands', () => { it('parses an RENAME command (regardless of case or whitespace)', () => { const msgs = ['RESPONSES ON', 'responses on', ' responses on '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RESPONSES_ON, language: languages.EN, payload: '', @@ -178,7 +178,7 @@ describe('parsing commands', () => { it('parses an RENAME command (regardless of case or whitespace)', () => { const msgs = ['RESPONSES OFF', 'responses off', ' responses off '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RESPONSES_OFF, language: languages.EN, payload: '', @@ -192,7 +192,7 @@ describe('parsing commands', () => { it('sets the language to English regardless of language in which English is specified', () => { const msgs = ['ENGLISH', 'INGLÉS', 'INGLES', 'english', 'inglés', 'ingles'] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.SET_LANGUAGE, language: languages.EN, payload: '', @@ -207,7 +207,7 @@ describe('parsing commands', () => { it('parses an ADD command (regardless of case or whitespace)', () => { const msgs = ['AGREGAR', 'agregar', ' agregar '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.ADD, language: languages.ES, payload: '', @@ -216,7 +216,7 @@ describe('parsing commands', () => { }) it('parses the payload from an ADD command', () => { - expect(parseCommand('AGREGAR foo')).to.eql({ + expect(parseExecutable('AGREGAR foo')).to.eql({ command: commands.ADD, language: languages.ES, payload: 'foo', @@ -228,7 +228,7 @@ describe('parsing commands', () => { it('parses an HELP command (regardless of case or whitespace)', () => { const msgs = ['AYUDA', 'ayuda', ' ayuda '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.HELP, language: languages.ES, payload: '', @@ -241,7 +241,7 @@ describe('parsing commands', () => { it('parses an INFO command but does NOT detect language', () => { const msgs = ['INFO', 'info', ' info '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.INFO, language: languages.EN, payload: '', @@ -254,7 +254,7 @@ describe('parsing commands', () => { it('parses an JOIN command from "hola"(regardless of case or whitespace)', () => { const msgs = ['HOLA', 'hola', ' hola '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.JOIN, language: languages.ES, payload: '', @@ -266,7 +266,7 @@ describe('parsing commands', () => { it('parses an LEAVE command from "ADIOS" (regardless of accents, case or whitespace)', () => { const msgs = ['ADIÓS', 'adiós', ' adiós ', 'ADIOS', 'adios', ' adios '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.LEAVE, language: languages.ES, payload: '', @@ -279,7 +279,7 @@ describe('parsing commands', () => { it('parses a REMOVE command (regardless of case or whitespace)', () => { const msgs = ['ELIMINAR', 'eliminar', ' eliminar '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.REMOVE, language: languages.ES, payload: '', @@ -288,7 +288,7 @@ describe('parsing commands', () => { }) it('parses the payload from an REMOVE command', () => { - expect(parseCommand('ELIMINAR foo')).to.eql({ + expect(parseExecutable('ELIMINAR foo')).to.eql({ command: commands.REMOVE, language: languages.ES, payload: 'foo', @@ -301,7 +301,7 @@ describe('parsing commands', () => { it('parses an RENAME command (regardless of case or whitespace)', () => { const msgs = ['RENOMBRAR', 'renombrar', ' renombrar '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RENAME, language: languages.ES, payload: '', @@ -311,7 +311,7 @@ describe('parsing commands', () => { }) it('parses the payload from an RENAME command', () => { - expect(parseCommand('RENOMBRAR foo')).to.eql({ + expect(parseExecutable('RENOMBRAR foo')).to.eql({ command: commands.RENAME, language: languages.ES, payload: 'foo', @@ -324,7 +324,7 @@ describe('parsing commands', () => { it('parses an RENAME command (regardless of case or whitespace)', () => { const msgs = ['RESPUESTAS ACTIVADAS', 'respuestas activadas', ' respuestas activadas '] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RESPONSES_ON, language: languages.ES, payload: '', @@ -343,7 +343,7 @@ describe('parsing commands', () => { ' respuestas desactivadas ', ] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.RESPONSES_OFF, language: languages.ES, payload: '', @@ -357,7 +357,7 @@ describe('parsing commands', () => { it('sets the language to Spanish regardless of language in which English is specified', () => { const msgs = ['ESPAÑOL', 'ESPANOL', 'SPANISH', 'español', 'espanol', 'spanish'] msgs.forEach(msg => - expect(parseCommand(msg)).to.eql({ + expect(parseExecutable(msg)).to.eql({ command: commands.SET_LANGUAGE, language: languages.ES, payload: '', diff --git a/test/unit/services/dispatcher/messages.spec.js b/test/unit/services/dispatcher/messages.spec.js index f2bc6e5..d6ecbbb 100644 --- a/test/unit/services/dispatcher/messages.spec.js +++ b/test/unit/services/dispatcher/messages.spec.js @@ -31,9 +31,8 @@ describe('messages module', () => { }) describe('for subscriber', () => { - it('shows publisher count and subscriber count', () => { + it('shows subscriber count', () => { const msg = cr.info.subscriber(channel) - expect(msg).to.include('admins: 2') expect(msg).to.include('subscribers: 2') }) }) diff --git a/test/unit/services/dispatcher/messenger.spec.js b/test/unit/services/dispatcher/messenger.spec.js index afb665d..df1f7c2 100644 --- a/test/unit/services/dispatcher/messenger.spec.js +++ b/test/unit/services/dispatcher/messenger.spec.js @@ -311,7 +311,7 @@ describe('messenger service', () => { describe('for a newly added publisher', () => { const newPublisher = genPhoneNumber() const sdMessage = `${commands.ADD} ${newPublisher}` - const response = messages.commandResponses.publisher.add.success(newPublisher) + const response = messages.commandResponses.add.success(newPublisher) const welcome = messages.notifications.welcome( publisherSender.phoneNumber, channel.phoneNumber, diff --git a/test/unit/services/dispatcher/strings.spec.js b/test/unit/services/dispatcher/strings.spec.js new file mode 100644 index 0000000..8f58539 --- /dev/null +++ b/test/unit/services/dispatcher/strings.spec.js @@ -0,0 +1,19 @@ +import { describe, it } from 'mocha' +import { expect } from 'chai' +import messagesEN from '../../../../app/services/dispatcher/strings/messages/EN' +import messagesES from '../../../../app/services/dispatcher/strings/messages/ES' + +describe('string translations', () => { + describe('for messages', () => { + it('has an ES string for every EN string', () => { + expect(messagesES.systemName).to.exist + Object.keys(messagesEN.commandResponses).forEach( + key => expect(messagesES.commandResponses[key]).to.exist, + ) + Object.keys(messagesEN.notifications).forEach( + key => expect(messagesES.notifications[key]).to.exist, + ) + Object.keys(messagesEN.prefixes).forEach(key => expect(messagesES.prefixes[key]).to.exist) + }) + }) +}) -- GitLab